目录

CMake属性

属性几乎影响着构建过程的所有方面,它附属于一个特定的实体,无论是目录、目标、源文件、测试用例、缓存变量甚至是整个构建过程本身。属性并不像变量那样持有一个独立的值,而是为它所连接的实体提供特定的信息。CMake用于相关属性和变量的名称通常遵循相同的模式:变量名称=CMAKE_属性名称。

通用属性命令

CMake提供了许多操作属性的命令,其中最通用的set_property和get_property命令,允许在任何类型的实体上设置和获取任何属性。语法如下:

1
2
3
set_property(entitySpecific
    [APPEND] [APPEND_STRING]
    PROPERTY propName [value1 [value2 [...]]])

entitySpecific为被设置属性的实体,它必须是以下之一:

1
2
3
4
5
6
7
GLOBAL
DIRECTORY [dir]
TARGET [target1 [target2 [...]]]
SOURCE [source1 [source2 [...]]]
INSTALL [file1 [file2 [...]]]
TEST [test1 [test2 [...]]]
CACHE [var1 [var2 [...]]]

GLOBAL是指构建本身,所以不需要具体的实体名称。对于DIRECTORY,如果没有指定目录,就会使用当前的源码目录。

PROPERTY关键字后面是属性名称和它的值,propName通常是CMake文档中定义的属性。除了CMake定义的属性外,项目也可以创建新的属性。如果创建新属性,最好避免与CMake或其他第三方包定义的属性发生潜在的名称冲突。

APPEND和APPEND_STRING关键字可以用来控制属性值如何被更新。默认情况下用新值替换旧值,APPEND将旧值和新值组成一个列表,而APPEND_STRING将旧值和新值连接成字符串。如下表:

旧值 新值 无关键字 APPEND关键字 APPEND_STRING关键字
foo bar bar foo;bar foobar
a;b c;d c;d a;b;c;d a;bc;d

get_property语法如下:

1
2
3
get_property(resultVar entitySpecific
    PROPERTY propName
    [DEFINED | SET | BRIEF_DOCS | FULL_DOCS])

resultVar变量用于存储获取到的属性值。和set_property类似,entitySpecific必须是以下之一:

1
2
3
4
5
6
7
8
GLOBAL
DIRECTORY [dir]
TARGET target
SOURCE source
INSTALL file
TEST test
CACHE var
VARIABLE

VARIABLE类型有点不同,变量名称是由propName指定,而不是附加载VARIABLE关键字上。

如果不指定任何可选的关键字,get_property获取指定属性的值。虽然使用VARIABLE关键字可以获取到当前作用域变量的值,但是直接用${}语法比get_property更清楚和简单。可选的关键字可以用来获取关于属性的细节,而不仅仅是其值。

DEFINED

结果是一个布尔值,表明属性是否已经被定义。在VARIABLE作用域查询的情况下,只有当变量被明确地用define_property命令定义时,结果才是真的。

SET

结果是一个布尔值,表明命名的属性是否已经被设置。

BRIEF_DOCS

获取指定属性的简要文档。如果没有简要文档,返回字符串NOTFOUND。

FULL_DOCS

获取指定属性的完整文档。如果没有完整文档,返回字符串NOTFOUND。

define_property语法如下:

1
2
3
4
define_property(entityType
    PROPERTY propName [INHERITED]
    BRIEF_DOCS briefDoc [moreBriefDocs...]
    FULL_DOCS fullDoc [moreFullDocs...])

define_property命令不设置属性的值,只设置它的文档。

如果在定义一个属性时使用了INHERITED选项,那么如果该属性在当前作用域没有被设置,get_property命令将链到父作用域。VARIABLE或CACHE没有这样的功能,因为在设计上它们已经连接到父作用域。INHERITED属性的继承行为只适用于get_property命令及其它相关的获取特定属性的命令。当调用带有APPEND或APPEND_STRING选项的set_property时,只考虑属性的当前值。

全局属性

全局属性与整体的构建有关,CMake提供get_cmake_property用于查询全局属性。

1
get_cmake_property(resultVar property)

和get_property一样,resultVar用于保存查询到的属性值,property可以是任何全局属性的名称,也可以是以下伪属性之一:

  • VARIABLES:所有常规(即非缓存)变量的列表。
  • CACHE_VARIABLES:所有缓存变量的列表。
  • COMMANDS:所有定义的命令、函数和宏的列表。
  • MACROS:所有已定义的宏的列表。
  • COMPONENTS:由install命令定义的所有组件的列表

这些只读的伪属性只能通过get_cmake_property进行检索。

目录属性

为了方便起见,CMake提供了设置和获取目录属性的专用命令。设置目录属性命令定义如下:

1
set_directory_properties(PROPERTIES prop1 val1 [prop2 val2 ...])

这个命令总是应用于当前目录。获取目录属性命令有两种形式:

1
2
get_directory_property(resultVar [DIRECTORY dir] property)
get_directory_property(resultVar [DIRECTORY dir] DEFINITION varName)

第一种形式从一个特定的目录或当前目录中获取一个属性的值。第二种形式获取一个变量的值,它提供了一种从当前目录以外的不同目录作用域获取一个变量的值的方法。对于get_directory_property命令的任何一种形式,如果使用了DIRECTORY参数,这个目录必须已经被CMake处理过。

目标属性

目标属性是收集和应用关于如何将源文件变成二进制文件的大部分细节的地方。为了方便,CMake提供了目标属性相关的命令:

1
2
3
4
5
set_target_properties(target1 [target2...]
    PROPERTIES
    propertyName1 value1
    [propertyName2 value2] ... )
get_target_property(resultVar target propertyName)

set_target_properties命令不支持附加到现有的属性值上,如果需要为一个给定的属性提供一个列表值,set_target_properties命令要求该值以字符串形式指定。

源码属性

CMake提供了源码属性相关的命令:

1
2
3
4
5
set_source_files_properties(file1 [file2...]
    PROPERTIES
    propertyName1 value1
    [propertyName2 value2] ... )
get_source_file_property(resultVar sourceFile propertyName)

源码属性只对定义在同一目录范围内的目标可见。

缓存变量属性

缓存变量的一些特性最终反映在缓存变量的属性中。

  • 每个缓存变量都有一个类型,它必须是BOOL、FILEPATH、PATH、STRING或INTERNAL中的一个。这个类型可以通过get_property获得,属性名称为TYPE。
  • 缓存变量可以通过mark_as_advanced命令被标记为高级变量,这实际上只是设置了布尔值ADVANCED缓存变量属性。
  • 缓存变量的帮助字符串通常是作为调用set命令的一部分来设置的,但它也可以通过HELPSTRING缓存变量属性来修改或读取。
  • 如果一个缓存变量是STRING类型的,那么CMake GUI将寻找一个名为STRINGS的缓存变量属性。

其它属性类型

CMake提供了常见的特定测试版本的属性setter和getter命令:

1
2
3
4
5
set_tests_properties(test1 [test2...]
    PROPERTIES
    propertyName1 value1
    [propertyName2 value2] ... )
get_test_property(resultVar test propertyName)