当前位置: 首页 > news >正文

使用 Modern CMake 构建现代 C++ 项目:target从入门到实践

CMake 是 C++ 项目中最主流的构建系统之一,而随着 CMake 3.x ,4.x的发展,Modern CMake(现代 CMake)已成为推荐的最佳实践。

本篇文章将用通俗易懂的方式,带你从头理解并实践 Modern CMake 的核心理念,包括 target_* 系列命令、文件组织、安装与打包、测试下游项目、以及 CMakePresets 的使用。


一、Modern CMake 的核心思想

传统 CMake 中常用的 include_directories()add_definitions()file(GLOB ...) 等方式,容易带来依赖混乱。

Modern CMake 提倡:一切都通过 target 管理

核心原则是:

  • 每个库/程序用一个 add_library()add_executable() 创建 target
  • 使用 target_sources()target_include_directories()target_link_libraries() 配置 target 的行为
  • 避免全局变量,改用 target 作用域

二、目录结构设计

一个清晰的目录结构是 Modern CMake 的第一步:

foo_project/
├── CMakeLists.txt
├── include/
│   └── foo/
│       └── foo.h
├── src/
│   └── foo.cpp
├── test_app/
│   ├── main.cpp
│   └── CMakeLists.txt
├── CMakePresets.json
└── fooConfig.cmake.in
  • include/foo/foo.h:公共头文件
  • src/foo.cpp:实现文件
  • test_app/:测试程序

三、使用 target_sources 管理源码

Modern CMake 中推荐使用 target_sources() 明确地将头文件和源文件加入库:

add_library(foo)  # 创建目标 footarget_sources(fooPUBLICFILE_SET foo_headers TYPE HEADERS         # 定义一个文件集用于安装头文件BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includeFILES ${CMAKE_CURRENT_SOURCE_DIR}/include/foo/foo.hPRIVATE${CMAKE_CURRENT_SOURCE_DIR}/src/foo.cpp   # 私有源文件不被安装
)

这不仅清晰地标明了头文件和源文件的作用域,还能与 install() 一起自动安装。


四、安装与导出库

使用 install() 命令,可以将构建好的库、头文件和 CMake 配置文件安装到系统或本地目录中。

install(TARGETS fooEXPORT fooTargets                           # 导出 target 定义供下游使用FILE_SET foo_headers DESTINATION include    # 安装头文件到 include/LIBRARY DESTINATION lib                     # 安装 .so 动态库ARCHIVE DESTINATION lib                     # 安装 .a 静态库
)install(EXPORT fooTargets                     # 安装导出文件FILE fooTargets.cmakeNAMESPACE foo::                             # 添加命名空间,使用 foo::fooDESTINATION lib/cmake/foo
)configure_package_config_file(fooConfig.cmake.in${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmakeINSTALL_DESTINATION lib/cmake/foo
)install(FILES${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmakeDESTINATION lib/cmake/foo
)

这样,其他项目就可以使用 find_package(foo) 来链接你的库了。


五、CMakePresets.json 的使用

CMakePresets.json 是 CMake 3.19+ 引入的新功能,可以统一预设构建参数:

{"version": 3,"configurePresets": [{"name": "release","generator": "Unix Makefiles","binaryDir": "${sourceDir}/build","cacheVariables": {"CMAKE_BUILD_TYPE": "Release","CMAKE_INSTALL_PREFIX": "${sourceDir}/install"}}],"buildPresets": [{ "name": "release", "configurePreset": "release" }]
}

使用方式非常简单:

cmake --preset=release                # 配置构建目录
cmake --build --preset=release       # 构建项目
cmake --install build                # 安装到 install/ 目录

实际终端输出如下所示:

$ cmake --preset=release
-- The CXX compiler identification is GNU 10.2.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /.../foo_project/build$ cmake --build --preset=release
[ 50%] Building CXX object CMakeFiles/foo.dir/src/foo.cpp.o
[100%] Linking CXX static library libfoo.a
[100%] Built target foo$ cmake --install build
-- Install configuration: "Release"
-- Installing: /.../foo_project/install/lib/libfoo.a
-- Installing: /.../foo_project/install/include/foo/foo.h
-- Installing: /.../foo_project/install/lib/cmake/foo/fooTargets.cmake
-- Installing: /.../foo_project/install/lib/cmake/foo/fooTargets-release.cmake
-- Installing: /.../foo_project/install/lib/cmake/foo/fooConfig.cmake

六、测试下游项目

在项目根目录下我们还设置了一个 test_app/ 目录,用于模拟一个使用 foo 库的下游项目。

// test_app/main.cpp
#include <foo/foo.h>int main() {foo::say_hello();return 0;
}
# test_app/CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(test_app)find_package(foo REQUIRED PATHS ../install/lib/cmake/foo)  # 查找安装后的包add_executable(test_app main.cpp)
target_link_libraries(test_app PRIVATE foo::foo)  # 链接目标

构建和运行:

$ cmake -B build -DCMAKE_PREFIX_PATH=../install
-- The CXX compiler identification is GNU 10.2.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /.../test_app/build$ cmake --build build
[ 50%] Building CXX object CMakeFiles/test_app.dir/main.cpp.o
[100%] Linking CXX executable test_app
[100%] Built target test_app$ ./build/test_app
Hello from foo!

说明 foo 库已经成功安装并被下游项目引用。


七、安装生成的配置文件说明

安装完成后你会得到:

install/lib/cmake/foo/
├── fooConfig.cmake
├── fooTargets.cmake
└── fooTargets-release.cmake

这些文件让其他项目通过 find_package(foo REQUIRED PATHS ./install/lib/cmake/foo) 使用 foo::foo 目标,无需写死路径。

它们的作用分别是:

文件作用
fooConfig.cmake包配置入口文件,供 find_package() 加载
fooTargets.cmake定义导出的目标及其依赖
fooTargets-release.cmake定义 release 模式下库文件路径

八、总结

功能Modern CMake 命令说明
添加源码add_library() + target_sources()创建目标并声明源文件和头文件
设置包含路径target_include_directories()设置头文件查找路径
链接库target_link_libraries()连接依赖库
安装头文件install(FILE_SET ...)安装头文件并保持目录结构
导出配置install(EXPORT ...)安装 target 定义供 find_package() 使用
包配置文件configure_package_config_file()生成并安装 Config.cmake 供下游使用
使用 preset 构建cmake --preset=...快速构建统一配置
测试下游项目find_package() + target_link验证库是否被成功引用

通过 Modern CMake,构建脚本更可维护、更易复用、更标准化。

下一步,你可以尝试将自己的项目改造成 Modern CMake 风格,或基于本文的结构构建可复用的 C++ SDK。


📌 如需完整示例项目打包文件、测试程序或跨平台支持配置,欢迎留言交流!

相关文章:

  • RK3568下QT实现输入框支持虚拟键盘
  • PYTHON训练营DAY26
  • 《Navicat之外的新选择:实测支持国产数据库的SQLynx核心功能解析》
  • 深入理解JavaScript中的闭包:原理、应用与常见问题
  • Web3.0:互联网的去中心化未来
  • 2505C++,py和go调用雅兰亭库的协程工具
  • 【向量模型 + HNSW 参数如何选择】
  • S7-1500 与 IM60 进行 PROFINET 通信
  • LeetCode LCR 015. 找到字符串中所有字母异位词 (Java)
  • 【重磅】配电网智能软开关和储能联合规划
  • ZFile与Cpolar技术结合实现远程数据实时访问与集中管理的可行性分析
  • 2025认证杯数学建模第二阶段C题:化工厂生产流程的预测和控制,思路+模型+代码
  • 计算图存储采用矩阵吗,和张量关系
  • 有什么工地现场施工进度成本管理软件?工程企业数字化转型的必要性?
  • 【滑动窗口】串联所有单词的子串
  • 图片、音频、视频都能转?简鹿格式工厂了解一下
  • 深入理解 Cortex-M 的中断输入和挂起行为
  • 网络爬虫学习之httpx的使用
  • 增强 HTNN 服务网格功能:基于 Istio 的BasicAuth 与 ACL 插件开发实战
  • 【js】JavaScript的变量提升、函数声明提升
  • 上海率先推进生物制品分段生产试点,这款国产1类创新药获批上市
  • 车建兴被留置:跌落的前常州首富和红星系重整迷路
  • 澳大利亚首例“漂绿”诉讼开庭:能源巨头因“碳中和”承诺遭起诉
  • 泽连斯基抵达安卡拉,称乌将派出最高级别代表团参与谈判
  • 商务部:今年前3月自贸试验区进出口总额达2万亿元
  • 秦洪看盘|缩量回踩,积蓄叩关能量