<<Modern CMake>> 翻译 2.1 变量和缓存
<<Modern CMake>> 翻译 2.1 变量和缓存
局部变量
我们首先来看变量。局部变量通常这样设置:
set(MY_VARIABLE "value")
变量的名称通常使用全大写字母,后面紧跟变量的值。您可以使用 ${}
来获取变量的值,例如,${MY_VARIABLE}
。1 CMake 具有作用范围的概念:在设置变量后,只要在同一范围内,你都可以存取该变量的值。 离开函数或子目录中的一个文件,变量也随之消失。 您可以在 PARENT_SCOPE
的尾部设置变量用于子作用域。
你可以设置多个值形成一个列表:
set(MY_LIST "one" "two")
这相当于多个值之间用 ; 隔开。所以以下声明和上面的效果相同:
set(MY_LIST "one;two")
list(
命令有一些实用方法来处理列表,separate_arguments
能够将一个空格分隔的字符串转为一个列表(直接修改变量值)。 请注意,CMake 中如果没有空格,值也可以不用引号引起来。 这允许您大多数时候都可以不把值用引号引起来。
使用 ${}
语法扩展变量时,对于空格的相关规则是一样的。对于文件和目录路径处理要特别小心。 因为路径可以随时包含空格,因此当它们是变量时应该始终用引号引起来(即永远不要写${MY_PATH}
,总是应该写为"${MY_PATH}"
)。
缓存变量
如果你想从命令行设置变量,CMake 会提供变量缓存。 有些变量已经内置了,比如CMAKE_BUILD_TYPE
。 这种如果变量尚未(从命令行)设置,则设置变量值的语法如下:
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")
这将不会取代已经设置的变量值,因此您可以在命令行上设置它们,而不会在执行 CMake 文件时被覆盖。 如果要将这些变量作为全局变量,你可以这样书写:
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "" FORCE)
mark_as_advanced(MY_CACHE_VARIABLE)
第一行将导致无论如何都对变量进行设置。 第二行使你运行 cmake -L ..
或使用 GUI
时,变量将不会显示在列表中。 这很常见的,因此你也可以使用 INTERNAL
类型来达到同样的效果(虽然从技术上来说它强制为 STRING 类型,但不会影响任何依赖于变量的 CMake 代码):
set(MY_CACHE_VARIABLE "VALUE" CACHE INTERNAL "")
由于 BOOL
类型非常常见,您也可以使用 option
指令简洁地设置它:
option(MY_OPTION "This is settable from the command line" OFF)
对于 BOOL
数据类型值 ON
和 OFF
,有几种不同语境。
有关 CMake
中内置变量列表,请参阅 cmake-variables。
环境变量
你也可以用 set(ENV{variable_name} value)
设置,用 $ENV{variable_name}
获取环境变量值, 但通常最好避免环境变量。
缓存
缓存实际上就是一个文本文件,CMakeCache.txt
。CMake 运行时会在构建目录中创建这个文件。 这就是 CMake 记住你设置的任何内容的方式,因此每次重新运行 CMake 时你不必重新(在命令行上)列上这些选项。
属性
CMake 存储信息的另一种方式是使用属性。 这类似于变量,但它只能附加到其他条目上,例如目录或目标。 全局属性可以作为无缓存全局变量。 许多目标属性通过从 CMAKE_
打头的相匹配的变量初始化而来。 例如,设置 CMAKE_CXX_STANDARD
意味着所有的新目标创建时都将把 CXX_STANDARD
设置为 CMAKE_CXX_STANDARD
变量的值。 设置属性有两种方法:
set_property(TARGET TargetName
PROPERTY CXX_STANDARD 11)
set_target_properties(TargetName PROPERTIES
CXX_STANDARD 11)
第一种形式更通用,可以一次设置多个目标/文件/测试,并提供有用的选项。 第二个是在一个目标上设置多个属性的快捷方式。 你可以这样获取目标属性:
get_property(ResultVariable TARGET TargetName PROPERTY CXX_STANDARD)
有关所有内置属性的列表,请参阅 cmake-properties。 在某些情况下,您也可以定义你自己的属性。2
1.if
语句有点奇怪,因为它可以使用也可以不使用包围语法来获取变量; 这是历史原因造成的:if
出现在${}
语法出现之前。 ↩
2. 例如,Interface
目标对允许的自定义属性有一些限制。 ↩