CMake 系列教程(一):CMake 基础知识
跨平台构建的艺术,从认识 CMake 开始
一、什么是 CMake?
CMake 是一个跨平台的开源构建系统生成器 (Build System Generator)。它并不直接编译代码,而是根据你编写的 CMakeLists.txt 配置文件,生成对应平台的原生构建文件:
| 平台 | 生成的构建文件 |
|---|---|
| Linux / macOS | Makefile、Ninja |
| Windows | Visual Studio .sln / .vcxproj |
| 通用 | Ninja、NMake |
简单理解:CMake 是构建系统的"元工具",它让你写一次配置,到处构建。
二、为什么选择 CMake?
2.1 跨平台是刚需
现实项目中,开发者可能用 Windows + MSVC 开发,而 CI 跑在 Linux + GCC 上。如果你手写 Makefile,Windows 上无法直接使用;如果写 .sln,Linux 上更没法用。CMake 一份配置,两处运行。
2.2 业界主流
- 大型项目:LLVM、OpenCV、Boost、Qt、Vulkan、Google Test......
- 集成友好:VSCode CMake Tools、CLion、Visual Studio 原生支持 CMake
- 包管理:vcpkg、Conan 等包管理器都与 CMake 深度集成
2.3 对比其他方案
| 方案 | 跨平台 | 学习曲线 | 生态 |
|---|---|---|---|
| 手写 Makefile | ❌ Linux/macOS 为主 | 低 | 小 |
| Visual Studio 工程 | ❌ Windows 专属 | 低 | Windows |
| QMake | ✅ 但绑定 Qt | 中 | Qt |
| Bazel | ✅ | 高 | Google 系 |
| CMake | ✅ | 中 | 最广泛 |
三、安装 CMake
3.1 Windows
powershell
# 方式一:winget(推荐)
winget install Kitware.CMake
# 方式二:Chocolatey
choco install cmake
# 方式三:官网下载安装包
# https://cmake.org/download/
安装后确认:
powershell
cmake --version
# cmake version 3.28.3
💡 提示 :Windows 安装时勾选 "Add CMake to the system PATH for all users" ,否则命令行找不到
cmake。
3.2 Linux
bash
# Ubuntu / Debian
sudo apt install cmake
# Fedora
sudo dnf install cmake
# 如果需要最新版,使用 Kitware 官方源
# https://apt.kitware.com/
3.3 macOS
bash
# Homebrew
brew install cmake
四、核心概念
在动手写代码之前,先理解 CMake 的几个核心概念。
4.1 构建目录(Out-of-Source Build)
CMake 强烈推荐不在源码目录中构建 ,而是创建一个独立的 build/ 目录:
my_project/
├── CMakeLists.txt # 配置文件
├── src/
│ └── main.cpp # 源码
└── build/ # 构建目录(可随时删除重建)
├── Makefile # 生成的构建文件
└── ...
好处 :构建产物不会污染源码目录,rm -rf build/ 即可彻底清理。
4.2 两步流程
CMake 的工作分为两步:
┌─────────────┐ ┌─────────────┐
│ 配置阶段 │ ──→ │ 构建阶段 │
│ (Configure) │ │ (Build) │
│ │ │ │
│ cmake -B │ │ cmake --build│
│ CMakeLists │ │ 调用编译器 │
│ → 生成构建文件│ │ → 生成目标文件│
└─────────────┘ └─────────────┘
- 配置阶段 :读取
CMakeLists.txt,检测编译器、查找依赖,生成原生构建文件 - 构建阶段 :调用底层构建工具(make、ninja、msbuild)编译代码
4.3 目标(Target)
Target 是 CMake 的核心抽象,有两种类型:
- 可执行目标 (Executable):生成可运行程序,如
add_executable(myapp main.cpp) - 库目标 (Library):生成静态库/动态库,如
add_library(mylib STATIC lib.cpp)
现代 CMake(3.x)提倡以目标为中心的写法,而非传统的"目录级变量"风格。
4.4 生成器(Generator)
生成器决定 CMake 产出什么构建文件:
bash
# 查看所有可用生成器
cmake --help
# 常用生成器
cmake -G "Unix Makefiles" .. # Linux/macOS 默认
cmake -G "Ninja" .. # 跨平台,速度最快
cmake -G "Visual Studio 17 2022" .. # Windows
🚀 推荐 :优先使用 Ninja 生成器,比 Make 快很多,且跨平台。
bash# 安装 Ninja # Ubuntu: sudo apt install ninja-build # macOS: brew install ninja # Windows: winget install Ninja-build.Ninja
五、第一个 CMake 项目
5.1 项目结构
hello_cmake/
├── CMakeLists.txt
└── main.cpp
5.2 源码
main.cpp:
cpp
#include <iostream>
int main() {
std::cout << "Hello, CMake!" << std::endl;
return 0;
}
CMakeLists.txt:
cmake
# 1. 最低版本要求
cmake_minimum_required(VERSION 3.20)
# 2. 项目定义
project(HelloCMake LANGUAGES CXX)
# 3. 添加可执行目标
add_executable(hello main.cpp)
三行配置,清晰明了:
| 行 | 作用 |
|---|---|
cmake_minimum_required |
声明所需最低 CMake 版本,低于此版本会报错 |
project |
定义项目名称和使用的语言(CXX = C++) |
add_executable |
告诉 CMake 编译 main.cpp 生成可执行文件 hello |
5.3 构建与运行
bash
# 配置 + 构建(一步到位写法,CMake 3.20+)
cmake -B build
cmake --build build
# 运行
./build/hello # Linux/macOS
.\build\Debug\hello.exe # Windows (Visual Studio)
💡
-B build指定构建目录为build/,无需手动mkdir build && cd build。
六、CMake 版本选择策略
不同 CMake 版本差异较大,选择策略如下:
| 场景 | 推荐最低版本 | 原因 |
|---|---|---|
| 个人新项目 | 3.25+ | 享受最新特性(CMakePresets、FetchContent 改进) |
| 团队项目 | 3.20+ | 平衡新特性与兼容性 |
| 开源库 | 3.14+ | 覆盖更广泛的用户环境 |
不要随意设太低 (如 VERSION 2.8),旧版本的行为与现代 CMake 差异巨大,容易踩坑。
七、常见问题
Q1:CMake 和 Make 是什么关系?
CMake 生成 Makefile,Make 执行 Makefile。 CMake 是"元构建系统",Make 是"构建系统"。关系如下:
CMakeLists.txt → [CMake] → Makefile → [Make] → 可执行文件
Q2:修改了 CMakeLists.txt 后需要重新配置吗?
需要。 但如果你使用 cmake --build,它会自动检测并重新运行配置。如果直接用 make,则需要手动重新 cmake。
Q3:构建出错如何彻底清理?
bash
# 删除构建目录,重新来过
rm -rf build/
cmake -B build
这是 out-of-source build 最大的好处------删除 build/ 就回到初始状态。
小结
| 要点 | 内容 |
|---|---|
| CMake 是什么 | 跨平台构建系统生成器 |
| 核心流程 | 配置(cmake -B)→ 构建(cmake --build) |
| 核心抽象 | Target(可执行/库) |
| 最佳实践 | Out-of-source build、使用现代 CMake 写法 |
| 生成器推荐 | Ninja > Makefile |
📖 下一期预告 :《CMake 系列教程(二):基础命令详解》------ 深入讲解
add_library、target_link_libraries、target_include_directories等核心命令,掌握多文件、多目标的真实项目构建。