我何时应该在CMake中使用$ {...}包装变量?

dan*_*jar 20 cmake

我想知道为什么CMake中的变量经常用美元符号和大括号括起来.例如,我在CMake教程中看到了这个调用.

include_directories(${PROJECT_BINARY_DIR})
Run Code Online (Sandbox Code Playgroud)

但是从我的尝试来看,这也是一样的.

include_directories(PROJECT_BINARY_DIR)
Run Code Online (Sandbox Code Playgroud)

${...}什么时候需要包装,这是什么意思?为什么变量经常包含在内,即使它没有任何区别?

Com*_*sMS 20

引用CMake文档:

变量参考的形式${variable_name}和一个引用参数或无报价参数内进行评价.变量引用将替换为变量的值,如果未设置变量,则替换为空字符串.

换句话说,PROJECT_BINARY_DIR字面意思是指字符串"PROJECT_BINARY_DIR".将其封装${...}为您提供名称为PROJECT_BINARY_DIR的变量的内容.

考虑:

set(FOO "Hello there!")
message(FOO)     # prints FOO
message(${FOO})  # prints Hello there!
Run Code Online (Sandbox Code Playgroud)

您可能已经猜到了,include_directories(PROJECT_BINARY_DIR)只需尝试将名称PROJECT_BINARY_DIR的子目录添加到include目录中.在大多数构建系统中,如果不存在这样的目录,它将简单地忽略该命令,这可能会让您感觉它按预期工作.

一个流行的混淆来源于if()不需要显式解除引用变量的事实:

set(FOO TRUE)
if(FOO)
    message("Foo was set!")
endif()
Run Code Online (Sandbox Code Playgroud)

文档再次解释了这种行为:

if(<constant>)

如果常量为1,ON,YES,TRUE,Y或非零数字,则为真.如果常量为0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,空字符串或以后缀-NOTFOUND结尾,则返回false.命名的布尔常量不区分大小写.如果参数不是这些常量之一,则将其视为变量.

if(<variable>)

如果变量定义为不是false常量的值,则为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()
Run Code Online (Sandbox Code Playgroud)

这将采用TRUE变量情况下的FALSE分支,以及常数情况下的分支.这是因为在常量情况下,CMake将寻找一个变量BLA来执行检查(未定义,因此我们最终进入FALSE分支).

  • `if()`是一种特殊情况,因为它适用于变量和值.虽然`if(SFML_FOUND)`和`if($ {SFML_FOUND})`可能都有效,但它们实际上做了不同的事情:检查[if`的文档](http://www.cmake.org/cmake/help /v3.0/command/if.html)并特别注意`if(<constant>)`和`if(<variable>)`之间的区别.我会相应地更新答案. (3认同)
  • 那么“if (SFML_FOUND)”之类的东西是如何工作的呢? (2认同)