- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
get_property是 CMake 中读取属性的通用入口命令,它从全局、目录、目标、源文件、测试、缓存等多种作用域中取回属性值并存入变量。本文以 get_property 官方文档 为主体,结合 CMake 源码实现与仓库测试用例,系统讲解其完整语法、十种作用域(Scope)的语义差异、SET/DEFINED/BRIEF_DOCS/FULL_DOCS四种输出模式,以及属性继承、错误行为等边界细节,读完即可在真实构建脚本中正确、灵活地使用该命令。
命令总览:统一属性读取入口
get_property从一个作用域中的一个对象上读取一个属性,并将结果存储到指定的变量中。其核心语法如下(来自 官方文档):
get_property(<variable> <GLOBAL | DIRECTORY [<dir>] | RULE <rule> | TARGET <target> | FILE_SET <file_set> TARGET <target> | SOURCE <source> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] | INSTALL <file> | TEST <test> [DIRECTORY <dir>] | CACHE <entry> | VARIABLE> PROPERTY <name> [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])- 第一个参数
<variable>:结果存储的目标变量名。 - 第二个参数:指定读取属性的作用域类型(Scope),必须是
GLOBAL、DIRECTORY、RULE、TARGET、FILE_SET、SOURCE、INSTALL、TEST、CACHE、VARIABLE之一。 PROPERTY <name>:必填,指定要读取的属性名。- 末尾可选参数:
SET、DEFINED、BRIEF_DOCS、FULL_DOCS,决定写入变量的是属性的值还是关于属性的信息(详见下文"四种输出模式")。
与专用命令的关系
get_property是通用形式,仓库中还提供了一批同类的"专用快捷命令",它们本质上是针对特定作用域的封装:
- get_directory_property ——
DIRECTORY作用域专用; - get_target_property ——
TARGET作用域专用; - get_source_file_property ——
SOURCE作用域专用; - get_test_property ——
TEST作用域专用; - get_cmake_property —— 全局/目录信息的另一入口。
与读取相对的写入命令是 set_property,它支持相同的作用域列表,并额外提供APPEND与APPEND_STRING两种追加语义。属性本身的定义与继承行为由 define_property 管理。三者构成 CMake 属性系统的完整闭环:定义 → 设置 → 读取。
十种作用域逐一拆解
作用域参数决定了"从哪里读属性"。从源码实现看,作用域字符串是在 cmGetPropertyCommand.cxx 中被逐一映射为内部枚举cmProperty::ScopeType的;若传入无法识别的字符串,CMake 会直接报错given invalid scope ...并列出全部合法取值。
GLOBAL —— 全局命名空间
get_property(<variable> GLOBAL PROPERTY <name>)全局作用域唯一,不接受名称参数(源码中若传入名称会报错given name for GLOBAL scope.,见 cmGetPropertyCommand.cxx)。常用于读取GENERATOR_IS_MULTI_CONFIG、CMAKE_C_KNOWN_FEATURES等全局属性。仓库自身大量使用这一形式,例如 CMakeInstall.cmake 中:
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)再如 CompileFeatures 测试 读取 CMake 已知的 C/C++ 语言特性列表:
get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES) get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)DIRECTORY —— 目录作用域
get_property(<variable> DIRECTORY [<dir>] PROPERTY <name>)- 不带
<dir>时,读取当前目录(即调用该命令的CMakeLists.txt所在目录)的属性; - 带
<dir>时,可读取另一个已被 CMake 处理过的目录的属性,<dir>可以是完整路径或相对路径,相对路径以当前源码目录为基准; - 自 CMake 3.19 起,
<dir>还可以引用二进制目录; - 若指定的目录尚未被处理(例如尚未执行到
add_subdirectory),会返回错误(源码错误信息见 cmGetPropertyCommand.cxx)。
RULE —— 自定义规则作用域(4.5 新增)
get_property(<variable> RULE <rule> PROPERTY <name>)- CMake 4.5 起新增。
<rule>必须是当前目录中已由 add_custom_rule 创建的规则名; - 若规则不存在,报错
could not find RULE ... Perhaps it has not yet been created.(见 cmGetPropertyCommand.cxx)。
仓库在 add_custom_rule 测试 中封装了规则属性读取的辅助函数:
function(check_rule_property rule property expected) get_property(value RULE ${rule} PROPERTY ${property}) if(NOT "${value}" STREQUAL "${expected}") string (APPEND TEST_FAILED "RULE ${rule}, PROPERTY ${property}: ...") endif() return(PROPAGATE TEST_FAILED) endfunction()TARGET —— 目标作用域
get_property(<variable> TARGET <target> PROPERTY <name>)<target>必须是已存在的目标;若目标未创建,报错could not find TARGET ...(见 cmGetPropertyCommand.cxx);- 目标不限于当前
CMakeLists.txt,此前创建的任何目标都可查询(与 get_target_property 行为一致); - 属性未设置时,与
get_target_property的<variable>-NOTFOUND行为不同,get_property会直接取消该变量的定义(详见下文"未设置属性的处理")。
仓库的 AliasTarget 测试 展示了通过别名(ALIAS)目标读取属性的用法,包括ALIASED_TARGET、IMPORTED、ALIAS_GLOBAL以及自定义属性LIB_PROPERTY:
add_library(lib empty.cpp) set_property (TARGET lib PROPERTY LIB_PROPERTY "LIB") add_library(alias::lib ALIAS lib) check_property (alias::lib ALIASED_TARGET "lib") check_property (alias::lib LIB_PROPERTY "LIB")FILE_SET —— 文件集作用域(4.3 新增)
get_property(<variable> FILE_SET <file_set> TARGET <target> PROPERTY <name>)- CMake 4.3 起新增。
<file_set>必须是已附加到<target>上的现有文件集,TARGET <target>为必填选项; - 文件集不存在时报错
could not find FILE_SET ... for TARGET ...(见 cmGetPropertyCommand.cxx); - 常用于读取
TYPE、SCOPE、BASE_DIRS、SOURCES、INTERFACE_SOURCES、LANGUAGE等文件集属性。
仓库 FileSetProperties 测试 给出完整读写示例:
add_library(foo STATIC) target_sources(foo PRIVATE FILE_SET sources TYPE SOURCES FILES foo.c) set_property(FILE_SET sources TARGET foo PROPERTY LANGUAGE CXX) get_property(language FILE_SET sources TARGET foo PROPERTY LANGUAGE) if(NOT language STREQUAL "CXX") message(SEND_ERROR "wrong language: '${language}' instead of 'CXX'") endif()SOURCE —— 源文件作用域
get_property(<variable> SOURCE <source> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] PROPERTY <name>)- 默认从当前源码目录的作用域读取该源文件的属性;
- CMake 3.18 起支持两种覆盖目录范围的子选项:
DIRECTORY <dir>:从<dir>目录的作用域读取;CMake 必须已知该目录(通过add_subdirectory添加或为顶层目录),相对路径以当前源码目录为基准;3.19 起<dir>可以是二进制目录;TARGET_DIRECTORY <target>:从创建<target>的目录作用域读取(目标必须已存在);
- 若源文件无法找到或创建,报错
given SOURCE name that could not be found or created: ...(见 cmGetPropertyCommand.cxx)。
INSTALL —— 安装文件作用域(3.1 新增)
get_property(<variable> INSTALL <file> PROPERTY <name>)- CMake 3.1 起新增。
<file>必须是已声明的安装文件路径; - 该作用域主要用于向 CPack 传递部署相关信息,目前安装文件属性主要面向 WIX 生成器定义,路径相对安装前缀,需使用正斜杠、已归一化且区分大小写(详见 set_property 文档 中
INSTALL段的说明); - 实现上通过
GetOrCreateInstalledFile查找或创建安装文件记录(见 cmGetPropertyCommand.cxx)。
TEST —— 测试作用域
get_property(<variable> TEST <test> [DIRECTORY <dir>] PROPERTY <name>)<test>必须是已存在的测试(通常由add_test创建);- CMake 3.28 起支持
DIRECTORY <dir>覆盖目录作用域:从<dir>目录的作用域读取测试属性;CMake 必须已知该目录,相对路径以当前源码目录为基准,<dir>也可以引用二进制目录; - 测试不存在时报错
given TEST name that does not exist: ...(见 cmGetPropertyCommand.cxx)。
CACHE —— 缓存条目作用域
get_property(<variable> CACHE <entry> PROPERTY <name>)<entry>必须是已存在的缓存条目,读取的是该缓存条目的属性(例如TYPE、HELPSTRING、ADVANCED等),而非缓存条目本身的值——读取缓存变量的值应使用$CACHE{<entry>}语法或VARIABLE作用域配合缓存变量名;- 实现中通过
GetCacheEntryValue判断条目是否存在、再经GetCacheEntryProperty取属性(见 cmGetPropertyCommand.cxx)。
VARIABLE —— 普通变量作用域
get_property(<variable> VARIABLE PROPERTY <name>)- 作用域唯一,不接受名称参数;
- 语义等价于"读取一个普通 CMake 变量的值":把名为
<name>的变量当前值写入<variable>(源码见 cmGetPropertyCommand.cxx)。
仓库 GetPropertyTest 对该作用域做了直接验证:
set(test_var alpha) get_property(result VARIABLE PROPERTY test_var) if(NOT result STREQUAL "alpha") message(SEND_ERROR "bad value of VARIABLE PROPERTY test_var: got '${result}' instead of 'alpha'") endif()PROPERTY 与四种输出模式
PROPERTY :必填的属性名
PROPERTY选项后必须紧跟属性名。源码在解析完参数后会检查propertyName是否为空,否则报错not given a PROPERTY <name> argument.(见 cmGetPropertyCommand.cxx)。
默认模式:直接返回属性值
不带任何末尾选项时,属性值被写入<variable>:
- 若属性已设置:变量被设为属性值;
- 若属性未设置:变量在调用作用域内被取消定义(
RemoveDefinition,见 cmGetPropertyCommand.cxx); - 特例:部分被定义为
INHERITED行为的属性(见 define_property)支持向父作用域链式查找。
这一"未设置即取消变量"的行为,与get_target_property(未找到时置为<variable>-NOTFOUND)形成鲜明对比,是排查"变量为何是空"问题时常被忽略的关键差异。
SET:属性是否被显式设置
get_property(<variable> TARGET <target> PROPERTY <name> SET)变量被设置为布尔值:属性已被设置时为1,否则为0。注意SET判断的是"是否显式设置过",与DEFINED(是否定义过该属性)语义不同。仓库在 AliasTarget 测试 中使用它:
get_property(_aliased_target_set TARGET foo PROPERTY ALIASED_TARGET SET)DEFINED:属性是否已被定义
get_property(<variable> TARGET <target> PROPERTY <name> DEFINED)变量被设为布尔值,表示该属性是否已被定义(例如通过 define_property 定义)。实现上直接查询状态机中的属性定义表(GetPropertyDefinition,见 cmGetPropertyCommand.cxx)。
BRIEF_DOCS / FULL_DOCS:读取属性文档
get_property(<variable> TARGET <target> PROPERTY <name> BRIEF_DOCS) get_property(<variable> TARGET <target> PROPERTY <name> FULL_DOCS)- 变量被设置为该属性的简要文档或完整文档字符串;
- 若该属性从未被定义过(没有关联文档),返回
NOTFOUND(见 cmGetPropertyCommand.cxx)。
仓库 GetPropertyTest 验证了未定义属性时两个模式均返回NOTFOUND:
get_property(FOO_BRIEF GLOBAL PROPERTY FOO BRIEF_DOCS) get_property(FOO_FULL GLOBAL PROPERTY FOO FULL_DOCS) if (NOT FOO_BRIEF STREQUAL "NOTFOUND") message(SEND_ERROR "property FOO has BRIEF_DOCS set to '${FOO_BRIEF}'") endif ()而 define_property 测试 则系统验证了"定义过的属性能取到对应文档、未定义的返回 NOTFOUND":
define_property(TARGET PROPERTY PROP2 BRIEF_DOCS "Brief") define_property(TARGET PROPERTY PROP3 FULL_DOCS "Full") # ... assert_prop_scope_eq(PROP2 BRIEF_DOCS "Brief") assert_prop_scope_eq(PROP2 FULL_DOCS "NOTFOUND") assert_prop_scope_eq(PROP3 BRIEF_DOCS "NOTFOUND") assert_prop_scope_eq(PROP3 FULL_DOCS "Full")属性继承(INHERITED)与 define_property 协同
get_property的继承行为由 define_property 的INHERITED选项控制:
- 带
INHERITED定义的属性,若在指定作用域未设置,get_property会向更高一级作用域链式查找:DIRECTORY作用域沿父目录逐级上溯,直到顶层仍未找到则链到GLOBAL作用域;TARGET、SOURCE、TEST属性链到DIRECTORY作用域,并继续按目录层级向上;
- 继承只发生在读取时(
get_property、get_directory_property、get_target_property、get_source_file_property、get_test_property);设置时不存在继承,因此 set_property 的APPEND/APPEND_STRING不会基于继承值追加,若属性未被显式设置,则行为等同未加APPEND/APPEND_STRING; - CMake 3.23 起,
BRIEF_DOCS/FULL_DOCS变为可选,并新增INITIALIZE_FROM_VARIABLE(仅限目标属性,变量名必须以属性名结尾、不得以CMAKE_或_CMAKE_开头、属性名须含至少一个下划线,且建议带项目专属前缀); - 属性一经定义不可重定义(同作用域同属性名的重复
define_property会被静默忽略),但同一属性名可分别用于不同作用域类型。
define_property 文档 给出了"定义 → 查询是否已定义 → 读取文档"的完整示例:
# Initial definition define_property(TARGET PROPERTY MY_NEW_PROP BRIEF_DOCS "My new custom property" ) # Later examination get_property(my_new_prop_exists TARGET NONE PROPERTY MY_NEW_PROP DEFINED ) if(my_new_prop_exists) get_property(my_new_prop_docs TARGET NONE PROPERTY MY_NEW_PROP BRIEF_DOCS ) # ${my_new_prop_docs} is now set to "My new custom property" endif()注意其中TARGET NONE的写法:查询DEFINED/BRIEF_DOCS这类属性元信息时不需要真实目标存在——因为处理这些输出模式时根本不会执行目标查找,NONE只是一个占位名称。
常见错误与边界行为
从源码的参数解析(cmGetPropertyCommand.cxx)与各作用域处理器中可以归纳出以下易错点:
| 场景 | 行为 |
|---|---|
| 参数少于 3 个 | 报错called with incorrect number of arguments |
| 作用域字符串不合法 | 报错given invalid scope ...并列出合法取值 |
GLOBAL/VARIABLE后跟名称 | 报错given name for GLOBAL scope./VARIABLE scope. |
TARGET/SOURCE/TEST/CACHE/RULE/FILE_SET/INSTALL缺少名称 | 报错not given name for ... scope. |
| 目标/规则/文件集/测试不存在 | 报错could not find ... Perhaps it has not yet been created. |
未给出PROPERTY | 报错not given a PROPERTY <name> argument. |
| 属性未设置(默认模式) | 变量在调用作用域中被取消定义 |
未定义属性 +BRIEF_DOCS/FULL_DOCS | 变量被设为NOTFOUND |
GENERATED源文件属性 | 可能全局可见(见 GENERATED 属性文档) |
此外还有一个易被忽略的细节:FILE_SET的TARGET子选项、SOURCE的DIRECTORY/TARGET_DIRECTORY子选项、TEST的DIRECTORY子选项都必须紧跟对应作用域之后出现,源码按"状态机"逐 token 解析(DoingFileSetTarget、DoingSourceDirectory等),顺序或用法错误会报given invalid argument ...。
实战小结与推荐路径
get_property的核心价值在于:一个命令、统一语法、覆盖 CMake 全部属性作用域。实际项目中的选择建议:
- 只读目标属性,且确认属性必定存在 → 可用
get_target_property(未命中时得到-NOTFOUND,便于if(...)判空); - 需要区分"属性未设置"与"值为空"、或需要跨作用域/带目录覆盖读取 → 用通用
get_property+SET/DEFINED; - 需要读取文档元信息 →
get_property+BRIEF_DOCS/FULL_DOCS,配合 define_property 为自定义属性书写文档; - 需要批量或追加设置属性 → 配合 set_property 的
APPEND/APPEND_STRING。
深入阅读建议:
- 属性读写对偶命令:set_property、define_property;
- 各作用域的完整属性清单:cmake-properties 手册;
- 底层实现:cmGetPropertyCommand.cxx(作用域映射、参数解析、
StoreResult存储逻辑); - 官方测试佐证:GetPropertyTest.cmake.in、define_property 测试、alias_targets/get_property.cmake、FileSetProperties 测试、add_custom_rule 测试。
- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
相关推荐
CMake function() 命令完全指南:作用域、参数变量与宏的差异详解
CMake function 命令完全指南:作用域、参数变量与宏的差异详解 本篇技术指南围绕 CMake 官方文档 Help/command/function.
构建工具开发工具CLIDiceDB BITFIELD_RO 命令深度解析:只读位域读取的实现原理与实战指南
DiceDB BITFIELD_RO 命令深度解析:只读位域读取的实现原理与实战指南 导读 BITFIELD_RO 是 DiceDB 中 BITFIELD 命令
数据库缓存后端Pandoc JATS 读取器中 `<title>` 的 `suppress` 属性:从命令测试到源码实现
Pandoc JATS 读取器中 <title 的 suppress 属性:从命令测试到源码实现 导读 本文以 pandoc 仓库中的命令测试用例 test/c
文档开发工具CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考