CMake 入门教程

一、前言
手写 g++ main.cpp -o app 编译一两个文件还行,项目一多,改一个头文件就要重新敲一大串命令,换到 Windows 上还得换成 MSVC 的参数。CMake 就是为了解决这个问题:你只描述项目由哪些文件组成,剩下的由 CMake 生成对应平台的构建文件(Linux 生成 Makefile/Ninja,Windows 生成 VS 工程)。
二、安装
| |
验证:
| |
-G Ninja 去掉即可。三、核心概念
| 概念 | 含义 |
|---|---|
CMakeLists.txt | 项目的构建描述文件,CMake 的“源代码” |
| 生成器(Generator) | 把 CMakeLists 翻译成 Makefile / VS 工程 |
| Target(目标) | 一个可执行文件或库,是 CMake 的基本单位 |
| 构建目录(build) | 存放生成结果,习惯单独建 build/,不污染源码 |
PRIVATE / PUBLIC | 依赖的作用范围,决定要不要传给下游 |
构建流程
---
config:
flowchart:
htmlLabels: false
---
flowchart LR
A["CMakeLists.txt"] --> B["cmake -B build"]
B --> C{"生成器"}
C -->|"Ninja"| D["build.ninja"]
C -->|"Make"| E["Makefile"]
C -->|"MSVC"| F[".sln 工程"]
D --> G["cmake --build build"]
E --> G
F --> G
G --> H(["可执行文件 / 库"])---
config:
flowchart:
htmlLabels: false
---
flowchart LR
A["CMakeLists.txt"] --> B["cmake -B build"]
B --> C{"生成器"}
C -->|"Ninja"| D["build.ninja"]
C -->|"Make"| E["Makefile"]
C -->|"MSVC"| F[".sln 工程"]
D --> G["cmake --build build"]
E --> G
F --> G
G --> H(["可执行文件 / 库"])---
config:
flowchart:
htmlLabels: false
---
flowchart LR
A["CMakeLists.txt"] --> B["cmake -B build"]
B --> C{"生成器"}
C -->|"Ninja"| D["build.ninja"]
C -->|"Make"| E["Makefile"]
C -->|"MSVC"| F[".sln 工程"]
D --> G["cmake --build build"]
E --> G
F --> G
G --> H(["可执行文件 / 库"]) | |
CMake 本身不编译代码,它只负责把 CMakeLists.txt 翻译成对应平台的原生构建文件,真正干活的是 Ninja / Make / MSVC。
四、第一个项目
目录结构:
| |
main.cpp:
| |
CMakeLists.txt:
| |
编译运行:
| |
cmake -B build + cmake --build build 这两条命令,它对所有生成器都通用,不需要 cd build && make。五、多文件与子目录
文件一多,就把源码放进 src/,每个子目录各写一个 CMakeLists.txt:
| |
顶层 CMakeLists.txt:
| |
src/CMakeLists.txt:
| |
六、编译库并链接
把公共代码做成库,方便复用:
| |
add_library 的 STATIC 是静态库(.a/.lib),SHARED 是动态库(.so/.dll)。
PUBLIC 的头文件目录会随 target_link_libraries 自动传给使用方,这正是为什么 calc 不需要再写一次 target_include_directories。作用域用错是新手最常见的坑:只给自己用写 PRIVATE,接口暴露给下游写 PUBLIC。七、引入第三方库
现代 CMake 的标准做法是 find_package + target_link_libraries:
| |
找不到包时,把第三方库源码直接放进项目并用 add_subdirectory(third_party/fmt) 也可以。
八、编译选项与条件配置
| |
构建类型在配置时指定:
| |
九、常用命令速查
| 命令 | 作用 |
|---|---|
cmake -B build | 配置(生成构建文件) |
cmake --build build | 编译 |
cmake --build build -j8 | 并行编译 |
cmake -B build -DCMAKE_BUILD_TYPE=Debug | 指定构建类型 |
cmake --build build --target clean | 清理 |
rm -rf build | 彻底重来(改缓存变量后常用) |
十、学习建议
- 用 CMake 重构一个自己写过的小项目
- 理解
PRIVATE/PUBLIC/INTERFACE的区别 - 学会用
find_package引入第三方库 - 了解
install()与CTest单元测试集成 - 进阶:
FetchContent、presets(CMakePresets.json)
推荐资源
十一、总结
CMake 的核心就三句话:用 add_executable / add_library 定义 target,用 target_* 系列命令给 target 加属性,用 target_link_libraries 表达依赖。掌握这些之后,剩下的都是查文档的功夫。
先把手头项目的编译命令搬进 CMakeLists.txt,比死记语法有效得多。有问题欢迎留言交流。