cmake

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CMake

CMake

Purpose

用途

Guide agents through modern (target-first) CMake for C/C++ projects: out-of-source builds, dependency management, generator selection, and integration with CI and IDEs.
指导Agent为C/C++项目使用现代的(以目标为核心的)CMake:实现源码外构建、依赖管理、生成器选择,以及与CI和IDE的集成。

Triggers

触发场景

  • "How do I write a CMakeLists.txt for my project?"
  • "How do I add an external library with CMake?"
  • "CMake can't find my package / library"
  • "How do I enable sanitizers in CMake?"
  • "How do I cross-compile with CMake?"
  • "How do I use CMake Presets?"
  • "我该如何为项目编写CMakeLists.txt?"
  • "怎么用CMake添加外部库?"
  • "CMake找不到我的包/库"
  • "怎么在CMake中启用sanitizers?"
  • "怎么用CMake进行交叉编译?"
  • "怎么使用CMake Presets?"

Workflow

工作流程

1. Modern CMake principles

1. 现代CMake原则

  • Define targets, not variables. Use
    target_*
    commands.
  • Use
    PUBLIC
    /
    PRIVATE
    /
    INTERFACE
    to control property propagation.
  • Never use
    include_directories()
    or
    link_libraries()
    (legacy).
  • Minimum CMake version:
    cmake_minimum_required(VERSION 3.20)
    for most features.
  • 定义目标而非变量,优先使用
    target_*
    系列命令。
  • 使用
    PUBLIC
    /
    PRIVATE
    /
    INTERFACE
    控制属性的传播范围。
  • 不要使用
    include_directories()
    link_libraries()
    (属于遗留用法)。
  • 最低CMake版本要求:大多数功能需要
    cmake_minimum_required(VERSION 3.20)

2. Minimal project

2. 最小项目示例

cmake
cmake_minimum_required(VERSION 3.20)
project(MyApp VERSION 1.0 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(myapp
    src/main.c
    src/utils.c
)

target_include_directories(myapp PRIVATE include)
target_compile_options(myapp PRIVATE -Wall -Wextra)
cmake
cmake_minimum_required(VERSION 3.20)
project(MyApp VERSION 1.0 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(myapp
    src/main.c
    src/utils.c
)

target_include_directories(myapp PRIVATE include)
target_compile_options(myapp PRIVATE -Wall -Wextra)

3. Static / shared libraries

3. 静态/共享库配置

cmake
undefined
cmake
undefined

Static library

静态库

add_library(mylib STATIC lib/foo.c lib/bar.c) target_include_directories(mylib PUBLIC include # consumers get this include path PRIVATE src # only mylib itself sees this )
add_library(mylib STATIC lib/foo.c lib/bar.c) target_include_directories(mylib PUBLIC include # 依赖该库的目标可访问这个头文件路径 PRIVATE src # 仅mylib自身可访问该路径 )

Shared library

共享库

add_library(myshared SHARED lib/foo.c) set_target_properties(myshared PROPERTIES VERSION 1.0.0 SOVERSION 1 )
add_library(myshared SHARED lib/foo.c) set_target_properties(myshared PROPERTIES VERSION 1.0.0 SOVERSION 1 )

Link executable against library

将可执行文件与库链接

add_executable(myapp src/main.c) target_link_libraries(myapp PRIVATE mylib)
undefined
add_executable(myapp src/main.c) target_link_libraries(myapp PRIVATE mylib)
undefined

4. Configure and build

4. 配置与构建

bash
undefined
bash
undefined

Out-of-source build (always do this)

源码外构建(推荐始终使用该方式)

cmake -S . -B build cmake --build build
cmake -S . -B build cmake --build build

With generator

指定生成器

cmake -S . -B build -G Ninja cmake --build build -- -j$(nproc)
cmake -S . -B build -G Ninja cmake --build build -- -j$(nproc)

Debug build

Debug构建

cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug cmake --build build-debug
cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug cmake --build build-debug

Release

Release构建

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

Install

安装

cmake --install build --prefix /usr/local

Build types: `Debug`, `Release`, `RelWithDebInfo`, `MinSizeRel`.
cmake --install build --prefix /usr/local

构建类型:`Debug`、`Release`、`RelWithDebInfo`、`MinSizeRel`。

5. External dependencies

5. 外部依赖管理

find_package (system-installed libraries)

find_package(系统已安装的库)

cmake
find_package(OpenSSL REQUIRED)
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto)

find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

find_package(ZLIB REQUIRED)
target_link_libraries(myapp PRIVATE ZLIB::ZLIB)
cmake
find_package(OpenSSL REQUIRED)
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto)

find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

find_package(ZLIB REQUIRED)
target_link_libraries(myapp PRIVATE ZLIB::ZLIB)

FetchContent (download and build dependency)

FetchContent(下载并构建依赖)

cmake
include(FetchContent)

FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG        v1.14.0
)
FetchContent_MakeAvailable(googletest)

add_executable(mytest test/test_foo.cpp)
target_link_libraries(mytest PRIVATE GTest::gtest_main mylib)
cmake
include(FetchContent)

FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG        v1.14.0
)
FetchContent_MakeAvailable(googletest)

add_executable(mytest test/test_foo.cpp)
target_link_libraries(mytest PRIVATE GTest::gtest_main mylib)

pkg-config fallback

pkg-config备选方案

cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBFOO REQUIRED libfoo>=1.2)
target_link_libraries(myapp PRIVATE ${LIBFOO_LIBRARIES})
target_include_directories(myapp PRIVATE ${LIBFOO_INCLUDE_DIRS})
cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBFOO REQUIRED libfoo>=1.2)
target_link_libraries(myapp PRIVATE ${LIBFOO_LIBRARIES})
target_include_directories(myapp PRIVATE ${LIBFOO_INCLUDE_DIRS})

6. Compiler options by configuration

6. 按构建配置设置编译器选项

cmake
target_compile_options(myapp PRIVATE
    $<$<CONFIG:Debug>:-g -Og -fsanitize=address>
    $<$<CONFIG:Release>:-O2 -DNDEBUG>
    $<$<CXX_COMPILER_ID:GNU>:-fanalyzer>
    $<$<CXX_COMPILER_ID:Clang>:-Weverything>
)

target_link_options(myapp PRIVATE
    $<$<CONFIG:Debug>:-fsanitize=address>
)
Generator expressions:
$<condition:value>
evaluated at build time.
cmake
target_compile_options(myapp PRIVATE
    $<$<CONFIG:Debug>:-g -Og -fsanitize=address>
    $<$<CONFIG:Release>:-O2 -DNDEBUG>
    $<$<CXX_COMPILER_ID:GNU>:-fanalyzer>
    $<$<CXX_COMPILER_ID:Clang>:-Weverything>
)

target_link_options(myapp PRIVATE
    $<$<CONFIG:Debug>:-fsanitize=address>
)
生成器表达式:
$<condition:value>
会在构建阶段进行求值。

7. Enable sanitizers

7. 启用sanitizers

cmake
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)

if(ENABLE_ASAN)
    target_compile_options(myapp PRIVATE -fsanitize=address -fno-omit-frame-pointer -g -O1)
    target_link_options(myapp PRIVATE -fsanitize=address)
endif()
Build:
cmake -DENABLE_ASAN=ON -S . -B build-asan && cmake --build build-asan
cmake
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)

if(ENABLE_ASAN)
    target_compile_options(myapp PRIVATE -fsanitize=address -fno-omit-frame-pointer -g -O1)
    target_link_options(myapp PRIVATE -fsanitize=address)
endif()
构建命令:
cmake -DENABLE_ASAN=ON -S . -B build-asan && cmake --build build-asan

8. Cross-compilation toolchain file

8. 交叉编译工具链文件

cmake
undefined
cmake
undefined

toolchain-aarch64.cmake

toolchain-aarch64.cmake

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_SYSROOT /opt/aarch64-sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

```bash
cmake -S . -B build-arm -DCMAKE_TOOLCHAIN_FILE=toolchain-aarch64.cmake
set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_SYSROOT /opt/aarch64-sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

```bash
cmake -S . -B build-arm -DCMAKE_TOOLCHAIN_FILE=toolchain-aarch64.cmake

9. CMake Presets (CMake 3.20+)

9. CMake Presets(CMake 3.20及以上版本支持)

json
{
  "version": 6,
  "configurePresets": [
    {
      "name": "release",
      "displayName": "Release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/release",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
      }
    },
    {
      "name": "debug",
      "displayName": "Debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "ENABLE_ASAN": "ON"
      }
    }
  ],
  "buildPresets": [
    { "name": "release", "configurePreset": "release" },
    { "name": "debug",   "configurePreset": "debug" }
  ]
}
bash
cmake --preset release
cmake --build --preset release
json
{
  "version": 6,
  "configurePresets": [
    {
      "name": "release",
      "displayName": "Release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/release",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
      }
    },
    {
      "name": "debug",
      "displayName": "Debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "ENABLE_ASAN": "ON"
      }
    }
  ],
  "buildPresets": [
    { "name": "release", "configurePreset": "release" },
    { "name": "debug",   "configurePreset": "debug" }
  ]
}
bash
cmake --preset release
cmake --build --preset release

10. Common errors

10. 常见错误

ErrorCauseFix
Could not find package Foo
Package not installed or wrong prefixInstall dev package; set
CMAKE_PREFIX_PATH
No CMAKE_CXX_COMPILER
No C++ compiler foundInstall g++/clang++; check PATH
target_link_libraries called with wrong number of arguments
Missing
PUBLIC/PRIVATE/INTERFACE
Add the keyword
Cannot find source file
Typo or wrong relative pathCheck path relative to
CMakeLists.txt
generator expression
error
Wrong
$<>
syntax
Check CMake docs for expression name
For a complete CMakeLists.txt template, see references/templates.md.
错误原因解决方法
Could not find package Foo
依赖包未安装或前缀路径错误安装对应开发包;设置
CMAKE_PREFIX_PATH
No CMAKE_CXX_COMPILER
未找到C++编译器安装g++/clang++;检查PATH环境变量
target_link_libraries called with wrong number of arguments
缺少
PUBLIC/PRIVATE/INTERFACE
关键字
补充对应的访问控制关键字
Cannot find source file
文件名拼写错误或相对路径错误检查相对于当前
CMakeLists.txt
的路径是否正确
generator expression
error
$<>
语法使用错误
查阅CMake官方文档确认表达式的正确写法
完整的CMakeLists.txt模板可参考references/templates.md

Related skills

相关技能

  • Use
    skills/build-systems/ninja
    for Ninja generator details
  • Use
    skills/build-systems/make
    for Make generator
  • Use
    skills/compilers/cross-gcc
    for cross-compilation toolchain setup
  • Use
    skills/runtimes/sanitizers
    for sanitizer integration details
  • 如需了解Ninja生成器的详细用法,可使用
    skills/build-systems/ninja
    技能
  • 如需了解Make生成器的详细用法,可使用
    skills/build-systems/make
    技能
  • 如需了解交叉编译工具链的配置方法,可使用
    skills/compilers/cross-gcc
    技能
  • 如需了解sanitizer集成的详细信息,可使用
    skills/runtimes/sanitizers
    技能