双笙子佯谬老师的【公开课】现代CMake高级教程课程笔记
第 9 章:分支与判断
BOOL 类型的值
通常来说 BOOL 类型的变量只有 ON/OFF 两种取值。但是由于历史原因,TRUE/FALSE 和 YES/NO 也可以表示 BOOL 类型。个人建议同学们始终使用 ON/OFF 避免混淆。
- https://stackoverflow.com/questions/41079291/cmake-use-of-true-false-or-on-off-or-yes-no-in-generator-expressions
- https://cmake.org/cmake/help/v3.7/command/if.html
if
if 的特点:不需要加 ${},会自动尝试作为变量名求值
由于历史原因,if 的括号中有着特殊的语法,如果是一个字符串,比如 MYVAR,则他会先看是否有 ${MYVAR} 这个变量。如果有这个变量则会被替换为变量的值来进行接下来的比较,否则保持原来字符串不变。
CMakeLists:
set(MYVAR Hello)
if (MYVAR MATCHES "Hello")message("MYVAR is Hello")
else()message("MYVAR is not Hello")
endif()
生成结果:
MYVAR is Hello
如果我加了 ${} 会怎么样呢?
if (${MYVAR} MATCHES "Hello")
会被翻译成 if (Hello MATCHES "Hello")
。但是因为找不到名为 Hello 的变量,所以会被直接当成普通的字符串来处理。
也就是 if ("Hello" MATCHES "Hello")
从而会执行真分支,结果正常。
set(MYVAR Hello)
if (${MYVAR} MATCHES "Hello")message("MYVAR is Hello")
else()message("MYVAR is not Hello")
endif()
生成结果:
MYVAR is Hello
万一好巧不巧,正好定义了 Hello 这个变量呢?
然而假如存在 Hello 这个变量,其值为 “world”。那么 if (${MYVAR} MATCHES "Hello")
会被翻译成 if (Hello MATCHES "Hello")
。而因为 Hello 这个变量名存在,所以会被(出于历史原因的)if 进一步求值:if (“world” MATCHES "Hello")
从而会执行假分支,结果不正常了。
set(Hello world)
set(MYVAR Hello)
if (${MYVAR} MATCHES "Hello")message("MYVAR is Hello")
else()message("MYVAR is not Hello")
endif()
生成结果:
MYVAR is not Hello
解决:用引号包裹起来,防止被当做变量名。
初学者如果搞不明白,可以把所有不确定的地方都套上一层引号,例如 "${MYVAR}"
,这样就可以避免被 if 当做变量名来求值了。
set(Hello world)
set(MYVAR Hello)
if ("${MYVAR}" MATCHES "Hello")message("MYVAR is Hello")
else()message("MYVAR is not Hello")
endif()
生成结果:
MYVAR is Hello