option本身不向编译器传宏,仅在CMakeLists.txt内生效;需配合add_compile_definitions(USE_MYMATH)才能使C++源码通过#ifdef USE_MYMATH感知开关。

直接说结论: option 本身不向编译器传宏,它只在 CMakeLists.txt 内部起作用;要让 C++ 源码感知开关,必须配合 add_compile_definitions(或旧式 add_definitions)显式注入预处理器定义。
为什么 option(USE_MYMATH ON) 在 C++ 里 #ifdef USE_MYMATH 不生效?
因为 option 定义的是 CMake 变量,不是 C/C++ 预处理器宏。CMake 变量只影响 CMakeLists.txt 的执行流程(比如是否走 if(USE_MYMATH) 分支),不会自动透传到编译器命令行。C++ 编译器根本看不到这个变量。
常见错误现象:CMake 配置时显示 USE_MYMATH=ON,但源码中 #ifdef USE_MYMATH 始终不进入分支。
-
option必须搭配add_compile_definitions(USE_MYMATH)才能让 C++ 看到该宏 - 如果要用带值的宏(如
#define VERSION 2),得写add_compile_definitions(VERSION=2) - 旧项目可能还在用
add_definitions(-DUSE_MYMATH),语法等价但已不推荐
option 的默认值和命令行覆盖方式
声明时指定的默认值(ON 或 OFF)只在首次配置(cmake -B build)时生效;后续重新配置必须显式传参,否则沿用缓存值。
立即学习“C++免费学习笔记(深入)”;
使用场景:CI 流水线中固定启用某功能,或本地调试时临时关闭耗时模块。
- 启用:
cmake -DUSE_MYMATH=ON -B build - 禁用:
cmake -DUSE_MYMATH=OFF -B build - 注意大小写:
On/off也认,但建议统一用全大写ON/OFF - 未声明的
-DXXX=ON不会报错,但 CMakeLists.txt 中无对应option或set就无效
比 add_compile_definitions 更灵活的方案:用 configure_file 生成头文件
当需要控制多个宏、版本号、路径等字符串常量,且希望它们在 C++ 中以 const char* 或 int 形式使用时,configure_file 比硬塞宏更安全。
性能与兼容性影响:生成的 config.h 是普通头文件,无额外开销;但每次修改 config.h.in 会触发所有包含它的源文件重编译。
- 在
CMakeLists.txt中写:configure_file(config.h.in ${CMAKE_BINARY_DIR}/config.h) -
config.h.in内容示例:#define USE_MYMATH @USE_MYMATH@(@xxx@会被 CMake 替换为变量值) - C++ 源码中
#include "config.h"即可直接用USE_MYMATH(值为1或未定义) - 注意:
configure_file默认只替换@VAR@,不支持${VAR},除非加参数@ONLY或NEWLINE_STYLE
最容易被忽略的一点:CMake 缓存变量一旦写入 CMakeCache.txt,后续 cmake -B build 不带 -D 参数就不会刷新——哪怕你改了 CMakeLists.txt 里的 option 默认值。真要重置,得删掉整个 build 目录,或者手动编辑缓存文件。


















