CMake 关键字
本页记录 CMakeLists.txt 中最常用的命令、变量和关键字。基础流程见 cmake基础知识。
CMakeLists.txt 基本骨架
现代 CMake 推荐围绕 target 组织配置。target 可以是可执行程序、静态库、动态库或接口库。
cmake_minimum_required(VERSION 3.20)
project(MyProject
VERSION 1.0.0
LANGUAGES CXX
)
add_library(my_library STATIC
src/library.cpp
)
target_include_directories(my_library
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_features(my_library
PUBLIC
cxx_std_17
)
add_executable(my_app
src/main.cpp
)
target_link_libraries(my_app
PRIVATE
my_library
)核心关键字自查表
| 命令/关键字 | 作用 | 常见写法 |
|---|---|---|
cmake_minimum_required | 声明最低 CMake 版本 | cmake_minimum_required(VERSION 3.20) |
project | 定义项目名称、版本、语言 | project(App VERSION 1.0 LANGUAGES CXX) |
set | 设置变量 | set(CMAKE_CXX_STANDARD 17) |
option | 定义开关选项 | option(ENABLE_TESTS "Build tests" ON) |
message | 输出配置日志 | message(STATUS "Configuring app") |
add_executable | 创建可执行程序目标 | add_executable(app src/main.cpp) |
add_library | 创建库目标 | add_library(core STATIC src/core.cpp) |
target_include_directories | 配置目标头文件目录 | target_include_directories(core PUBLIC include) |
target_link_libraries | 配置目标链接库 | target_link_libraries(app PRIVATE core) |
target_compile_features | 配置目标语言特性 | target_compile_features(core PUBLIC cxx_std_17) |
target_compile_options | 配置目标编译选项 | target_compile_options(core PRIVATE -Wall) |
target_compile_definitions | 配置宏定义 | target_compile_definitions(core PRIVATE USE_LOG) |
find_package | 查找外部依赖包 | find_package(fmt REQUIRED) |
include | 加载其他 CMake 脚本 | include(GNUInstallDirs) |
add_subdirectory | 加载子目录项目 | add_subdirectory(src) |
install | 定义安装规则 | install(TARGETS app RUNTIME DESTINATION bin) |
enable_testing | 启用测试 | enable_testing() |
add_test | 添加测试 | add_test(NAME unit COMMAND unit_tests) |
cmake_minimum_required
声明项目要求的最低 CMake 版本。它应该放在顶层 CMakeLists.txt 的第一条有效命令。
cmake_minimum_required(VERSION 3.20)作用:
- 避免用户使用过旧版本 CMake 配置项目。
- 固定 CMake 策略行为,减少不同版本之间的兼容性问题。
project
定义项目名称、版本、描述和启用语言。
project(Hello
VERSION 1.0.0
DESCRIPTION "Hello application"
LANGUAGES CXX
)常用形式:
project(Hello LANGUAGES C)
project(Hello LANGUAGES CXX)
project(Hello LANGUAGES C CXX)project 会设置一些常用变量:
| 变量 | 说明 |
|---|---|
PROJECT_NAME | 当前项目名称 |
PROJECT_VERSION | 当前项目版本 |
PROJECT_SOURCE_DIR | 当前项目源码目录 |
PROJECT_BINARY_DIR | 当前项目构建目录 |
<PROJECT-NAME>_SOURCE_DIR | 指定项目名对应的源码目录 |
<PROJECT-NAME>_BINARY_DIR | 指定项目名对应的构建目录 |
推荐在通用脚本中优先使用 PROJECT_SOURCE_DIR、PROJECT_BINARY_DIR 或 CMAKE_CURRENT_SOURCE_DIR,避免项目改名后变量名失效。
set
设置普通变量、缓存变量或 CMake 内置变量。
set(SRC_LIST
src/main.cpp
src/app.cpp
)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)常见用途:
- 保存源码列表。
- 设置语言标准。
- 设置安装路径、输出路径等配置。
更推荐的现代写法是把配置绑定到目标上:
target_compile_features(my_target PUBLIC cxx_std_17)option
定义用户可以通过 -D 修改的开关。
option(ENABLE_TESTS "Build test targets" ON)
option(ENABLE_WARNINGS "Enable compiler warnings" ON)命令行修改:
cmake -S . -B build -DENABLE_TESTS=OFF配合 if 使用:
if(ENABLE_TESTS)
enable_testing()
add_subdirectory(tests)
endif()message
输出配置阶段日志。
message(STATUS "Project source dir: ${PROJECT_SOURCE_DIR}")
message(WARNING "Optional dependency not found")
message(FATAL_ERROR "Required dependency missing")常用级别:
| 级别 | 作用 |
|---|---|
STATUS | 普通状态信息 |
WARNING | 警告,不中断配置 |
SEND_ERROR | 记录错误,配置继续执行但最终失败 |
FATAL_ERROR | 立即终止配置 |
add_executable
创建可执行文件目标。
add_executable(demo_app
src/main.cpp
src/app.cpp
)目标名 demo_app 是 CMake 内部使用的 target 名称,最终文件名默认也会使用它。可以通过目标属性修改输出名:
set_target_properties(demo_app PROPERTIES
OUTPUT_NAME demo
)add_library
创建库目标。
add_library(core STATIC
src/core.cpp
)
add_library(plugin SHARED
src/plugin.cpp
)
add_library(headers_only INTERFACE)库类型:
| 类型 | 说明 |
|---|---|
STATIC | 静态库 |
SHARED | 动态库 |
MODULE | 插件模块库 |
INTERFACE | 只携带头文件、宏、编译选项等使用要求,不产生二进制 |
target_include_directories
给目标配置头文件搜索路径。
target_include_directories(core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)可见性含义:
| 可见性 | 含义 |
|---|---|
PRIVATE | 只给当前目标使用 |
PUBLIC | 当前目标使用,依赖它的目标也继承 |
INTERFACE | 当前目标不用,依赖它的目标继承 |
经验规则:
- 公开头文件目录通常写
PUBLIC。 - 源码内部目录通常写
PRIVATE。 - 头文件库通常写
INTERFACE。
target_link_libraries
给目标链接库或声明目标之间的依赖关系。
target_link_libraries(demo_app
PRIVATE
core
)链接第三方包时也使用这个命令:
find_package(fmt REQUIRED)
target_link_libraries(demo_app
PRIVATE
fmt::fmt
)PRIVATE、PUBLIC、INTERFACE 的含义和头文件目录相同。业务程序链接内部库时通常使用 PRIVATE;库的公开 API 暴露了某个依赖的类型时,才需要使用 PUBLIC。
target_compile_features
给目标声明需要的 C++ 标准或编译特性。
target_compile_features(core
PUBLIC
cxx_std_17
)相比全局设置 CMAKE_CXX_STANDARD,这个写法更精确,因为它描述的是目标自己的使用要求。
target_compile_options
给目标添加编译器参数。
if(MSVC)
target_compile_options(core PRIVATE /W4)
else()
target_compile_options(core PRIVATE -Wall -Wextra -Wpedantic)
endif()注意:
- 不同编译器参数不完全相同,需要区分 MSVC、GCC、Clang。
- 优先绑定到具体目标,避免全局污染第三方库。
target_compile_definitions
给目标添加宏定义。
target_compile_definitions(core
PRIVATE
CORE_ENABLE_LOG
PUBLIC
CORE_USE_FAST_MATH
)等价于给编译器传入:
-DCORE_ENABLE_LOG如果宏会影响公开头文件中的 API,需要考虑使用 PUBLIC。
add_subdirectory
把子目录中的 CMakeLists.txt 加入当前构建。
add_subdirectory(src)
add_subdirectory(tests)常见项目结构:
project/
├── CMakeLists.txt
├── src/
│ └── CMakeLists.txt
└── tests/
└── CMakeLists.txt适合中大型项目按模块拆分配置。
find_package
查找外部依赖包。
find_package(fmt REQUIRED)
target_link_libraries(demo_app
PRIVATE
fmt::fmt
)常见参数:
| 参数 | 作用 |
|---|---|
REQUIRED | 找不到就配置失败 |
QUIET | 找不到时减少输出 |
COMPONENTS | 指定包组件 |
示例:
find_package(Boost REQUIRED COMPONENTS filesystem system)install
定义安装规则,让构建产物可以被安装到统一目录。
include(GNUInstallDirs)
install(TARGETS demo_app core
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)执行安装:
cmake --install build --prefix ./dist安装目标说明:
| 目标类型 | 常见安装目录 |
|---|---|
RUNTIME | 可执行文件,通常是 bin |
LIBRARY | 动态库,通常是 lib |
ARCHIVE | 静态库,通常是 lib |
| 头文件目录 | 通常是 include |
测试相关关键字
启用测试:
enable_testing()添加测试目标:
add_executable(unit_tests
tests/test_calculator.cpp
)
target_link_libraries(unit_tests
PRIVATE
core
)
add_test(NAME calculator_tests COMMAND unit_tests)运行测试:
ctest --test-dir build条件判断关键字
if(WIN32)
message(STATUS "Configuring on Windows")
elseif(APPLE)
message(STATUS "Configuring on macOS")
elseif(UNIX)
message(STATUS "Configuring on Unix-like system")
endif()常见条件变量:
| 变量 | 说明 |
|---|---|
WIN32 | Windows 平台 |
APPLE | Apple 平台 |
UNIX | Unix-like 平台,包括 Linux 和 macOS |
MSVC | Microsoft Visual C++ 编译器 |
CMAKE_CXX_COMPILER_ID | C++ 编译器 ID,如 GNU、Clang、MSVC |
变量引用和列表
变量引用:
message(STATUS "Source dir: ${CMAKE_CURRENT_SOURCE_DIR}")列表变量:
set(SOURCES
src/main.cpp
src/app.cpp
src/service.cpp
)
add_executable(app
${SOURCES}
)追加列表:
list(APPEND SOURCES
src/new_feature.cpp
)完整可直接使用的 CMakeLists.txt 模板
适用于常见 C++ 业务程序:一个内部库、一个可执行程序、可选测试、可安装。
cmake_minimum_required(VERSION 3.20)
project(BusinessApp
VERSION 1.0.0
DESCRIPTION "Business application"
LANGUAGES CXX
)
option(BUSINESS_APP_BUILD_TESTS "Build tests" ON)
option(BUSINESS_APP_ENABLE_WARNINGS "Enable compiler warnings" ON)
add_library(business_core STATIC
src/service.cpp
src/repository.cpp
)
target_include_directories(business_core
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_features(business_core
PUBLIC
cxx_std_17
)
if(BUSINESS_APP_ENABLE_WARNINGS)
if(MSVC)
target_compile_options(business_core PRIVATE /W4)
else()
target_compile_options(business_core PRIVATE -Wall -Wextra -Wpedantic)
endif()
endif()
add_executable(business_app
src/main.cpp
)
target_link_libraries(business_app
PRIVATE
business_core
)
include(GNUInstallDirs)
install(TARGETS business_core business_app
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
if(BUSINESS_APP_BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()配套命令:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build
cmake --install build --prefix ./dist常见错误排查
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
CMakeLists.txt 修改后构建不生效 | 没有重新配置 | 重新执行 cmake -S . -B build |
| 找不到头文件 | 没有配置 target_include_directories | 给对应库或程序添加头文件目录 |
| 链接时报 unresolved symbol | 没有链接库或源码未加入目标 | 检查 target_link_libraries 和源码列表 |
| Debug/Release 参数不生效 | 生成器类型不同 | Make/Ninja 用 CMAKE_BUILD_TYPE,Visual Studio 用 --config |
| 第三方包找不到 | 没安装包或 CMAKE_PREFIX_PATH 不正确 | 安装依赖,或配置 -DCMAKE_PREFIX_PATH=... |