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_COMPILER | C++ 编译器 |
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})