跳到主要内容

CMake 速查表

本页面提供 CMake 常用命令、变量和表达式的快速参考。

项目配置

基本设置

# 最低版本要求
cmake_minimum_required(VERSION 3.15)

# 项目定义
project(MyProject
VERSION 1.0.0
DESCRIPTION "Project description"
LANGUAGES CXX C
)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 或使用编译特性
target_compile_features(myapp PUBLIC cxx_std_17)

构建类型

# 设置默认构建类型
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# 可选值:Debug, Release, RelWithDebInfo, MinSizeRel

输出目录

# 可执行文件输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 库文件输出目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

目标定义

可执行文件

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

# 从列表创建
set(SOURCES src/main.cpp src/utils.cpp)
add_executable(myapp ${SOURCES})

# 静态库
add_library(mylib STATIC src/lib.cpp)

# 动态库
add_library(mylib SHARED src/lib.cpp)

# 接口库(仅头文件)
add_library(mylib INTERFACE)

# 对象库
add_library(myobj OBJECT src/obj.cpp)

编译配置

头文件路径

target_include_directories(myapp
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)

编译定义

target_compile_definitions(myapp
PRIVATE
DEBUG_MODE
VERSION="1.0"
PUBLIC
API_EXPORT
)

编译选项

target_compile_options(myapp
PRIVATE
-Wall -Wextra -Wpedantic
$<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3>
)

# MSVC 特定
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4 /utf-8>
)

# GCC/Clang 特定
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra>
)

链接库

target_link_libraries(myapp
PRIVATE
mylib # 项目内库
Threads::Threads # 系统库
PUBLIC
fmt::fmt # 外部库
)

变量

内置变量

变量说明
CMAKE_SOURCE_DIR项目根目录
CMAKE_BINARY_DIR构建目录
CMAKE_CURRENT_SOURCE_DIR当前 CMakeLists.txt 所在目录
CMAKE_CURRENT_BINARY_DIR当前构建目录
PROJECT_NAME项目名称
PROJECT_VERSION项目版本
CMAKE_CXX_COMPILERC++ 编译器
CMAKE_BUILD_TYPE构建类型
CMAKE_INSTALL_PREFIX安装前缀

变量操作

# 设置变量
set(VAR value)
set(LIST item1 item2 item3)

# 追加
list(APPEND LIST item4)
set(VAR "${VAR} more")

# 取消
unset(VAR)

# 缓存变量
set(VAR value CACHE STRING "description")
option(ENABLE_FEATURE "Enable feature" ON)

条件判断

# 基本条件
if(WIN32)
# Windows
elseif(UNIX)
# Unix/Linux
elseif(APPLE)
# macOS
endif()

# 布尔判断
if(ENABLE_FEATURE)
# ...
endif()

# 比较
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
# ...
endif()

# 版本比较
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")
# ...
endif()

# 文件存在
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h")
# ...
endif()

# 逻辑运算
if(WIN32 AND MSVC)
# ...
endif()
if(UNIX OR APPLE)
# ...
endif()
if(NOT DEBUG_MODE)
# ...
endif()

循环

# 遍历列表
foreach(file IN LISTS SOURCES)
message("File: ${file}")
endforeach()

# 遍历范围
foreach(i RANGE 0 9)
message("Number: ${i}")
endforeach()

# 遍历项
foreach(item IN ITEMS a b c)
message("Item: ${item}")
endforeach()

# while 循环
set(i 0)
while(i LESS 10)
math(EXPR i "${i} + 1")
endwhile()

函数和宏

# 函数(独立作用域)
function(add_my_executable name)
add_executable(${name} $\{ARGN\})
target_compile_features(${name} PRIVATE cxx_std_17)
endfunction()

# 调用
add_my_executable(myapp src/main.cpp)

# 宏(调用者作用域)
macro(print_var var)
message("${var} = ${${var}}")
endmacro()

文件操作

# 读取文件
file(READ "input.txt" CONTENT)

# 写入文件
file(WRITE "output.txt" "content")

# 追加
file(APPEND "log.txt" "new line\n")

# 收集文件
file(GLOB SOURCES "src/*.cpp")
file(GLOB_RECURSE SOURCES "src/**/*.cpp")

# 创建目录
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/output)

# 复制
file(COPY "data" DESTINATION "${CMAKE_BINARY_DIR}")

安装

# 安装目标
install(TARGETS myapp mylib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

# 安装文件
install(FILES include/mylib.h
DESTINATION include
)

# 安装目录
install(DIRECTORY docs/
DESTINATION share/doc/myapp
)

测试

# 启用测试
enable_testing()

# 添加测试
add_test(NAME MyTest COMMAND test_exe)
add_test(NAME MyTest COMMAND test_exe --arg1 --arg2)

# 设置测试属性
set_tests_properties(MyTest PROPERTIES
TIMEOUT 60
LABELS "unit"
)

# Google Test 集成
include(GoogleTest)
gtest_discover_tests(test_target)

依赖管理

find_package

# 查找包
find_package(Threads REQUIRED)
find_package(Boost 1.70 COMPONENTS filesystem REQUIRED)

# 使用
target_link_libraries(myapp PRIVATE
Threads::Threads
Boost::filesystem
)

FetchContent

include(FetchContent)

FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.0.0
)

FetchContent_MakeAvailable(fmt)

target_link_libraries(myapp PRIVATE fmt::fmt)

生成器表达式

常用表达式

# 构建类型
$<CONFIG:Debug> # 是否为 Debug 配置
$<$<CONFIG:Debug>:-g> # Debug 时添加 -g

# 平台
$<PLATFORM_ID:Windows>
$<PLATFORM_ID:Linux>

# 编译器
$<CXX_COMPILER_ID:GNU>
$<CXX_COMPILER_ID:MSVC>

# 目标文件
$<TARGET_FILE:myapp> # 目标文件路径
$<TARGET_FILE_DIR:myapp> # 目标文件目录

# 条件
$<IF:condition,true_value,false_value>
$<AND:cond1,cond2>
$<OR:cond1,cond2>
$<NOT:condition>

实用示例

# 根据配置设置编译选项
target_compile_options(myapp PRIVATE
$<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3 -DNDEBUG>
)

# 跨平台编译选项
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)

# 条件链接
target_link_libraries(myapp PRIVATE
$<$<PLATFORM_ID:Linux>:rt>
$<$<PLATFORM_ID:Windows>:ws2_32>
)

预设配置

CMakePresets.json 基本结构

{
"version": 6,
"cmakeMinimumRequired": { "major": 3, "minor": 25 },
"configurePresets": [
{
"name": "debug",
"displayName": "Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
],
"buildPresets": [
{
"name": "debug",
"configurePreset": "debug"
}
]
}

命令行使用

cmake --preset debug
cmake --build --preset debug
ctest --preset debug

命令行参考

cmake 命令

# 配置
cmake -B build # 指定构建目录
cmake -S . -B build # 指定源码和构建目录
cmake -G Ninja .. # 指定生成器
cmake -DCMAKE_BUILD_TYPE=Debug .. # 设置变量
cmake --preset debug # 使用预设

# 构建
cmake --build build # 构建
cmake --build build -j4 # 并行构建
cmake --build build --target myapp # 构建指定目标
cmake --build build --config Release # 多配置生成器

# 安装
cmake --install build # 安装
cmake --install build --prefix /usr # 指定安装路径

ctest 命令

ctest                                    # 运行所有测试
ctest -V # 详细输出
ctest --output-on-failure # 失败时显示输出
ctest -R "Math.*" # 运行匹配的测试
ctest -L unit # 运行指定标签的测试
ctest -j4 # 并行运行
ctest --rerun-failed # 重新运行失败的测试

cpack 命令

cpack                                    # 打包
cpack -G DEB # 指定生成器
cpack -C Release # 指定配置
cpack -B ./packages # 指定输出目录

平台宏

# 操作系统
WIN32 # Windows
UNIX # Unix/Linux/macOS
APPLE # macOS
LINUX # Linux(需要检测)
MINGW # MinGW
MSVC # MSVC 编译器

# 检测 Linux
if(UNIX AND NOT APPLE)
set(LINUX TRUE)
endif()

调试技巧

# 打印变量
message(STATUS "Variable: ${VAR}")
message(STATUS "List: ${LIST}")
message(FATAL_ERROR "Error message")

# 打印所有变量
get_cmake_property(_variableNames VARIABLES)
foreach(_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()

# 调试模式
cmake --trace ..
cmake --trace-expand ..

常见模式

现代项目结构

cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

# 设置默认构建类型
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 收集源文件
file(GLOB_RECURSE SOURCES "src/*.cpp")

# 创建目标
add_executable(myapp ${SOURCES})

# 设置包含目录
target_include_directories(myapp
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)

# 设置 C++ 标准
target_compile_features(myapp PUBLIC cxx_std_17)

# 编译选项
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)

# 查找依赖
find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

# 安装
install(TARGETS myapp RUNTIME DESTINATION bin)

静态库 + 可执行文件

# 库
add_library(mylib STATIC
src/lib.cpp
src/helper.cpp
)

target_include_directories(mylib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)

# 可执行文件
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)

条件编译

set(SOURCES
src/main.cpp
src/common.cpp
)

if(WIN32)
list(APPEND SOURCES src/windows.cpp)
elseif(UNIX)
list(APPEND SOURCES src/linux.cpp)
endif()

add_executable(myapp ${SOURCES})

参考资源