一、实用但较少使用的 CMake 命令
-
file(GENERATE ...)
该命令用于在配置阶段完成之后、构建之前生成文件内容,例如从模板生成配置头文件。它支持使用生成器表达式(generator expressions),能够根据构建配置动态调整输出内容。
file(GENERATE ...)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/config.hpp INPUT ${CMAKE_SOURCE_DIR}/config.hpp.in)
-
add_custom_target(NAME ALL ...) 与 add_custom_command() 配合使用
将自定义构建步骤自动纳入默认构建流程中,常用于代码生成、资源预处理等场景。通过设置 NAME 和 ALL 参数,可确保该目标在每次构建时都被执行。
add_custom_target(NAME ALL ...)
add_custom_command()
ALL
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/generated.cpp
COMMAND python ${CMAKE_SOURCE_DIR}/gen.py > ${CMAKE_BINARY_DIR}/generated.cpp
DEPENDS gen.py)
add_custom_target(gen ALL DEPENDS ${CMAKE_BINARY_DIR}/generated.cpp)
-
target_link_options() 与 target_compile_options()
相较于全局设置链接或编译选项的方式,这两个命令允许针对特定目标进行精细化控制,是现代 CMake 推荐的做法,提升项目的模块化和可维护性。
target_link_options()
target_compile_options()
set(CMAKE_CXX_FLAGS ...)
target_compile_options(mylib PRIVATE -march=native)
target_link_options(myexe PRIVATE -Wl,--no-undefined) # Linux
-
target_precompile_headers() (CMake 3.16 及以上版本)
支持为指定目标配置预编译头文件(PCH),在大型项目中能显著减少重复头文件解析时间,加快整体编译速度。
target_precompile_headers()
target_precompile_headers(myapp PRIVATE <vector> <string> "common.hpp")
-
set_property() 与 get_property()
用于读取或修改 CMake 对象(如目标、源文件、目录、测试等)的属性值,适用于需要精细控制构建行为的高级用例。
set_property()
get_property()
set_property(SOURCE foo.cpp APPEND PROPERTY COMPILE_DEFINITIONS DEBUG_MODE)
-
try_compile() 与 try_run()
在配置阶段尝试编译或运行一小段代码,常用于探测编译器特性支持情况、库是否存在或平台能力判断。
try_compile()
try_run()
try_compile(HAVE_OPENMP ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tests/test_openmp.cpp)
-
cmake_path() (CMake 3.20 起支持)
提供跨平台安全的路径操作功能,替代传统的字符串拼接方式,避免因路径分隔符差异导致的问题。
cmake_path()
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH parent_dir)
cmake_path(SET config_file NORMALIZE "${parent_dir}/etc/config.txt")
-
FetchContent_Declare() 与 FetchContent_MakeAvailable()
实现依赖项的声明与即时获取,无需借助外部包管理工具,是现代 CMake 推荐的内建依赖管理方案。
FetchContent_Declare()
FetchContent_MakeAvailable()
include(FetchContent)
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz)
FetchContent_MakeAvailable(json)
二、实用但不常见的 CMake 内置系统变量
-
CMAKE_HOST_SYSTEM_NAME 与 CMAKE_HOST_SYSTEM_PROCESSOR
提供主机系统的名称和处理器架构信息,常用于交叉编译环境中的条件判断。
示例值包括:
CMAKE_HOST_SYSTEM_NAME
Linux, CMAKE_HOST_SYSTEM_PROCESSOR
Windows,
Linux
Darwin, Windows
FreeBSD,
Darwin
x86_64, x86_64
ARM, aarch64
aarch64
-
CMAKE__COMPILER_ID
标识当前使用的编译器类型(如 GNU、Clang、MSVC 等),可用于编写针对不同编译器的条件逻辑。
CMAKE_<LANG>_COMPILER_ID
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(mylib PRIVATE -fopenmp)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(mylib PRIVATE /openmp)
endif()
-
CMAKE_BUILD_TYPE
在单配置生成器(如 Makefile 或 Ninja)中控制构建模式(如 Debug、Release)。此变量对多配置生成器(如 Visual Studio)无效。
影响 CMAKE_CXX_FLAGS 和其他相关标志的设定。
CMAKE_BUILD_TYPE
Debug
Release
-
CMAKE_MSVC_RUNTIME_LIBRARY (CMake 3.15+)
统一控制 MSVC 下运行时库的选择(静态或动态链接),避免手动添加编译选项,提高配置一致性。
可选值如:
CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreadedDLL
/MT
MultiThreadedDebugDLL
/MD
等
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
-
CMAKE_CURRENT_FUNCTION 与 CMAKE_CURRENT_FUNCTION_LIST_LINE
在编写函数或宏时,可用于调试定位当前执行位置及调用上下文。
CMAKE_CURRENT_FUNCTION
CMAKE_CURRENT_FUNCTION_LIST_LINE
-
CMAKE_ARGV 与 CMAKE_ARGC
分别表示传递给 CMake 的完整命令行参数列表及其数量,适合用于封装脚本或自动化工具中解析输入参数。
CMAKE_ARGV
CMAKE_ARGC
-
CMAKE_GENERATOR_PLATFORM 与 CMAKE_GENERATOR_TOOLSET
用于支持 Visual Studio 或 Xcode 等多配置生成器时指定目标平台或工具集。
示例命令:
cmake -G "Visual Studio 17 2022" -A x64 -T host=x64 ...
CMAKE_GENERATOR_PLATFORM
CMAKE_GENERATOR_TOOLSET
-
CMAKE__STANDARD_REQUIRED
设为 TRUE 时,若请求的标准不被支持则直接报错,比仅设置标准版本更严格,有助于保障代码兼容性。
CMAKE_<LANG>_STANDARD_REQUIRED
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
三、CMake 使用技巧汇总
- 利用 message() 命令结合 STATUS、WARNING 或 FATAL_ERROR 级别输出信息,帮助追踪 CMake 脚本执行流程,辅助调试。
--trace
--trace-expand
- 灵活运用生成器表达式(Generator Expressions),例如
$<CONFIG:Release>、$<TARGET_PROPERTY:...> 等,在不生成额外构建配置的情况下实现条件逻辑控制。
$<IF:...>
用条件逻辑在构建时进行控制,而非在配置时处理,从而确保构建过程的稳定性。
CMAKE_POLICY(VERSION ...)
通过该方式锁定行为,可有效防止因新版 CMake 默认策略发生变化而导致构建失败或行为异常。