CMake 基础知识
CMake 是一个跨平台的构建配置工具。它本身通常不直接编译代码,而是根据 CMakeLists.txt 生成具体平台可执行的构建系统,例如 Makefile、Ninja 工程、Visual Studio 工程等。
在业务开发中,CMake 常用于管理 C/C++ 项目的源码、头文件、库依赖、编译选项、安装规则和测试流程。它的核心价值是:用一套配置描述项目,让 Linux、Windows、macOS 和不同 IDE 都能按相同规则构建。
相关笔记:cmake关键字
CMake 解决什么问题
手写编译命令适合很小的程序:
g++ main.cpp -o hello但真实项目通常会遇到这些问题:
- 源码文件很多,手动维护编译命令容易漏文件。
- 需要链接第三方库或项目内静态库、动态库。
- Debug、Release 使用不同编译参数。
- Windows、Linux、macOS 的编译器和构建工具不同。
- 需要把可执行文件、库、头文件安装到指定目录。
- CI/CD 需要稳定、可重复的构建命令。
CMake 通过 CMakeLists.txt 把这些规则写成项目配置,然后生成对应平台的构建文件。
基本工作流
推荐使用 out-of-source build,也就是把构建产物放到 build 目录,不污染源码目录。
cmake -S . -B build
cmake --build build常用流程如下:
- 在项目根目录编写
CMakeLists.txt。 - 执行
cmake -S . -B build配置项目。 - 执行
cmake --build build编译项目。 - 需要安装时执行
cmake --install build。 - 修改源码后通常只需要重新执行
cmake --build build。 - 修改
CMakeLists.txt或依赖配置后,重新执行配置命令。
最小可运行示例
目录结构:
hello-cmake/
├── CMakeLists.txt
└── main.cppmain.cpp:
#include <iostream>
int main()
{
std::cout << "Hello CMake" << std::endl;
return 0;
}CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(HelloCMake
VERSION 1.0.0
DESCRIPTION "A minimal CMake executable example"
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(hello
main.cpp
)构建命令:
cmake -S . -B build
cmake --build build运行:
./build/helloWindows 使用 Visual Studio 生成器时,可执行文件通常在配置子目录中,例如:
.\build\Debug\hello.exe业务项目常用完整示例
下面示例展示一个更接近业务项目的结构:可执行程序依赖一个项目内静态库,并配置头文件目录、编译特性、编译选项和安装规则。
目录结构:
demo-app/
├── CMakeLists.txt
├── include/
│ └── demo/
│ └── calculator.h
└── src/
├── calculator.cpp
└── main.cppinclude/demo/calculator.h:
#pragma once
namespace demo {
int add(int left, int right);
}src/calculator.cpp:
#include "demo/calculator.h"
namespace demo {
int add(int left, int right)
{
return left + right;
}
}src/main.cpp:
#include "demo/calculator.h"
#include <iostream>
int main()
{
std::cout << demo::add(2, 3) << std::endl;
return 0;
}完整 CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(DemoApp
VERSION 1.0.0
DESCRIPTION "Demo business application built with CMake"
LANGUAGES CXX
)
option(DEMO_ENABLE_WARNINGS "Enable common compiler warnings" ON)
add_library(demo_core STATIC
src/calculator.cpp
)
target_include_directories(demo_core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_features(demo_core
PUBLIC
cxx_std_17
)
if(DEMO_ENABLE_WARNINGS)
if(MSVC)
target_compile_options(demo_core PRIVATE /W4)
else()
target_compile_options(demo_core PRIVATE -Wall -Wextra -Wpedantic)
endif()
endif()
add_executable(demo_app
src/main.cpp
)
target_link_libraries(demo_app
PRIVATE
demo_core
)
install(TARGETS demo_core demo_app
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install(DIRECTORY include/
DESTINATION include
)构建 Debug 版本:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build构建 Release 版本:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build安装到指定目录:
cmake --install build --prefix ./dist说明:
demo_core是项目内部库,业务逻辑放在这里。demo_app是最终可执行程序。target_include_directories(... PUBLIC ...)表示使用demo_core的目标也能继承头文件路径。target_link_libraries(demo_app PRIVATE demo_core)表示demo_app链接demo_core。install(...)让产物可以统一安装到bin、lib、include。
配置说明书:从零使用 CMake 构建项目
1. 准备工具
需要安装:
- CMake。
- C/C++ 编译器,例如 GCC、Clang 或 MSVC。
- 构建工具,例如 Make、Ninja 或 Visual Studio Build Tools。
验证:
cmake --version2. 编写项目入口配置
每个 CMake 项目根目录都需要一个 CMakeLists.txt。建议固定包含这些内容:
cmake_minimum_required(VERSION 3.20)
project(MyProject LANGUAGES CXX)
add_executable(my_app
src/main.cpp
)3. 生成构建目录
cmake -S . -B build含义:
-S .:源码目录是当前目录。-B build:构建目录是build。
4. 编译
cmake --build build多核编译:
cmake --build build --parallel5. 指定构建类型
单配置生成器,例如 Makefile、Ninja:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build多配置生成器,例如 Visual Studio:
cmake -S . -B build
cmake --build build --config Release6. 清理和重新配置
普通重新编译:
cmake --build build配置混乱或切换生成器时,删除 build 目录后重新生成:
cmake -S . -B build
cmake --build build核心命令自查表
| 命令 | 作用 |
|---|---|
cmake --version | 查看 CMake 版本 |
cmake -S . -B build | 使用当前目录源码生成 build 构建目录 |
cmake -S . -B build -G Ninja | 指定使用 Ninja 生成器 |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug | 配置 Debug 构建 |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release | 配置 Release 构建 |
cmake --build build | 编译 build 目录中的项目 |
cmake --build build --parallel | 并行编译 |
cmake --build build --target demo_app | 只构建指定目标 |
cmake --build build --config Release | 多配置生成器下构建 Release |
cmake --install build | 执行安装规则 |
cmake --install build --prefix ./dist | 安装到指定目录 |
ctest --test-dir build | 在构建目录中运行测试 |
常见变量自查表
| 变量 | 作用 |
|---|---|
CMAKE_SOURCE_DIR | 顶层源码目录 |
CMAKE_BINARY_DIR | 顶层构建目录 |
CMAKE_CURRENT_SOURCE_DIR | 当前 CMakeLists.txt 所在源码目录 |
CMAKE_CURRENT_BINARY_DIR | 当前 CMakeLists.txt 对应构建目录 |
PROJECT_SOURCE_DIR | 当前项目源码目录 |
PROJECT_BINARY_DIR | 当前项目构建目录 |
CMAKE_BUILD_TYPE | 单配置生成器的构建类型,如 Debug、Release |
CMAKE_CXX_STANDARD | 全局 C++ 标准设置 |
CMAKE_INSTALL_PREFIX | 默认安装前缀 |
推荐实践
- 使用
cmake -S . -B build,不要在源码目录里直接执行cmake .。 - 优先使用
target_*命令配置目标,例如target_include_directories、target_link_libraries、target_compile_options。 - 库和可执行程序分别建目标,不要把所有源码都堆进一个
add_executable。 - 公共头文件路径使用
PUBLIC,只给当前目标使用的路径用PRIVATE。 - 业务项目中建议显式写
cmake_minimum_required、project、语言标准和安装规则。 - 第三方依赖优先使用包管理器或
find_package,不要在业务CMakeLists.txt中写死本机绝对路径。