使用第三方库
官方文档:https://cmake.org/cmake/help/latest/index.html
find_package查找库
find_package查找库有两种方式,一种是module模式和config模式。
module模式
使用find_package()的 MODULE 参数指定
使用CMake 内置的或者⾃⼰写的 Find<PackageName>.cmake ⽂件查找。
适用于没有提供 CMake 配置⽂件的旧库。
config模式
使用find_package()的 CONFIG 参数指定
查找库⾃⾝提供的 CMake 配置⽂件(如 PackageNameConfig.cmake )。
适用于现代库(如 Boost、Qt, Curl)。
module模式:就是手动查找模式,早期没有使用cmake管理的项目,下游使用方自己编写查找脚本来完成库的使用。
config模式:现代cmake推荐的查找模式,由库的发布者 提供文件的定位以及使用信息,下游不需要手动编写脚本,直接使用上游定义好的导入目标,完成使用。
默认优先尝试config模式,失败后尝试module模式。可以使⽤ CONFIG 或 MODULE 参数强制指定模式。
module模式
执行步骤
1、查找模块文件
搜索FindMyPackageName.cmake ⽂件(这是自己编写的查找文件)
顺序: CMAKE_MODULE_PATH → CMake 内置模块(/usr/local/share/cmake/Modules/)
2、执行模块文件
查找库⽂件( find_library() )、查找头⽂件( find_path() )、检查版本( find_package_handle_standard_args() )、定义导⼊⽬标( add_library(... IMPORTED) )
3、设置输出变量
MyPackage_FOUND :是否找到包
MyPackage_INCLUDE_DIRS :头⽂件路径
MyPackage_LIBRARIES :库⽂件路径
MyPackage_VERSION :包版本
config模式
执行步骤
1、查找配置文件
搜索PackageNameConfig.cmake 或 <lower-case-package-name>-config.cmake
(这是库的发布者提供使用信息)
搜索路径: CMAKE_PREFIX_PATH → 标准系统路径(/usr/local/lib/cmake/)
2、执行配置文件
配置⽂件通常由包开发者提供,会:
定义导⼊⽬标(如 PackageName::PackageName)
设置依赖关系(头⽂件路径和库⽂件路径属性)
提供版本信息
包名大小写规范
包名区分大小写:例如 find_package(Boost) 和 find_package(boost) 可能指向不同的包。
官方推荐:⼤多数 CMake 内置模块(如 Boost、OpenCV、Threads)使⽤⼤写⾸字⺟。
包配置文件: ${PackageName}Config.cmake 或 ${PackageName}ConfigVersion.cmake ,其中 PackageName 通常为⼤写⾸字⺟(如 BoostConfig.cmake )。
查找模块: Find${PackageName}.cmake (如 FindBoost.cmake )。
特殊情况:某些包可能全部⼤写(如 CURL)或⼩写(如 protobuf),但这通常由包作者决定。
CTest
CTest是CMake的⼀个集成测试框架,⽤于⾃动化执⾏项⽬测试。⽀持多种测试类型(如单元测试、性 能测试),并能⽣成详细的测试报告。
核心函数
include(CTest)开启测试功能
add_test(NAME <name> COMMAND <command> [<arg>...] 可以运行多次,每一次都是添加一个测试的唯一标识符
参数解释
参数 | 含义 |
<name> | 测试的唯⼀标识符(在 CTest 中显⽰的名称) |
<command> | 要执⾏的命令(可执⾏⽂件、脚本或 CMake 命令) |
<arg> | 传递给命令的参数(可选)。 |
include(CTest) 应位于top-level source ⽬录中CMakeLists.txt中,因为 ctest(1) 希望在 top-level-build ⽬录中找到测试⽂件,⽽且必须位于任何add_test命令之前,不然添加的命令不会被ctest 收集到。
CTest使用
下面是当前的文件目录结构
main.cpp中的内容如下
#include <iostream>
#include "math/math.h"
#include <cassert>int main()
{// 测试加法assert(add(2, 3) == 5); // 测试减法assert(sub(2, 3) == -1);std::cout << "Test OK" << std::endl;return 0;
}
CMakeLists.txt内容如下
cmake_minimum_required(VERSION 3.27.4)project(TestMaMathLANGUAGES CXX
)# 1、开启测试功能
include(CTest)
# 2、添加测试执行文件
add_executable(main main.cpp)
# 3、查找MyMath库
find_package(MyMath CONFIG REQUIRED)
# 4、链接MyMath库
target_link_libraries(main PRIVATE MyMath::MyMath)
# 5、添加测试Case到CTest
add_test(NAME TestMyMathCOMMAND main
)
使用cmake运行如下。首先进行构建,编译,再执行ctest。
可以看见ctest通过。然后再将main.cpp中的文件进行修改如下。
#include <iostream>
#include "math/math.h"
#include <cassert>int main()
{// 测试加法assert(add(2, 3) == 6); // 测试减法assert(sub(2, 3) == -1);std::cout << "Test OK" << std::endl;return 0;
}
再次执行编译和ctest命令
可以看见出错了。其中红框标识着错误的日志。按住ctrl再点击便能进入查看错误日志。
CPack
使用CPack 来打包发布我们⽣成的⼆进制,库⽂件等。CPack 是 CMake 的打包⼯具, ⽤于将 CMake 构建的项⽬打包成各种分发格式(如 DEB、RPM、ZIP、MSI 等)。它能⾃动收集可执 ⾏⽂件、库、配置⽂件和⽂档,并⽣成符合平台规范的安装包,极⼤简化了软件分发流程。
cpack核心功能
1、自动收集⽂件:基于 CMake 的 install() 指令,⾃动收集需要打包的⽂件。
2、多格式⽀持:⽀持⽣成跨平台的包格式(如 DEB、RPM、ZIP、MSI、DMG 等)。
3、依赖管理:可配置依赖关系(如系统库、运⾏时环境)。
4、自定义安装逻辑:⽀持预安装、后安装脚本。
5、版本控制:⾃动包含版本号、发布信息等元数据。
CPack使用
当前的一个目录结构如下
顶级CMakeLists.txt内容如下
# 1、设置最低版本号
cmake_minimum_required(VERSION 3.27.4)
# 2、设置项目名称
project(TestMyMath)
# 3、添加目录层级
add_subdirectory(my_lib)
add_subdirectory(app)# 4、开启打包功能
include(CPack)
set(CPACK_PACKAGE_NAME "MyApp")
set(CPACK_PACKAGE_VERSION "1.2.3")
set(CPACK_GENERATOR "TGZ")
在顶级CMakeLists.txt中需要完成开启打包功能,设置打包格式等的作用。
my_lib中的CMakeLists.txt内容如下(库的制作方)
# 1、收集库的源代码
#将src目录下的所有cpp文件添加到SRC_LISTS变量中
file(GLOB SRC_LISTS "src/*.cpp")# 2、添加构建目标
#将SRC_LISTS变量中的文件构建动态库MyMath
add_library(MyMath SHARED ${SRC_LISTS})# 3、设置库的使用要求
# 实际上是告诉使用方头文件的位置
target_include_directories(MyMath PUBLIC# 这里的属性设置使用的是生成器表达式"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>""$<INSTALL_INTERFACE:include>"
)# 4、修改默认的输出路径
set_target_properties(MyMath PROPERTIESARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/libLIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)# 5、添加 -fPIC 编译选项
target_compile_options(MyMath PRIVATE "-fPIC") #-fPIC全称为Position Independent Code,即位置无关代码,# 6、安装库文件
install(TARGETS MyMath)# 7、安装头文件
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/includeDESTINATION includeFILES_MATCHING PATTERN "*.h"
)
作为库的制作方,设置好构建目录和安装目录下的头文件搜索路径,作为下游使用。
并且使用install将目标安装起来(头文件和库文件)
app中的CMakeLists.txt内容(库的使用方)
# 1、搜集文件列表
file(GLOB SRC_LISTS "*.cpp")
# 2、添加构建目标
add_executable(main ${SRC_LISTS})# 3、添加依赖库列表
# 这里是指定链接时的库,这样链接器才能找到库中定义,完成重定位
target_link_libraries(main PRIVATE MyMath)# 4、修改默认的输出路径
set_target_properties(main PROPERTIESRUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin#设置运行时搜索路径,在二进制可执行程序运行的时候INSTALL_RPATH "$ORIGIN/../lib" # 这里的ORIGIN是当前可执行文件的绝对路径,可以理解为设置rpath
)# 5、打印库文件相对main的相对路径 自动定义命令
add_custom_command(TARGET mainPOST_BUILDCOMMAND ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:MyMath>"COMMENT "输出动态库的全路径"
)# 6、安装二进制main
install(TARGETS main)
作为使用方需要设置运行时可执行文件搜索路径,头文件使用的相对路径,和rpath路径。再安装二进制程序。