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

常用流程如下:

  1. 在项目根目录编写 CMakeLists.txt
  2. 执行 cmake -S . -B build 配置项目。
  3. 执行 cmake --build build 编译项目。
  4. 需要安装时执行 cmake --install build
  5. 修改源码后通常只需要重新执行 cmake --build build
  6. 修改 CMakeLists.txt 或依赖配置后,重新执行配置命令。

最小可运行示例

目录结构:

hello-cmake/
├── CMakeLists.txt
└── main.cpp

main.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/hello

Windows 使用 Visual Studio 生成器时,可执行文件通常在配置子目录中,例如:

.\build\Debug\hello.exe

业务项目常用完整示例

下面示例展示一个更接近业务项目的结构:可执行程序依赖一个项目内静态库,并配置头文件目录、编译特性、编译选项和安装规则。

目录结构:

demo-app/
├── CMakeLists.txt
├── include/
│   └── demo/
│       └── calculator.h
└── src/
    ├── calculator.cpp
    └── main.cpp

include/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(...) 让产物可以统一安装到 binlibinclude

配置说明书:从零使用 CMake 构建项目

1. 准备工具

需要安装:

  • CMake。
  • C/C++ 编译器,例如 GCC、Clang 或 MSVC。
  • 构建工具,例如 Make、Ninja 或 Visual Studio Build Tools。

验证:

cmake --version

2. 编写项目入口配置

每个 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 --parallel

5. 指定构建类型

单配置生成器,例如 Makefile、Ninja:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

多配置生成器,例如 Visual Studio:

cmake -S . -B build
cmake --build build --config Release

6. 清理和重新配置

普通重新编译:

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单配置生成器的构建类型,如 DebugRelease
CMAKE_CXX_STANDARD全局 C++ 标准设置
CMAKE_INSTALL_PREFIX默认安装前缀

推荐实践

  • 使用 cmake -S . -B build,不要在源码目录里直接执行 cmake .
  • 优先使用 target_* 命令配置目标,例如 target_include_directoriestarget_link_librariestarget_compile_options
  • 库和可执行程序分别建目标,不要把所有源码都堆进一个 add_executable
  • 公共头文件路径使用 PUBLIC,只给当前目标使用的路径用 PRIVATE
  • 业务项目中建议显式写 cmake_minimum_requiredproject、语言标准和安装规则。
  • 第三方依赖优先使用包管理器或 find_package,不要在业务 CMakeLists.txt 中写死本机绝对路径。