cmake:pkg_check_modules

1059 篇文章 286 订阅

此文为:轻松入门cmake系列教程

理论

是什么?

pkg_check_modules是 CMake 自己的 pkg-config 模块的一个用来简化的封装:你不用再检查 CMake 的版本,加载合适的模块,检查是否被加载,等等,参数和传给 find_package 的一样:先是待返回变量的前缀,然后是包名(pkg-config 的)。这样就定义了<prefix>_INCLUDE_DIRS和其他的这类变量,后续的用法就与find_package一致。

工作原理

当安装某些库时(例如从RPM,deb或其他二进制包管理系统),会包括一个后缀名为 pc 的文件,它会放入某个文件夹下(依赖于系统设置,例如,Linux 为该库文件所在文件夹/lib/pkgconfig),并把该子文件夹加入pkg-config的环境变量PKG_CONFIG_PATH作为搜索路径。

pkg_check_modules实质上是检测系统中的 pkg-config 是否存在指定的 .pc 文件。

关于PKG_CONFIG_PATH

会在目录${PKG_CONFIG_PATH}寻找.pc文件

在环境变量中设置

执行echo $PKG_CONFIG_PATH

echo $PKG_CONFIG_PATH

在这里插入图片描述
解决:
1、查看自己的 pkgconfig 路径在哪里

find / -name pkgconfig

在这里插入图片描述
可以看出有三个,随意选择一个就可以

2、设置路径

export PKG_CONFIG_PATH=/usr/lib64/pkgconfig/:$PKG_CONFIG_PATH

在cmakelists.txt中设置

set(ENV{PKG_CONFIG_PATH}
  ${CMAKE_SOURCE_DIR}/libs/lib/pkgconfig:/opt/ffmpeg/lib/pkgconfig:$ENV{PKG_CONFIG_PATH})

what is the difference between find_package and pkg_search_module

  • pkg_search_module使用pkg-config工具确定请求的库的位置。这在已经使用pkg-config的系统上最有用,因此您不需要为CMake复制所有信息。请注意,此方法存在潜在的可移植性问题,因为它要求在构建计算机上正确设置pkg-config。

  • 另一方面,find_package是CMake自己解决相同问题的机制。为此,您可能需要一个用于请求的库的CMake查找脚本(CMake已经附带了其中的两个,但您可以轻松编写自己的脚本),或者是由请求的库本身提供的软件包配置脚本。无论哪种情况,您都可能需要调整CMAKE_MODULE_PATH才能使CMake能够找到相应的脚本。

使用哪种选择非常简单:

  • 如果库提供的话,优先选择软件包配置脚本。
  • 使用查找脚本作为不了解CMake的库的后备。
  • 如果要利用pkg-config的协同作用,请使用pkg_search_module。特别是,请注意,可以使用pkg_search_module来实现查找脚本,作为获取所需信息的一种方法。

使用示例

find_package(PkgConfig REQUIRED)

pkg_check_modules(LIBUV REQUIRED libuv)
set(NETDATA_COMMON_CFLAGS ${NETDATA_COMMON_CFLAGS} ${LIBUV_CFLAGS_OTHER})
set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} ${LIBUV_LIBRARIES})
set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${LIBUV_INCLUDE_DIRS})

前提:安装了libuv,并且将libuv.pc复制到了/usr/lib64/pkgconfig/路径下。否则出错: – Checking for module ‘libuv’
– No package ‘libuv’ found

官网翻译

官方文档

FindPkgConfig

CMake的pkg-config模块。

找到pkg-config可执行文件并添加pkg_get_variable()、pkg_check_modules()和pkg_search_module()命令。以下变量也将被设置:

  • PKG_CONFIG_FOUND:是否找到pkg-config可执行文件
  • PKG_CONFIG_EXECUTABLE:pkg-config程序的路径
  • PKG_CONFIG_VERSION_STRING:pkg-config版本(自CMake 2.8.8以来)

pkg_check_modules

检查所有给定的模块,在调用范围内设置各种结果变量

pkg_check_modules(<prefix>
                  [REQUIRED] [QUIET]
                  [NO_CMAKE_PATH]
                  [NO_CMAKE_ENVIRONMENT_PATH]
                  [IMPORTED_TARGET [GLOBAL]]
                  <moduleSpec> [<moduleSpec>...])

(0)<prefix>。举个例子

pkg_check_modules(SDL2 IMPORTED_TARGET  sdl2)
  • 意思是:
    • 我们要去默认路径下找叫做sdl2模块的库
    • 如果找到了,就生成一个叫做PkgConfig:SDL2的导入目标,这个目标可以直接用到target_link_libraries语句中
    • pkg_check_modules(....)执行完毕之后,会生成如下变量(SDL2就是<prefix>,可以自己起一个容易记住的名字,随便起):
SDL2_FOUND:如果模块存在,则设置为1
SDL2_LIBRARIES:只有库(没有“-l”)
SDL2_LINK_LIBRARIES:库及其绝对路径
SDL2_LIBRARY_DIRS:库的路径(没有“-L”)
SDL2_LDFLAGS:所有必需的链接器标志
.....
  • 然后,我们就可以这样利用了
pkg_check_modules(SDL2  IMPORTED_TARGET sdl2)
if (SDL2_FOUND)
        include_directories(${SDL2_INCLUDE_DIRS})
        link_directories(${SDL2_LIBRARY_DIRS})
        list(APPEND LINK_LIB_LIST ${SDL2_LIBRARIES})
        target_link_libraries(${PROJECT_NAME}  PkgConfig::SDL2)
        message(STATUS "found library:${SDL2_LIBRARIES}")
endif ()

再举个例子,如下:

pkg_check_modules(ffmpeg REQUIRED IMPORTED_TARGET libavcodec libavformat libavutil)
  • 去默认路径下,libavcodec libavformat libavutil这三个库,如果都找到了,那么,会生成如下变量:
ffmpeg_FOUND:如果模块存在,则设置为1
ffmpeg_LIBRARIES:只有库(没有“-l”)
......

(1) REQUIRED:可选。意为“必须”

  • 如果找不到模块,命令将失败并报错,并停止运行
  • 如果不选择,那么没有找到这个模块,那么就跳过

(2)QUIET:也是可选的。意为“安静”,当填写此参数,将会静默输出,不会打印任何信息
(3)NO_CMAKE_PATHNO_CMAKE_ENVIRONMENT_PATH,也是可选的

  • 默认情况下,CMAKE_PREFIX_PATH、CMAKE_FRAMEWORK_PATH和CMAKE_APPBUNDLE_PATH缓存和环境变量将被添加到pkg-config搜索路径。
  • 如果填写了这两个参数,NO_CMAKE_PATHNO_CMAKE_ENVIRONMENT_PATH参数就不去缓存路径和环境变量路径中搜索了

(4)[IMPORTED_TARGET [GLOBAL]]

  • IMPORTED_TARGET参数将创建一个名为PkgConfig::< prefix>的导入目标,该目标可以作为参数直接传递给target_link_libraries()。
  • GLOBAL参数将使导入的目标在全局作用域中可用。

(5)< moduleSpec >

  • 每个< moduleSpec >可以是裸模块名,也可以是带有版本约束的模块名(支持运算符=、<、>、<=和>=)。以下是具有各种约束的名为foo的模块的示例:
    • Foo匹配任何版本。
    • Foo <2只匹配2之前的版本。
    • Foo >=3.1匹配3.1或更高版本的任何版本。
    • Foo =1.2.3要求Foo必须是1.2.3版本。

(6)返回值
返回时可以设置以下变量。存在两组值:一组用于普通情况(< XXX > = < prefix>),另一组用于pkg-config在使用——static选项调用时提供的信息(< XXX > = < prefix>_STATIC)。

< XXX > _FOUND:如果模块存在,则设置为1
< XXX > _LIBRARIES:只有库(没有“-l”)
< XXX > _LINK_LIBRARIES:库及其绝对路径
< XXX > _LIBRARY_DIRS:库的路径(没有“-L”)
< XXX > _LDFLAGS:所有必需的链接器标志
< XXX > _LDFLAGS_OTHER:所有其他链接器标志
< XXX > _INCLUDE_DIRS:预处理器标记’-I’(没有’-I’)
< XXX > _CFLAGS:所有必需的cflags
< XXX > _CFLAGS_OTHER:其他编译器标志
< YYY > _VERSION:模块版本
< YYY > _PREFIX:模块的前缀目录
< YYY > _INCLUDEDIR:包含模块的目录
< YYY > _LIBDIR:模块的Lib目录

例子:

pkg_check_modules(ffmpeg REQUIRED IMPORTED_TARGET libavcodec libavformat libavutil)

target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::ffmpeg)

例子:

pkg_check_modules (GLIB2 glib-2.0)

查找任何版本的glib2。如果找到,输出变量GLIB2_VERSION将保存找到的实际版本。

pkg_check_modules (GLIB2 glib-2.0>=2.10)

查找glib2至少2.10版本。如果找到,输出变量GLIB2_VERSION将保存找到的实际版本。

pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0)

查找glib2-2.0(至少2.10版本)和gtk2±2.0的任何版本。只有当两者都被找到时,才会认为FOO被找到。FOO_glib-2.0_VERSION和FOO_gtk±2.0_VERSION变量将被设置为它们各自找到的模块版本。

pkg_check_modules (XRENDER REQUIRED xrender)

这句话的意思是“你可以去路径中找xrender这个库,任何版本都可以”。如果能够找到,那么就会设置宏XRENDER_LIBRARIES,XRENDER_STATIC_LIBRARIES。举个例子 :

XRENDER_LIBRARIES=Xrender;X11
XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp

pkg_search_module

此命令的行为与pkg_check_modules()相同,不同之处是它只搜索第一个成功匹配的模块,而不是检查所有指定的模块。

pkg_search_module(<prefix>
                  [REQUIRED] [QUIET]
                  [NO_CMAKE_PATH]
                  [NO_CMAKE_ENVIRONMENT_PATH]
                  [IMPORTED_TARGET [GLOBAL]]
                  <moduleSpec> [<moduleSpec>...])

3.16新版功能:如果找到一个模块,< prefix >_MODULE_NAME变量将包含匹配模块的名称。如果需要运行pkg_get_variable(),可以使用这个变量。

例子:

pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2)

pkg_get_variable

3.4新版功能。

检索pkg-config变量varName的值,并将其存储在调用范围内的结果变量resultVar中。

pkg_get_variable(<resultVar> <moduleName> <varName>)

如果pkg-config返回指定变量的多个值,resultVar将包含一个;-list。

例如:

pkg_get_variable(GI_GIRDIR gobject-introspection-1.0 girdir)
  • 11
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值