在上一小节当中,查找第三方库用到一个新语法 find_package,这个语法往往被人误解,以为只要是找第三方库就可以用,但如果你看我第三章的那种方式构建库文件,你就无法用 find_package。
我们是官方的第三方库,我们可以用 find_package,因为人家已经整理好相关的文件到一个变量中,我们才可以非常方便简单设置几个参数值快速找到库文件。但如果说我们自己的或不规范的第三方库,即没提过规范的语法设置快速寻找,就只能先添加库文件的寻找路径,再一个一个寻找,这就是 find_library 命令。
总之,find_package 和 find_library 都可以用于在 CMake 中查找和链接库,但 find_package 更适用于具有CMake 配置文件的库,而 find_library 则适用于没有 CMake 配置文件的库。
find_package
典型用法
1 |
|
<PackageName> 是唯一的必选参数。
<version> 通常会被省略,如果没有软件包就无法成功配置项目,则应给出 REQUIRED。
一些更复杂的软件包支持组件,可以使用 COMPONENTS 关键字来选择组件,但大多数软件包都没有这种复杂程度。
1 |
|
搜索包的模式
Module 模式:在这种模式下,CMake 会搜索名为 Find<PackageName>.cmake
的文件,首先在 CMAKE_MODULE_PATH
指定的路径中查找,则在CMake安装目录(即CMAKE_ROOT变量)下的Modules目录下查找。找到文件后,CMake 会读取并处理它,负责查找包、检查版本,并生成任何必要的消息。
1 |
|
Config 模式:在这种模式下,CMake 会搜索名为 <lowercasePackageName>-config.cmake
或 <PackageName>Config.cmake
的文件。如果指定了版本信息,还会查找 <lowercasePackageName>-config-version.cmake
或 <PackageName>ConfigVersion.cmake
。Config 模式下,可以指定一个包名列表来搜索。CMake 搜索配置和版本文件的位置比 Module 模式复杂得多。
1 |
|
默认情况下是先 Module 模式,如果查找失败就采用 Config 模式。
OpenCV 是 Config 模式,见下:
如果想让CMake找到<PackageName>Config.cmake文件,需要在CMakeLists.txt中设置参数<PackageName>_DIR来设置路径。
比方说OpenCV的设置情况:
1 |
|
然后你接着去设置头文件路径、库文件路径,最后把库文件链接到可执行程序中
1 |
|
因此 find_package
并不是直接去找具体的动态库文件和头文件。而是去找包配置文件,这个配置文件里包含了包的具体信息,包括动态库文件的位置,头文件的目录,链接时需要开启的编译选项等等。
再者,不同的操作系统平台,CMake 都会有默认的搜索路径,再结合官方提供的CMake信息,以及你的 CMakeLists.txt 文件就能找到库文件。那如果你没有把这些库文件安装到 CMake 默认搜索路径呢?
默认的搜索路径
Windows 和 Linux 都有自己的标准路径,这里就以 Linux 作为探讨对象。
1 |
|
<prefix>
是变量${CMAKE_PREFIX_PATH}
,Unix 平台默认为/usr
。<name>
是你在find_package(<name> REQUIRED)
命令中指定的包名。<arch>
是系统的架构,例如x86_64-linux-gnu
或i386-linux-gnu
。- ( Ubuntu 喜欢把库文件套娃在
/usr/lib/x86_64-linux-gnu
目录下)
- ( Ubuntu 喜欢把库文件套娃在
例如你是 64 位的 Linux 系统,find_package(Qt5 REQUIRED)
会依次搜索:
1 |
|
非标准路径下的搜索
如果你没有在前面介绍的标准路径下,你在其他地方下载并编译安装了,也没有把库文件和头文件移动到标准路径中,那该怎么办?这时你需要手动指定一个变量告诉它在哪儿。我们依旧还是以 Linux 举例。
例如Qt5 安装到了/opt/Qt5.12.1
。 首先找到它里面的 Qt5Config.cmake
文件所在位置。假如你找到该文件的位置是 /opt/Qt5.12.1/lib/cmake/Qt5/Qt5Config.cmake
,那么请你设置变量 Qt5_DIR 为 /opt/Qt5.12.1/lib/cmake/Qt5
。有三种设置方法:
- 单次有效:在 configure 阶段,可以从命令行设置:
cmake -B build -DQt5_DIR="/opt/Qt5.12.1/lib/cmake/Qt5"
- 全局启用:修改你的
~/.bashrc
文件添加环境变量:export Qt5_DIR="/opt/Qt5.12.1/lib/cmake/Qt5"
,然后重启终端。这样以后你每次构建任何项目,find_package 都能自动找到这个路径的 Qt5 包了。 - 单项目有效:直接在你自己项目的 CMakeLists.txt 最开头写一行:
set(Qt5_DIR ""/opt/Qt5.12.1/lib/cmake/Qt5")
。但是一定要写在最前面。
只要不删除 build ,单次有效的方式就会一直存在,因为 CMake 会有缓存,但如果你删除 build 了,下次你还得再设置一次。
find_library
在 CMake 中,find_library
用于查找特定的库文件(如 .lib
、.a
、.so
等),并将该库的路径存储到变量中。它的功能类似于手动指定库文件路径,但通过 find_library
可以让 CMake 自动在系统的标准库路径或用户指定的路径中查找库。
1 |
|
<VAR>
: 将找到的库的完整路径存储到这个变量中。
name
: 要查找的库的名称,不需要后缀(如 .a
或 .so
)。
PATHS
: 可选,指定额外的搜索路径,CMake 会在这些路径中查找库。
如果库文件已经在标准路径中,无需指定。否则,需要通过 PATH 参数指定。
1 |
|
find_library(MYLIB_LIB NAMES mylib)
: 这是查找名为 mylib
的库文件,查找到的路径会存储在 MYLIB_LIB
变量中。
PATHS /usr/local/lib /opt/libs
: 在这些路径下查找库文件。如果没有指定 PATHS
,CMake 会默认查找系统标准的库路径,例如 /usr/lib
、/lib
等。
target_link_libraries(MyExecutable ${MYLIB_LIB})
: 如果找到了库文件,将其链接到目标 MyExecutable
。