CMake 是一个跨平台的构建系统生成器。其核心功能并非直接编译代码,而是根据开发者编写的 CMakeLists.txt 配置文件,自动生成适配不同平台或编译器的构建文件,例如在 Linux 上生成 Makefile,在 Windows 上生成 Visual Studio 工程文件。
核心工作流程简化如下:
- 开发者:无需为每个平台手动编写复杂的 Makefile 或工程文件,只需维护一套统一的
CMakeLists.txt 配置文件。
- CMake:读取配置文件,并针对当前平台生成对应的、可直接使用的构建文件。
- 本地编译工具:使用生成的构建文件(如执行
make 或打开 .sln)来完成实际的编译、链接工作。
为什么选择 CMake?
- 跨平台:一套配置,即可在 Windows、Linux、macOS 等主流操作系统上构建项目。
- 灵活强大:原生支持 C、C++,并可通过扩展支持 CUDA、Java 等多种语言,允许深度自定义编译规则。
- 生态广泛:绝大多数主流 C/C++ 开源项目(如 OpenCV、TensorFlow)都采用 CMake 作为构建工具,便于项目集成。
基础使用流程
第一步:安装 CMake
- Debian/Ubuntu:
sudo apt install cmake
- CentOS/RHEL:
sudo yum install cmake
- Windows: 从 CMake官网 下载安装包,安装时勾选“Add CMake to the system PATH”。
- macOS:
brew install cmake
安装后,在终端输入 cmake --version 验证是否安装成功。
最小示例:编译单个C++文件
假设有一个简单的 C++ 源文件 main.cpp:
// main.cpp
#include <iostream>
int main() {
std::cout << "Hello CMake!" << std::endl;
return 0;
}
步骤 1:编写 CMakeLists.txt
在与 main.cpp 相同的目录下创建 CMakeLists.txt 文件(文件名大小写敏感),内容如下:
# 1. 指定CMake最低版本要求(推荐明确指定)
cmake_minimum_required(VERSION 3.10)
# 2. 定义项目名称
project(HelloCMake)
# 3. 设置C++标准(例如C++11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 4. 添加可执行目标:语法 add_executable(目标名 源文件列表)
add_executable(hello_cmake main.cpp)
步骤 2:生成构建系统
推荐使用“外部构建”,避免编译产物污染源代码目录。
- 创建并进入
build 目录:
mkdir build && cd build
- 运行 CMake,指定上级目录(即
CMakeLists.txt 所在位置):
cmake ..
- 在 Linux/macOS 上,这会生成
Makefile。
- 在 Windows 上,默认会生成 Visual Studio 解决方案文件(可使用
-G 参数指定其他生成器,如 cmake .. -G "MinGW Makefiles")。
步骤 3:编译项目
- Linux/macOS: 在
build 目录下执行 make。
- Windows (通用命令): 在
build 目录下执行 cmake --build .,或直接打开生成的 .sln 文件进行编译。
步骤 4:运行程序
# Linux/macOS
./hello_cmake
# Windows (在build目录下)
hello_cmake.exe
终端将输出:Hello CMake!
进阶示例:管理多文件与多目录项目
假设项目结构如下:
my_project/
├── CMakeLists.txt # 根目录CMake配置
├── src/
│ ├── main.cpp
│ └── math/
│ ├── math.cpp
│ ├── math.h
│ └── CMakeLists.txt # 子目录CMake配置
1. 编写子目录配置 (src/math/CMakeLists.txt)
# 将 math.cpp 编译成一个静态库
add_library(math_lib STATIC math.cpp)
2. 编写根目录配置 (CMakeLists.txt)
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加子目录,CMake会执行其中的 CMakeLists.txt
add_subdirectory(src/math)
# 生成主可执行文件
add_executable(my_app src/main.cpp)
# 将前面生成的 math_lib 库链接到可执行文件 my_app
target_link_libraries(my_app PRIVATE math_lib)
# 为 my_app 添加头文件搜索路径,使其能找到 math.h
target_include_directories(my_app PRIVATE src/math)
3. 编译与运行
mkdir build && cd build
cmake ..
make # 或在Windows上使用: cmake --build .
./my_app # 运行程序
核心CMake指令速查表
| 指令 |
作用说明 |
cmake_minimum_required(VERSION x.x) |
指定项目所需CMake的最低版本。 |
project(ProjectName) |
定义项目名称。 |
add_executable(target_name src1.cpp src2.cpp) |
生成一个可执行文件目标。 |
add_library(lib_name STATIC/SHARED src.cpp) |
生成一个静态库(STATIC)或动态库(SHARED)。 |
target_link_libraries(target_name PRIVATE lib_name) |
将库链接到指定的目标(可执行文件或库)。 |
target_include_directories(target_name PRIVATE include_dir) |
为指定目标添加头文件包含目录。 |
add_subdirectory(sub_dir) |
添加一个子目录,CMake会处理其中的 CMakeLists.txt。 |
set(VARIABLE_NAME value) |
定义一个变量。 |
cmake -G “GeneratorName” .. |
指定构建系统生成器(如 "Unix Makefiles", "Visual Studio 17 2022")。 |
实用技巧与配置
1. 指定编译器
在生成构建系统时,可以通过参数指定编译器,这对于跨平台编译和特定环境配置非常有用。
# 在Linux上指定使用Clang
cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
# 在Windows上生成特定版本的VS工程
cmake .. -G "Visual Studio 17 2022" -A x64
2. 切换构建类型 (Debug/Release)
# 生成调试版本(包含调试符号,未优化)
cmake .. -DCMAKE_BUILD_TYPE=Debug
# 生成发布版本(进行优化,不包含调试符号)
cmake .. -DCMAKE_BUILD_TYPE=Release
3. 安装目标
可以在 CMakeLists.txt 中配置安装规则,使用 make install 或 cmake --install . 命令将编译好的目标文件、库或头文件安装到系统目录。
# 安装可执行文件
install(TARGETS my_app DESTINATION bin)
# 安装库文件
install(TARGETS math_lib DESTINATION lib)
# 安装头文件
install(FILES src/math/math.h DESTINATION include)
总结
CMake 的核心思想是声明式配置:你只需在 CMakeLists.txt 中声明“要编译什么”(目标)和“依赖什么”(库、头文件),CMake 便会为你处理所有平台相关的构建细节。
- 入门核心:掌握
cmake_minimum_required, project, add_executable 足以应对简单项目。
- 项目进阶:掌握
add_library, target_link_libraries, target_include_directories 和 add_subdirectory 是管理复杂、模块化项目的关键。
- 生态集成:绝大多数第三方库都提供 CMake 配置,通过
find_package() 等指令可以方便地集成,其底层逻辑与本文介绍的基础用法一脉相承。