目录
一、find_package语法
二、find_package两种模式
1.Module模式
2.Config模式
【扩展】pkg-config
三、问题汇总
1.找不到.h文件
四、参考文档
find_package( [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
version |
需要一个版本号,它是正在查找的包应该兼容的版本号(格式是major[.minor[.patch[.tweak]]]) |
EXACT | 要求版本号必须精确匹配 |
QUIET | 会禁掉包没有被发现时的警告信息。对应于FindXXX.cmake模块中的 NAME_FIND_QUIETLY |
REQUIRED | 其含义是指是否是工程必须的,表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。对应于FindXXX.cmake模块中的 NAME_FIND_REQUIRED 变量。 |
COMPONENTS | 在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在它们的后面可以列出一些与包相关(依赖)的部件清单(components list) |
find_package()有Module模式和Config模式,cmake默认采取Module模式,如果Module模式未找到库,才会采取Config模式。
Module模式(模块模式)下是要查找到名为FindXXX.cmake的文件。这个文件负责找到库所在的路径,为我们的项目引入头文件路径和库文件路径。cmake搜索这个文件的路径有两个,一个是cmake安装目录下的Modules目录(如D:\soft\CMake\share\cmake-3.21\Modules),另一个使我们指定的CMAKE_MODULE_PATH的所在目录。
#以Eigen3库为例(在cmake下自带FindEigen3.cmake文件):
set(CMAKE_MODULE_PATH "D:/thirdParties/eigen-3.4.0/eigen-3.4.0/cmake/")
set(EIGEN3_INCLUDE_DIR "D:/thirdParties/eigen-3.4.0/eigen-3.4.0")#windows端需要指定,否则路径会报找不到头文件
find_package(Eigen3 3.4.0 REQUIRED )
每一个FindXXX.cmake模块都会定义以下几个变量:
默认情况下,如果Module模式搜索失败,没有找到对应的FindXXX.cmake文件,则转入Config模式(配置模式)进行搜索。当然,如果显示指定CONFIG或者NO_MODULE,那就会直接走Config模式。
Config模式主要通过XXXConfig.cmake或XXX-config.cmake 这两个文件来引入我们需要的库(它们是假定库会安装的文件,但是目前还没有多少库会安装它们)。包含XXXConfig.cmake文件的路径会被存储在一个名为XXX_DIR的cache条目里。
以Eigen3库为例,在我们通过cmake .. 配置之后,它在配置目录下生成了Eigen3Config.cmake文件。当然我们可以定义XXX_DIR(Eigen3_DIR)变量,find_package最优先到这个目录下查询XXXConfig.cmake文件。(题外话:Eigen3库在windows端安装时需要用管理员权限调起VS,在VS中生成Install,必要的文件被复制到由CMAKE_INSTALL_PREFIX指定的输出目的地,如C:/Program Files (x86)/Eigen3 )
set(Eigen3_DIR "D:/thirdParties/eigen-3.4.0/eigen-3.4.0/build")
find_package(Eigen3 3.4.0 REQUIRED CONFIG)
如果设置了XXX_DIR变量,但是它没有包含XXXConfig.cmake或XXX-config.cmake文件信息,那么CMake将会直接无视它,然后重新开始查找。
如果某个依赖项既不提供查找模块,也不提供供应商打包的CMake文件,该怎么办?在这种情况下,我们只有两个选择:
当找到 pkg-config 时, CMake需要提供两个函数,来封装这个程序提供的功能:
- pkg_check_modules ,查找传递列表中的所有模块(库和/或程序)。
- pkg_search_module ,要在传递的列表中找到第一个工作模块 与 find_package 一样,这些函数接受 REQUIRED 和 QUIET 参数。
pkg_search_module(
[REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [IMPORTED_TARGET [GLOBAL]] [ ...])
- 第一个参数是前缀,它将用于命名存储搜索xxx库结果的目标: PkgConfig::xxx
- IMPORTED_TARGET参数将创建一个名为PkgConfig::
的导入目标,该目标可以作为参数直接传递给target_link_libraries()。
#使用CMake附带的find-module,查找 pkg-config 。这里在 find_package 中传递了 QUIET 参数。只有在没有找到 pkg-config 时,CMake才会报错:
find_package(PkgConfig REQUIRED QUIET)
#找到 pkg-config 时,我们将使用 pkg_search_module 函数,以搜索任何附带包配置 .pc 文件的库或程序。该示例中,我们查找ZeroMQ库:
pkg_search_module(
ZeroMQ
REQUIRED
libzeromq libzmq lib0mq
IMPORTED_TARGET
)
#如果找到ZeroMQ库,则打印状态消息
if(TARGET PkgConfig::ZeroMQ)
message(STATUS "Found ZeroMQ")
endif()
有四种方式可用于找到依赖包:
1. Config模式:使用由包供应商提供CMake文件XXXConfig.cmake,通常会在包的标准安装位置查找。
2. Module模式:无论是由CMake还是第三方提供的模块,为所需包使用 find-module 。
3. 使用 pkg-config(通常是在POSIX系统:Linux,MacOS等使用)。
4. 编写自己的 find 模块。
解决办法:设置XXX_INCLUDE_DIR
1.find_package与CMake如何查找链接库详解_bytxl的专栏-CSDN博客_find_package
2.find_package — CMake 3.21.4 Documentation
3.cmake find_package路径详解 - 知乎 (zhihu.com)