CMake的if语句不支持圆括号包裹条件,需直接写if(condition);布尔逻辑用AND/OR/NOT;判断变量存在用DEFINED,字符串比较用STREQUAL;缓存变量与普通变量行为不同,if判断需注意作用域和配置时机。

if 语句的基本写法和括号规则
CMake 的 if 不是类 C 语法,不支持 if (condition) 这种带圆括号的写法。括号在 CMake 中只用于分组或函数调用,不是语法必需;写多了反而容易出错。
- 条件表达式直接跟在
if后面,空格分隔 -
endif()必须配对,括号里可以写任意标识(如endif(TEST)),但推荐留空或写上同名关键字增强可读性 - 布尔逻辑用
AND、OR、NOT(全大写),不能用&&或||
if(WIN32)
message("Windows platform")
elseif(APPLE)
message("macOS platform")
else()
message("Other OS")
endif()字符串比较和变量存在性判断
CMake 把未定义变量当作空字符串处理,所以 if(VAR) 无法区分“未定义”和“值为空”。真正安全的写法是用 DEFINED、EXISTS 等关键字。
-
if(DEFINED VAR):判断变量是否被set()过(哪怕设为空) -
if(VAR STREQUAL "value"):严格字符串相等(推荐,STREQ已弃用) -
if(VAR MATCHES "^foo.*$"):正则匹配,注意转义需双反斜杠 -
if(EXISTS "/path/to/file"):检查路径是否存在(文件或目录)
错误写法:if(${VAR} STREQUAL "on") —— 如果 VAR 未定义,会变成 if("" STREQUAL "on"),看似能运行,但掩盖了变量缺失问题。
常见陷阱:缓存变量 vs 普通变量
缓存变量(set(VAR val CACHE STRING "..."))和普通变量行为不同,直接影响 if 判断结果:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 缓存变量即使被
unset(),仍保留在 CMakeCache.txt 中,下次 configure 时自动恢复 -
if(CMAKE_BUILD_TYPE)在首次 configure 时通常为空(除非手动指定),但后续 configure 可能已有值 - 使用
if(NOT CMAKE_BUILD_TYPE)判断是否首次设置,不如显式检查DEFINED CMAKE_BUILD_TYPE可靠
典型误判场景:在 CMakeLists.txt 开头写 if(CMAKE_BUILD_TYPE STREQUAL "Debug"),结果第一次 configure 时条件为假,但用户以为它该生效——其实此时 CMAKE_BUILD_TYPE 根本没被 set 过。
嵌套 if 和作用域问题
CMake 的变量默认是当前目录作用域,if 块内部定义的变量不会自动提升到外层:
-
set(FLAG ON)写在if块内,只在该块内有效(除非加PARENT_SCOPE) - 多层嵌套时,每个
endif()必须与对应if对齐,缩进不解决匹配问题 - 不支持
elif,必须用elseif(),且只能接在if()或另一个elseif()后面
最易忽略的一点:CMake 的 if 是配置时求值,不是构建时。所有判断都在 cmake 配置阶段完成,后续 make/ninja 过程中无法再改变逻辑分支。

















