CMake I 细谈find_package函数

目录

一、find_package语法

二、find_package两种模式

1.Module模式

2.Config模式

【扩展】pkg-config

三、问题汇总

1.找不到.h文件

四、参考文档


一、find_package语法

find_package(<PackageName> [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两种模式

        find_package()有Module模式和Config模式,cmake默认采取Module模式,如果Module模式未找到库,才会采取Config模式。

1.Module模式

        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模块都会定义以下几个变量:

  • <LibaryName>_FOUND:用来判断FindXXX.cmake模块是否被找到;
  • <LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES;
  • <LibaryName>_LIBRARY or <LibaryName>_LIBRARIES;

2.Config模式

        默认情况下,如果Module模式搜索失败,没有找到对应的FindXXX.cmake文件,则转入Config模式(配置模式)进行搜索。当然,如果显示指定CONFIG或者NO_MODULE,那就会直接走Config模式。

        Config模式主要通过XXXConfig.cmakeXXX-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.cmakeXXX-config.cmake文件信息,那么CMake将会直接无视它,然后重新开始查找。

【扩展】pkg-config

        如果某个依赖项既不提供查找模块,也不提供供应商打包的CMake文件,该怎么办?在这种情况下,我们只有两个选择:

  • 依赖 pkg-config 程序,来找到系统上的包。这依赖于包供应商在 .pc 配置文件中,其中有关于发行包的元数据。
  • 为依赖项编写自己的 find-package 模块。

        当找到 pkg-config 时, CMake需要提供两个函数,来封装这个程序提供的功能:

  • pkg_check_modules ,查找传递列表中的所有模块(库和/或程序)。
  • pkg_search_module ,要在传递的列表中找到第一个工作模块 与 find_package 一样,这些函数接受 REQUIRED 和 QUIET 参数。
pkg_search_module(<prefix>
                  [REQUIRED] [QUIET]
                  [NO_CMAKE_PATH]
                  [NO_CMAKE_ENVIRONMENT_PATH]
                  [IMPORTED_TARGET [GLOBAL]]
                  <moduleSpec> [<moduleSpec>...])
  • 第一个参数是前缀,它将用于命名存储搜索xxx库结果的目标: PkgConfig::xxx
  • IMPORTED_TARGET参数将创建一个名为PkgConfig::<prefix>的导入目标,该目标可以作为参数直接传递给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 模块。

三、问题汇总

1.找不到.h文件

解决办法:设置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)

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值