我想知道为什么CMake中的变量经常用美元符号和大括号括起来。例如,我看到了这个电话in a CMake tutorial。
include_directories(${PROJECT_BINARY_DIR})
但是从我的尝试来看,这也是做同样的事情。
include_directories(PROJECT_BINARY_DIR)
何时需要${...}
包裹,这是什么意思?为什么变量经常包含在内,即使它没有任何区别?
答案 0 :(得分:19)
变量引用的格式为
${variable_name}
,并进行评估 在引用的参数或不带引号的参数中。变量引用 由变量的值替换,或由空字符串if替换 该变量未设置。
换句话说,写PROJECT_BINARY_DIR
字面意思是字符串“PROJECT_BINARY_DIR”。将其封装在${...}
中会为您提供变量的内容,名称为PROJECT_BINARY_DIR。
考虑:
set(FOO "Hello there!")
message(FOO) # prints FOO
message(${FOO}) # prints Hello there!
正如您可能已经猜到的那样,include_directories(PROJECT_BINARY_DIR)
只是尝试将名称PROJECT_BINARY_DIR的子目录添加到包含目录中。在大多数构建系统中,如果不存在这样的目录,它将完全忽略该命令,这可能会让您觉得它按预期工作。
一个流行的混淆来源于if()
不需要显式解除引用变量的事实:
set(FOO TRUE)
if(FOO)
message("Foo was set!")
endif()
再次the documentation explains this behavior:
if(<constant>)
如果常量为1,ON,YES,TRUE,Y或非零数字,则为真。如果常量为0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,则为False 空字符串,或以后缀-NOTFOUND结尾。命名的布尔常量 不区分大小写。如果参数不是这些常量之一, 它被视为变量。
if(<variable>)
如果变量定义为不是假常量的值,则为true。否则就错了。 (注意宏参数不是变量。)
特别是,人们可以提出一些奇怪的例子:
unset(BLA)
set(FOO "BLA")
if(FOO)
message("if(<variable>): True")
else()
message("if(<variable>): False")
endif()
if(${FOO})
message("if(<constant>): True")
else()
message("if(<constant>): False")
endif()
将在变量大小写中使用TRUE
分支,在常量大小写中使用FALSE
分支。这是因为在常量情况下,CMake将寻找变量BLA
来执行检查(未定义,因此我们最终进入FALSE分支)。