现代 CMake 简明教程(一)- CMake 基础 (转载)
系列文章目录
文章目录
前言
用 CMake 来构建 C/C++ 项目是业内的主流做法。最近,我们的项目代码做了一些拆分和合并:引入其他仓库代码,并且将公共部分拆分以供多个仓库同时使用。为此,就得修改项目中的 CMake 以满足需求。
在做这件事情时,过程是相当痛苦的,修改的难度超过了我的预期。这份痛苦的回忆,让我陷入了沉思:这 CMake 咋这么不好使,是我的使用姿势不对吗?CMake 的最佳实践是啥?
在经过一番搜索和学习,我开始了解 Modern CMake 的一些用法与理念,它主张放弃传统的基于变量的方法,而采用基于 target 的结构化模式,使其成为一个更可维护、更直观、更易集成、更具意义的方案。
在这里对自己的学习做一个总结,主要内容包括:
- 介绍 Modern CMake 的基础语法与工具,让你对 CMake 能做些啥有更清楚的认识
- 介绍 Modern CMake 理念与最佳实践,并给出具体实例
CMake基础
这部分内容是 An Introduction to Modern CMake 的总结,并不会讲的非常详细,希望通过几句话来高度总结各个用法,旨在了解 CMake 有哪能力,如果对某些部分感兴趣请大家自行查阅具体内容。
1. Modern CMake 介绍
- 为什么需要一个好的构建系统?如果你有以下需求,那么使用 CMake 可以从中获益
- 你想避免硬编码路径
- 你需要在多台电脑上建立一个软件包。
- 你想使用CI(持续集成)。
- 你需要支持不同的操作系统(甚至可能只是Unix的不同版本)。
- 你想支持多个编译器
- 你想使用IDE,但也许并不是所有时间都想使用。
- 你想要更好地组织程序的结构
- 你想使用别人的库
- 你想使用工具,比如Clang-Tidy,来帮助你编写代码。
- 你想使用调试器
- 为什么一定是 CMake?其他工具不行吗?
- 各个 IDE 都支持 CMake,使用 CMake 可以有更大程度的方便, save you life
- 目前很多 C/C++ 开源项目都在使用 CMake,通过 find CMake 或者 CMake config 很容易将它们集成至你的项目中
- 使用 CMake 来管理发布,让别人更容易使用你的库
- 更多理由请参考 19 reasons why CMake is actually awesome
- 为什么要用现代 CMake?
- 通常认为 3.1+ 版本是现代 CMake。CMake 是向下兼容的,可以放心使用
- 至少应该使用你的编译器出来之后的 CMake 版本,因为它需要知道该版本的编译标志等等
- 高版本 CMake 有更多特性,可以节省数百行和数小时的 CMakeLists.txt 编写工作,长运来看更容易维护
安装 CMake
略,请参考原文
运行 CMake
- 经典用法
~/package $ mkdir build
~/package $ cd build
~/package/build $ cmake ..
~/package/build $ make
- 新版本可以简单一点
~/package $ cmake -S . -B build
~/package $ cmake --build build
- 安装命令
#From the build directory (pick one)
~/package/build $ make install
~/package/build $ cmake --build . --target install
~/package/build $ cmake --install . # CMake 3.15+ only
#From the source directory (pick one)
~/package $ cmake --build build --target install
~/package $ cmake --install build # CMake 3.15+ only
- 推荐使用
--build
用法
- 通过
-v
显示执行的构建命令:cmake --build build -v
- 通过
--target
来选择目标:cmake --build --target install
- 设置
CC
和CXX
环境变量来选择 C/C++ 编译器
~/package/build $ CC=clang CXX=clang++ cmake ..
- 选择不同的工具进行构建
- make 通常是默认的,通过 cmake --help 查看支持的构建器
cmake -G"My Tool"
设置构建器,例如cmake -S . -B buildXcode -G"Xcode"
- 通过
-D
来设置选项,例如cmake -S . -B build -DCMAKE_INSTALL_PREFIX=dist
--trace
打印 CMake configure 阶段的输出,例如cmake -S . -B build --trace
CMake 行为准则(Do's and Don'ts)
- CMake 应避免的行为(CMake Antipatterns)
- 不要使用全局函数,例如
link_directories
,include_libraries
,add_definitions
等,请你忘记它们 - 不要滥用
PUBLIC
,除非有依赖传递,否则请你使用PRIVATE
替换PUBLIC
- 不要使用
GLOB
来添加文件
如果不重新运行 CMake,Make或者其他工具将不会知道你是否添加了某个文件。值得注意的是,CMake 3.12 添加了一个
CONFIGURE_DEPENDS
标志能够使你更好的完成这件事。- 不要直接链接文件:如果可以的话总是链接目标
- 当链接库文件时,不要省略 PUBLIC或PRIVATE 关键字: 否则会导致未来的链接都没有关键字
- 不要使用全局函数,例如
- CMake 应遵守的规范(CMake Antipatterns)
- 把 CMake 视作代码,保持它的整洁和可读性
- 围绕 target 构建你的 CMake。将需要的信息打包在 target 里,然后链接那个目标
- 导出你的接口:你的 CMake 项目应该可以直接构建或者安装。
- 为库书写一个 Config.cmake 文件:这是一个库作者应该做的,可以方便别人使用你的库
- 使用 ALAS 目标以保持使用一致性:使用
add_subdirectory
和find_package
应该提供相同的目标和命名空间。 - 将常用的功能提取成函数或者宏,通常函数更好
- 使用小写的函数名,全大写的变量名
- 使用
cmake_policy
和/或 限定版本号范围:每次改变版本特性 (policy) 都要有据可依。应该只有不得不使用旧特性时才降低特性 (policy) 版本。
原文链接:https://blog.csdn.net/weiwei9363/article/details/109290252
后续
- 发现老外写的CMake教程真不错,比任何中文版的都清晰易懂,还比官方文档简洁,要说缺点可能就是不是最新的CMake3.0以后的主流写法,不过当前阶段会用更重要。
CMake part 1: It is a programming language!