ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CMake get_property 命令完全指南:十种作用域属性读取与源码实现解析

CMake get_property 命令完全指南:十种作用域属性读取与源码实现解析 构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载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_PROPERTYadd_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 验证了未定义属性时两个模式均返回NOTFOUNDget_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 测试 则系统验证了定义过的属性能取到对应文档、未定义的返回 NOTFOUNDdefine_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_STRINGCMake 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变量被设为NOTFOUNDGENERATED源文件属性可能全局可见见 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_propertySET/DEFINED需要读取文档元信息 →get_propertyBRIEF_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【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载相关推荐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上一篇GPU模拟与高性能计算的终极指南GPGPU-Sim完整教程下一篇终极指南让Element UI表格横向滚动条始终可见的完美解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表