如果你跟我一样,写 C++ 代码的历史里有一半时间都花在“手动敲编译命令、然后被各种链接错误支配”这件事上,那 CMake 绝对是你绕不过去的一个工具。简单说,CMake 是一个跨平台的构建系统生成器,它不直接编译代码,而是根据你写好的 CMakeLists.txt 规则,生成当前平台需要的构建文件——在 Linux 上是 Makefile,在 Windows 上可能是 Visual Studio 工程,在 macOS 上可以是 Xcode 工程,你不换代码就能在不同平台间复用同一套构建逻辑。这篇文章我会从安装开始,把 CMake 的基本使用给你完整捋一遍,包括 CMakeLists.txt 怎么写、构建流程怎么走、常见报错怎么排查,全都是我实际用下来摸索出来的经验,适合刚接触 CMake 或者一直被各种编译问题劝退的同学。
CMake 的学习门槛其实不高,真正难的是很多人一开始就被“生成器”“目标”“构建目录”这些概念绕晕。我会用尽量直白的方式讲,先把 CMake 到底干了什么事说清楚,再带你上手写第一个项目。你不需要一次记住所有命令,只要跟着我搭好一个能跑的工程,后面的细节慢慢就会融会贯通。
1. 项目结构设计:先搞清楚 CMake 站在哪一层
1.1 为什么需要 CMake 这个中间层
直接写 Makefile 不行吗?对于单个平台、单个编译器、不依赖第三方库的小项目,Makefile 完全够用。但一旦你需要同时支持 Linux、Windows、macOS,或者要动态切换编译选项、引入一堆第三方依赖,手写 Makefile 就会变得非常痛苦。CMake 的出现就是为了解决“同一份构建逻辑,跨平台复用”的问题。
CMake 的工作模式可以这样理解:
- 你写的是“构建剧本”CMakeLists.txt,描述项目里有哪些源文件、要生成什么目标、需要链哪些库。
- CMake 读取这份剧本,结合当前系统和编译器信息,生成对应的构建系统文件(Makefile、Ninja 文件、Visual Studio 工程等)。
- 然后用生成的构建工具去执行真正的编译和链接。
也就是说,你不需要关心各个平台的编译命令差异,CMake 帮你翻译成了对应平台能理解的语言。这也是它叫“构建系统生成器”而不是“编译器”的原因。
1.2 CMake 的两个阶段:配置和生成
CMake 在使用时分两个阶段。第一阶段是配置阶段,执行cmake命令读取 CMakeLists.txt,检查编译器、头文件、库文件,然后生成构建文件;第二阶段是构建阶段,执行cmake --build或者直接调用生成的构建系统(比如make),此时才会真正编译你的源码。
很多人第一次跑cmake ..后看到一大堆输出就慌,其实大部分信息是配置阶段的检查结果。比如它会找编译器、检查语言特性、查找依赖库等。如果这一步顺利,你就会看到Generating done的字样;如果这里报错,通常是你 CMakeLists.txt 写的条件不满足,或者环境里缺了什么工具。
所以当你遇到问题时,先分清是配置阶段还是构建阶段的问题。配置阶段的问题多半是找不到编译器、找不到依赖、语法错误;构建阶段的问题才跟你的源码有关,比如编译错误、链接错误。
1.3 源码目录与构建目录分离
CMake 有个重要的设计原则:编译产生的临时文件和最终产物,不要和源码混在一起。你可以在源码目录旁边单独建一个 build 目录,在 build 目录里执行cmake <源码路径>,所有生成的 Makefile、中间文件、可执行文件都会放进这个目录,源码目录保持干净。
这种“外部构建”的方式是我强烈建议你从一开始就养成的习惯。我见过太多人直接在源码目录里执行cmake .,结果生成一堆 CMakeCache.txt、CMakeFiles 文件夹,代码仓库里总是出现各种不明文件,维护起来非常折磨。外部构建的好处是,你随时可以删掉 build 目录重新来,不会污染源码,也不会误把临时文件提交到消息管理里,而且同一个源码可以同时生成多个配置(比如一个 Debug 一个 Release)放进不同目录。
2. 安装 CMake:三个平台的坑我都替你踩过了
2.1 Linux 下安装:版本号比想象中重要
Linux 下安装 CMake 最省事的方式是用系统包管理器。Ubuntu 和 Debian 系执行:
sudo apt update sudo apt install cmake如果你是 CentOS、RHEL、Fedora,用:
sudo yum install cmake # 或者 sudo dnf install cmake不过这里有个很容易被忽略的问题:包管理器自带的版本通常比较旧。比如某些老版 Ubuntu 仓库里的 CMake 可能停留在 3.16 甚至更早,而很多现代项目的 CMakeLists.txt 会要求最低版本 3.20 以上。如果你只需要编译一些基础项目,系统自带的版本够用;但如果你准备参与开源项目或者想体验新特性,我建议直接用 CMake 官方发布的安装脚本。
官方会发布类似cmake-3.29.3-linux-x86_64.tar.gz的二进制压缩包,把压缩包下载到/opt或~/tools目录解压,然后把bin目录加到 PATH 里就行。这样你拿到的是一个非常新的版本,而且不影响系统自带的包。
2.2 Windows 下安装:安装包和配置环境变量
Windows 上安装最简单的方法是去 CMake 官方网站下载 Windows 安装程序(.msi)。安装过程中它会问你是否把 CMake 添加到 PATH,我建议你勾选上,尤其是“Add CMake to the system PATH for all users”这个选项。如果没有勾选,后面你去命令行敲cmake就会提示“不是内部或外部命令”,还得自己手动补环境变量,麻烦得很。
装完以后,你可以在“开始菜单”里找到“CMake GUI”,它提供一个图形化界面,让你填源码目录、构建目录、选生成器,点 Configure 按钮完成配置,再点 Generate 生成构建文件。图形界面适合不想敲命令的初学者,但实际开发中命令行更灵活,也更好脚本化,所以我推荐你还是尽早习惯命令行用法。
如果你的 Windows 上装了 Visual Studio,CMake 会自动检测到 VS 的各个版本,并可以使用-G "Visual Studio 17 2022"这种参数指定生成器。用 VS 作为生成器时,CMake 会生成一个.sln解决方案文件,双击就能在 Visual Studio 里开发调试,体验很顺。
2.3 macOS 下安装:Homebrew 一把梭
macOS 用户最舒服的安装方式是 Homebrew:
brew install cmake这个命令会给你装好最新版 CMake,同时把依赖都处理好。如果你还没装 Homebrew,那先去装 Homebrew,它是 macOS 上必不可少的包管理器。装完 CMake 后终端里直接敲cmake --version就能看到输出。
除了 Homebrew,你也可以从官网下载 macOS 安装包,或者用我要安装在/Applications/CMake.app/Contents/bin/cmake的方式,但那样还得改 PATH,不如 Homebrew 省心。
2.4 验证安装:cmake --version
无论哪个平台,安装完成后先执行一条命令验证:
cmake --version输出类似:
cmake version 3.29.3 CMake suite maintained and supported by Kitware (kitware.com/cmake).如果能看到版本号,说明安装成功。如果系统提示找不到命令,请先检查你的 PATH 环境变量是否配置正确。这时候不要急着重装,先确认是不是环境变量没生效——我见过太多人卡在这一步,明明装了但终端找不到。
另外,如果你想确认 CMake 支持哪些生成器,可以执行:
cmake --help其中有一段会列出所有可用的生成器,比如 Unix Makefiles、Ninja、Visual Studio 17 2022 等。这个信息在排查生成器相关错误的时候很有用。
3. 第一个项目:从零写出可运行的 CMakeLists.txt
3.1 最基础的项目目录结构
假设我们要做一个超级简单的 C++ 项目,只有一个主文件,输出 “Hello CMake”。项目目录长这样:
hello_cmake/ ├── CMakeLists.txt └── main.cpp这里的CMakeLists.txt就是整个项目的构建配置文件,所有 CMake 指令都写在这个文件里。main.cpp是源码文件。
这里先说明一下,CMakeLists.txt 的文件名是固定的,不能写错也不能改叫别的。CMake 执行时会自动在当前或指定目录里寻找这个文件,如果找不到,直接报错让你怀疑人生。
3.2 最简 CMakeLists.txt 的写法
打开 CMakeLists.txt,写入:
cmake_minimum_required(VERSION 3.16) project(HelloCmake LANGUAGES CXX) add_executable(hello_cmake main.cpp)这三行就是 CMake 工程的骨架:
cmake_minimum_required(VERSION 3.16)声明最低 CMake 版本。这是为了防止你用新版命令去跑旧版 CMake 时产生莫名其妙的错误,这是项目管理上的一个保险丝。project(HelloCmake LANGUAGES CXX)定义项目名称,并告诉 CMake 这是一个 C++ 项目。如果你不声明 LANGUAGES,CMake 默认会同时探测 C 和 CXX,没有实际坏处,但显式声明是更清晰的习惯。add_executable(hello_cmake main.cpp)是最核心的命令,意思是:用main.cpp编译并链接出一个名为hello_cmake的可执行文件。如果后续你还想加其他源文件,就往后面的列表里继续加。
写好以后,进入项目根目录,建立 build 目录并进入,执行 CMake 配置和构建。
3.3 构建三步走:配置、编译、运行
在项目根目录下执行:
mkdir build cd build cmake ..这里的..指的是源码目录,CMake 会去hello_cmake目录下找 CMakeLists.txt。这一步执行完,build 目录里会生成一堆文件,包括 Makefile、CMakeCache.txt 等。如果输出结尾出现:
-- Build files have been written to: /path/to/hello_cmake/build就说明配置阶段成功。
接着执行:
cmake --build .这个命令会调用构建系统(我们这里用的是 Makefile,所以实际上等于执行make),把 main.cpp 编译成可执行文件。编译成功后,你会看到 build 目录里出现一个hello_cmake可执行文件(Windows 下是hello_cmake.exe)。
最后运行:
./hello_cmake如果输出Hello CMake,恭喜你,第一个 CMake 项目已经跑通了。我建议你把这三步刻在脑子里:cmake ..配置、cmake --build .构建、直接运行产物。以后无论项目多复杂,最核心的流程不会变。
4. CMake 核心概念与常用命令逐个拆解
4.1 版本声明和项目声明
cmake_minimum_required这句很多人写项目时会忽略,觉得无关紧要。实际上,如果你用了一个高版本才有的命令,而别人用低版本 CMake 运行你的项目,就会收到“CMake 3.10 does not support ... ”这类错误。我一般会查看自己当前 CMake 的版本,然后声明一个比它略低的版本,比如当前是 3.29,我就写 3.16,既支持了绝大多数功能,又不至于过高地限制别人。
project命令除了定义名字,还会定义一些变量,比如PROJECT_NAME、PROJECT_SOURCE_DIR、PROJECT_BINARY_DIR。这两个变量在大型项目中非常常用,分别指向源码根目录和构建目录。比如你有一个配置文件需要拷贝,就可以用${PROJECT_SOURCE_DIR}/config/xxx.ini来定位源文件位置,而不是写死绝对路径。
4.2 生成可执行文件:add_executable
add_executable是 CMake 中最常用的命令。它的第一个参数是生成的目标名,第二个及以后是参与编译的源文件列表。目标名不需要和可执行文件名完全一致,但为了方便,我通常保持一致。
如果源文件只有一个,直接把文件名写在后面;如果有很多,可以用空格分隔罗列,也可以使用变量来收集。比如:
set(SOURCES src/main.cpp src/utils.cpp src/logger.cpp ) add_executable(my_app ${SOURCES})这个写法在项目变大的时候尤其好用。你把所有源文件放在一个变量里,后面想加几个文件,只需要修改set(SOURCES ...)那一块,不需要改动其他命令。
4.3 生成库文件:add_library
当你的项目不是简单的主程序,而是包含几个模块时,把公共代码拆成库是一个好习惯。CMake 里用add_library来生成静态库或动态库:
add_library(calc STATIC src/calc.cpp) add_library(calc_shared SHARED src/calc.cpp)STATIC生成静态库(Linux 下是.a,Windows 下是.lib),SHARED生成动态库(Linux 下是.so,Windows 下是.dll)。一般小项目我更喜欢静态库,因为部署一个可执行文件就够了,不用额外考虑动态库的搜索路径。
库目标生成以后,其他目标可以通过target_link_libraries来链接它。这里注意一个概念:在 CMake 里,“目标”包括可执行文件、库文件,它们之间可以做依赖关联。CMake 会自动推导出编译顺序,不需要你手动去管“先编译库还是先编译主程序”。
4.4 头文件路径与链接库:目标属性是关键
假设项目里有独立的头文件目录include,源文件在src下,那你需要让编译器能找到头文件。最直观的方式是:
target_include_directories(my_app PRIVATE include)target_include_directories的作用是告诉编译器,在编译my_app时,要从include目录里搜索头文件。这里的PRIVATE关键字是传递范围限制,指这个目录只对当前目标生效,不会影响别人。
稍微复杂一点的场景是,你有一个库目标calc,它自己的源文件需要include目录;同时可执行目标my_app链接了calc,也需要拿到calc的头文件路径。如果你只在calc上做:
target_include_directories(calc PUBLIC include)并且之后:
target_link_libraries(my_app PRIVATE calc)那么my_app也会自动获得include目录。这就是PUBLIC和PRIVATE的意义。如果你用 PRIVATE 把头文件路径限定在calc内部,my_app去包含calc.h时就找不到了。这个传递机制是 CMake 里最容易让人迷糊的地方,也是很多“找不到头文件”问题的根源。
target_link_libraries的语法是:
target_link_libraries(target_name PRIVATE calc )如果你链接的是系统库,比如m(数学库)、pthread,直接写上库名即可:
target_link_libraries(my_app PRIVATE m pthread)4.5 引入子目录:add_subdirectory
实战项目通常会划分成多个层级,比如最外层 CMakeLists.txt 通过add_subdirectory(calc)引入 calc 子目录,而calc/CMakeLists.txt里定义自己的目标。这样做的好处是每个模块的构建规则就近管理,不需要在一个巨大的 CMakeLists.txt 里塞下所有东西。
比如顶层 CMakeLists.txt 可以写成:
cmake_minimum_required(VERSION 3.16) project(MiniCalc) add_subdirectory(calc) add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE calc)然后calc/CMakeLists.txt写:
add_library(calc STATIC calc.cpp) target_include_directories(calc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)这里${CMAKE_CURRENT_SOURCE_DIR}表示当前 CMakeLists.txt 所在目录,用它拼出 include 绝对路径,可以避免各种相对路径出错。CMake 本身对相对路径有一套规则,但新手很容易绕晕,所以我建议在子目录里总是用这个变量来定位当前模块路径。
5. 一个完整的小型实战项目:多文件 + 子目录 + 库
前面把命令都过了一遍,现在我们来把这些东西串起来,做一个 MiniCalc 项目。这个项目会包含一个calc静态库、一个main.cpp主程序,结构大概是这样:
MiniCalc/ ├── CMakeLists.txt ├── main.cpp └── calc/ ├── CMakeLists.txt ├── include/ │ └── calc.hpp └── src/ └── calc.cpp5.1 calc 模块的 CMakeLists.txt
calc/include/calc.hpp里声明一个简单的加法函数:
#ifndef CALC_HPP #define CALC_HPP int add(int a, int b); #endifcalc/src/calc.cpp里实现:
#include "calc.hpp" int add(int a, int b) { return a + b; }calc/CMakeLists.txt写:
add_library(calc STATIC src/calc.cpp) target_include_directories(calc PUBLIC include)注意:这里我没有写cmake_minimum_required和project,因为在子目录的 CMakeLists.txt 里不需要重复声明,顶层已经声明过了。如果写上也不算错,但会显得冗余。
target_include_directories(calc PUBLIC include)里的include是相对路径,CMake 会相对于当前 CMakeLists.txt 所在目录去解释,所以它会指向calc/include。这里我用PUBLIC,目的是让链接calc的my_app也能自动找到calc.hpp。
5.2 主程序的 CMakeLists.txt
顶层CMakeLists.txt:
cmake_minimum_required(VERSION 3.16) project(MiniCalc LANGUAGES CXX) add_subdirectory(calc) add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE calc)main.cpp:
#include <iostream> #include "calc.hpp" int main() { std::cout << "3 + 4 = " << add(3, 4) << std::endl; return 0; }这里直接#include "calc.hpp",因为my_app链接了calc目标,calc的 PUBLIC include 目录会被 CMake 自动传递给my_app,编译器就能找到头文件。
5.3 构建与运行流程
在项目根目录执行:
mkdir build && cd build cmake .. cmake --build . ./my_app运行结果:
3 + 4 = 7这个流程里,CMake 会自动识别calc库的依赖关系:先编译calc,再编译my_app,最后链接。你不用手动指定,也根本不需要关心add函数的实现细节。这就是 CMake 的“目标系统”帮我们解决的最大问题。
这个小项目如果再往大了扩展,比如再加一个tests目录、一个utils目录,逻辑都类似:add_subdirectory引入模块,target_link_libraries建立依赖,target_include_directories传递头文件路径。一旦这个思路被你看透,后面看别人的大型 CMake 项目就不会再一头雾水。
6. 常见报错与排查经验:我遇到过的坑,基本都在这了
6.1 找不到编译器:No CMAKE_CXX_COMPILER found
这种错误通常出现在 Linux 上,原因是你系统里只装了 CMake,却没装 C++ 编译器。Ubuntu 上执行:
sudo apt install build-essential如果错误信息里提示找不到 C 编译器,则还要确认gcc是否存在。Windows 上出现这个错误通常是 Visual Studio 未安装或者没有安装 C++ 开发组件。CMake 默认会去系统 PATH 里找编译器,如果你装有 VS 但不在 PATH,你需要用-G "Visual Studio 17 2022" -A x64这样的参数显式指定生成器,CMake 会通过注册表信息定位 VS 并自动配置编译器。
这个报错还有一个隐藏坑:当你在 build 目录里换了一个编译器路径时,CMakeCache.txt 里会残留旧配置。比如你先用 gcc 配置了一次,后来把 gcc 卸载了,重新执行 cmake 可能还会报错说找不到之前的编译器。这时候直接删掉 build 目录重新来,比疯狂找原因更高效。
6.2 找不到头文件:fatal error: xxx.h: No such file or directory
这个问题我在复习时见过无数次。原因基本是两个:一是你根本没有写target_include_directories,或者写错了路径;二是用了PRIVATE导致头文件路径没有传递给使用者。
排查步骤我一般这样走:
- 先确认头文件是否真的存在于你写的目录里,排除拼写错误。
- 再检查
target_include_directories的路径是否正确,如果用的是相对路径,结合当前的 CMakeLists.txt 所在目录来判断。 - 最后看目标之间的依赖关系:如果你需要
main.cpp能包含库提供的头文件,那库的 include 属性必须是PUBLIC,且你的主目标必须链接了库。
如果你是在 IDE 里(比如 VS)遇到这个错误,还有一个可能是 CMake 重新生成之后 IDE 没刷新缓存。VS 对 CMake 工程有时会缓存旧的 include 路径,右键点击项目根目录,选择“重新加载”或者清一下 CMake 缓存就能解决。
6.3 链接报错:undefined reference to xxx
编译能通过,但链接时报错,说明你的声明写在了头文件里,但实现没有被链接进来。常见情况:你声明了一个函数,但是忘记把它所在的源文件加入add_executable;或者你用了库目标但忘了target_link_libraries。
我遇到过的典型场景是:在 Windows 上使用 VS 生成器,源码文件在 VS 里看着已经包含了,但链接器就是找不到实现。最后发现是 CMakeLists.txt 里的源文件列表是硬编码好的,后来新增了一个 .cpp 文件却忘了加进去。解决方案很简单:把新文件加入源文件列表,然后重新生成工程。
另外,如果你链接动态库,还要注意库文件的搜索路径。Linux 下动态库找不到常见的报错是cannot open shared object file,此时你需要设置LD_LIBRARY_PATH或者在 CMake 里用install规则把库安装到系统路径。个人小项目更推荐直接用静态库,省掉这堆麻烦。
6.4 修改了 CMakeLists.txt 但似乎没生效
CMake 的配置是累积的,如果你在源码目录外层配置过,后来增删了源文件、改了编译选项,理论上重新执行cmake --build .时会自动感知 CMakeLists.txt 的变化并重新生成构建文件。但有时因为修改了cmake_minimum_required或者改变了生成器、缓存等原因,会发生“改了半天没反应”的问题。
最粗暴也最有效的方法:清掉 build 目录,重新走一遍cmake ..和cmake --build .。虽然会让增量编译失效,但几乎所有诡异问题都能通过“删除 build 目录重来”解决。这个习惯我建议你彻底接受,它和 “重启大法”一样万能。
6.5 如何确定使用了哪个生成器
如果系统里有多个生成器,CMake 默认选择会根据平台决定:Linux 上默认Unix Makefiles,Windows 上默认 VS 工程,macOS 上默认 Xcode。很多时候你想用 Ninja,或者明确要用 VS 的新版本,可以通过-G参数指定:
cmake -G "Ninja" .. cmake --build .注意,如果你第一次配置时用了-G,之后重新配置也必须用相同的-G,否则 CMake 会报错说构建目录已经配置过。我建议在项目里写好一个build.sh或build.bat保存配置命令,避免每次都要回忆。
7. 提升开发体验的几个实用技巧
7.1 用 CMakePresets.json 统一团队配置
CMake 3.19 以后支持CMakePresets.json,它可以把常用的配置参数固化下来,比如生成器、构建类型、编译选项等。以后团队成员执行:
cmake --preset release就可以得到一套统一的配置方式,不用每个人都在命令行里敲一长串参数。同时配套的还有CMakeUserPresets.json,用于覆盖本机个性化设置,这个文件一般不需要提交到版本管理。
这个功能对团队协作非常香。我之前参与过一个项目,每个人配置命令都不同,有人用 Ninja,有人用 Makefile,还有人用 VS,经常出现“我这边编译好好的,别人那报错”的情况。后来统一用 presets 后,再也没因为生成器不一致争吵过。
7.2 Debug 和 Release 要分开目录
如果你想在同一份源码上分别生成 Debug 和 Release 版本,不要用同一个 build 目录来回切换配置。因为 CMakeCache.txt 会记住上一次的构建类型,切来切去很容易出现缓存混乱。
推荐的做法是:
mkdir build-debug && cd build-debug cmake .. -DCMAKE_BUILD_TYPE=Debug mkdir build-release && cd build-release cmake .. -DCMAKE_BUILD_TYPE=Release这样两份构建产物互不干扰。Debug 版本默认带上调试信息,不优化;Release 版本开优化开关,跑起来快很多。如果你不开CMAKE_BUILD_TYPE,默认是空字符串,不会加优化参数,但也不影响功能。我一般主程序都用 Release,只有需要断点调试时才切到 Debug。
7.3 怎么快速判断一个项目能不能用 CMake 构建
很多开源项目下载下来后,你只需要看根目录有没有CMakeLists.txt。如果有,那构建路径基本就是老三样:
mkdir build && cd build cmake .. cmake --build .如果项目用到外部依赖,你可能还需要先cmake ..之后看一下输出的错误提示,按提示装依赖。有些项目提供了INSTALL步骤,安装到系统路径或者指定前缀:
cmake --install .在 Windows 上,cmake --install .会把产物安装到你指定的目录,配合-DCMAKE_INSTALL_PREFIX可以控制安装位置。这个功能用于部署到本地环境很方便,不需要手动复制一堆文件。
7.4 CTest 和 CPack:CMake 全家桶里的另外两兄弟
CTest 是 CMake 自带的测试工具,你只要在 CMakeLists.txt 里用enable_testing()和add_test注册测试,再执行ctest就能跑全部测试。CPack 则是打包工具,可以生成 tar.gz、zip、deb、rpm、NSIS 安装包等。新手阶段不一定需要掌握,但至少知道它们存在:当你的项目需要发布给更多人用的时候,CPack 能省掉非常多重复劳动。
我自己是从一年后才开始用 CTest 的。之前一直觉得 “测试随便跑跑就行”,但后来项目大了,手动回归测试根本覆盖不过来。用add_test注册几个关键用例之后,每次改动跑一遍ctest,心里踏实很多。
最后分享一点我的真实体会
如果让我说学习 CMake 最重要的几个节点,我会总结成:先跑通一个最小工程,再理解目标(target)的概念,最后熟悉怎么排查缓存和生成器问题。这三个节点只要过了,CMake 对你来说就不再是拦路虎了。很多人的误区是一上来就找一堆高级语法,比如 module、macro、自定义命令,结果被吓得不敢用。其实日常开发用到的东西不到 CMake 能力的十分之一,先把这十分之一练熟,后面遇到新需求时再去查那个具体功能的文档,效率才是最高的。
我个人到现在写新项目时,还是会习惯先丢一个最简单的cmake_minimum_required+add_executable进去,让项目先动起来,再逐步补充目录、库、测试。每次手动敲完cmake ..和cmake --build .,看到 “Build files have been written” 这个输出,还是会有一种“今天也是顺利构建的一天”的感觉。希望这篇文章能帮你少走一点弯路,也让 CMake 成为你顺手的东西,而不是学习路上的绊脚石。