C++-Cmake指令:find_package【用于查找包(通常是使用三方库)】【指定第三方库所在路径】
一、搜索模式
find_package
用于查找包(通常是使用三方库),并返回关于包的细节(使用包所依赖的头文件、库文件、编译选项、链接选项等)
与find_libaray直接在指定搜索目录下搜索库不同,find_package
命令可以获取更多的信息,那么它的搜索方式也是与find_libaray
不一样,它有两种不同的搜索方式,因此在介绍这个命令的细节之前,先简单介绍一下find_package
命令的两种搜索模式:模块模式(Module mode
)和配置模式(Config mode
)。
1.1 模块模式(Module mode
)
在该模式下,Cmake
会搜索一个名为Find<PackageName>.cmake
的文件,其中<PackageName>
为待搜索包的名称。
搜索路径的顺序依次是:
- 从变量
CMAKE_MODULE_PATH
指定的路径中进行查找 - 从
Cmake
安装路径中查找。Cmake
会在其安装路径下提供很多.cmake
文件,例如/XXX/cmake/Modules/
目录下(不同的系统安装目录可能不一致)
如果找到文件Find<PackageName>.cmake
,Cmake
会读取并处理该文件,简而言之,它负责检查一些条件(如版本号是否满足等)是否满足,并在找到包后,返回给调用者一些变量,用以获取包的详细信息。
一般来说,Find<PackageName>.cmake
文件不是随包本身一起提供的,更多的是外部针对已有包的重新包装,例如操作系统、Cmake
程序、甚至是调用find_package
命令的工程针对已有的包提供针对该包的.cmake
文件。
1.2 配置模式(Config mode
)
该模式下,CMake
会搜索<lowercasePackageName>-config.cmake
文件或<PackageName>Config.cmake
文件。如果find_package
命令中指定了具体的版本,也会搜索<lowercasePackageName>-config-version.cmake
或<PackageName>ConfigVersion.cmake
文件,因此配置模式下通常会提供配置文件和版本文件(注意形式上要保持一致),并且作为包的一部分一起提供给使用者。
该模式下对.cmake
文件的搜索路径的顺序比较复杂,具体见本文的4.1
节。
.cmake
后缀文件的作用是什么?
find_package
的两种搜索模式都会按照一定规则从路径下搜索.cmake
后缀的文件,两种模式下的.cmake
文件作用都是为了给find_package
命令的调用方返回有关包的信息(头文件路径、库文件路径、编译连接选项、版本信息等等)
二、命令格式
find_package
命令有两种格式,基本命令格式和完整命令格式。
2.1 基本命令
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
几个重要的参数介绍:
PackageName
:待查找包的名称。此外它还决定两种搜索模下的.cmake
文件名称:例如模块模式下的名称为Find<PackageName>.cmake
,而配置模式下为<lowercasePackageName>-config.cmake
/<lowercasePackageName>-config-version.cmake
。MODULE
:该选项指定find_package
命令只使用模块模式
搜索方式查找。未指定该选项时,find_package
会优先使用模块模式
搜索,仍未找到包时,会切换成配置模式
搜索。version
:待查找包的版本号要求,版本号为点分格式,由四个部分组成,每个部分都是一个数字,均为可选:major[.minor[.patch[.tweak]]]
,例如1.1.1.1
、1.0
、等。同样也可以指定版本范围(CMake 3.19
及之后才支持),格式为:versionMin...[<]versionMax
,versionMin
和versionMax
均是major[.minor[.patch[.tweak]]]
形式的版本号,默认情况下会包含这个指定区间两端的版本号,但如果指定了<
,那么会排除掉versionMax
,例如1.1.1.1...1.1.2.0
、1.1.1.1...<1.1.2.0
等。EXACT
:该选项要求待查找包的版本必须与指定的版本精确匹配,因此如果指定的是一个版本范围,不能使用该参数。QUIET
:禁止输出信息,正常情况当找到包时,CMake
会打印一些信息,指定该选项时会禁止掉这些打印。例外是当同时指定QUIET
时,如果找不到包,仍然会输出错误信息并终止执行过程。REQUIRED
:当未找到满足条件的包(例如版本号不匹配,或指定组件未找到等),会终止CMake
的执行过程,并输出一条错误信息。如果未指定该选项,即使未找到满足条件的包,CMake
的执行过程也会继续。COMPONENTS
:指定要查找的组件。通常一个包可能包含多个组件(可以理解为多个库,例如把C++的std看成一个包的概念,那么vector就是std下的其中一个组件),我们的工程可能会依赖包下的具体某个组件,因此可以通过这个选项来检测这些组件是否存在。通常的约定是,该选项后的组件应该都找到时才认为包找到,否则认为未找到满足条件的包。这个约束会依赖包的.cmake
来实现,通过find_package
命令传入的COMPONENTS
可以通过<PackName>_FIND_COMPONENTS
这个变量来获得。举个简单的例子:# mymathConfig.cmake,假定它位于./mymath/mymath目录下 # 作用就是校验COMPONENTS是否是test,只有当COMPONENTS为空或者为test时,包mymath才会被找到 message(${mymath_FIND_COMPONENTS}) # `find_package`命令的`COMPONENTS`传入的 if(${mymath_FIND_COMPONENTS} STREQUAL "") message("Empty comps.") set(mymath_INCLUDE_DIR "/XXX/mymath") set(mymath_LIBRARY "/XXX/mymath/libmymath.a") else() foreach(comp ${mymath_FIND_COMPONENTS}) if (comp MATCHES "test") message("Find comp test") set(mymath_INCLUDE_DIR "/XXX/mymath") set(mymath_LIBRARY "/XXX/mymath/libmymath.a") endif() endforeach() endif()
# 顶层目录的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(find_package_test) find_package(mymath CONFIG REQUIRED COMPONENTS test PATHS ./mymath/mymath ) if(mymath_FOUND) message("Find mymath: ${mymath_INCLUDE_DIR}; ${mymath_LIBRARY};") endif()
# 执行cmake . cmake . # 输出为 test Find comp test Find mymath: /XXX/mymath; /XXX/mymath/libmymath.a;
OPTIONAL_COMPONENTS
:与COMPONENTS
的区别是,不强制要求这些组件必须存在。不影响CMake
的执行。
2.2 完整命令
find_package(<PackageName> [version] [EXACT] [QUIET]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[CONFIG|NO_MODULE]
[NO_POLICY_SCOPE]
[NAMES name1 [name2 ...]]
[CONFIGS config1 [config2 ...]]
[HINTS path1 [path2 ... ]]
[PATHS path1 [path2 ... ]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[NO_DEFAULT_PATH]
[NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_PACKAGE_REGISTRY]
[NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
[NO_CMAKE_SYSTEM_PATH]
[NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH])
这里介绍一下与基本命令有差异的地方:
CONFIG|NO_MODULE
:这两个选项二选一即可,表示强制find_package
命令使用配置模式
搜索,忽略模块模式
搜索。NAMES
:默认情况下find_package
命令会查找名为<PackageName>
的包。如果NAMES
选项后指定了名称,则会使用这些名字来查找包而忽略<PackageName>
参数。PATHS
/HINTS
:配置模式下指定.cmake
文件的搜索路径。NO_XXX_PATH
:配置模式下忽略指定的路径,具体的含义可以参考4.1.2
节。
相关文章
- C/C++vsnprintf用法(要配合va_list使用)
- c++程序猿经典面试题(2)
- C++根据图片url下载图片
- 利用OpenCV的函数Rect()提取感兴趣区域的C++代码
- MATLAB、C++、OpenCV、Python、Python-Numpy近似值(取整)求取函数总结【round()、ceil()、floor()、fix()】
- C++中函数调用的整个过程内存堆栈分配详解
- C#与 C++数据结构类型对应关系表
- C++11特性:decltype关键字
- 《C++编程风格(修订版)》——2.3 物理状态的一致性
- 《好学的C++程序设计》——第1章 概论
- 基于C++实现(控制台)图书信息管理系统【100010609】
- 基于C++实现(控制台)职工管理管理系统【100010547】
- C/C++中的一些关键字理解
- 蓝桥杯省赛(填空题)— 路径 SPFA算法(C++)
- 148、【动态规划】leetcode ——63. 不同路径 II:递归法+迭代法(C++版本)
- 浅谈C++ STL string容器