使用以下cmake脚本:
get_cmake_property(_variableNames VARIABLES) foreach (_variableName ${_variableNames}) message(STATUS "${_variableName}=${${_variableName}}") endforeach()
我们可以打印CMake项目中的所有变量。那么我的问题是:是否有一个函数可以打印目标的所有属性?
roejwanj1#
对于明显缺乏动态查询目标属性的能力,我采用了以下解决方案,但收效有限。我调用cmake命令列出所有属性,然后在目标上尝试每个属性。
# Get all propreties that cmake supports if(NOT CMAKE_PROPERTY_LIST) execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE CMAKE_PROPERTY_LIST) # Convert command output into a CMake list string(REGEX REPLACE ";" "\\\\;" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") string(REGEX REPLACE "\n" ";" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") endif() function(print_properties) message("CMAKE_PROPERTY_LIST = ${CMAKE_PROPERTY_LIST}") endfunction() function(print_target_properties target) if(NOT TARGET ${target}) message(STATUS "There is no target named '${target}'") return() endif() foreach(property ${CMAKE_PROPERTY_LIST}) string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" property ${property}) # Fix https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i if(property STREQUAL "LOCATION" OR property MATCHES "^LOCATION_" OR property MATCHES "_LOCATION$") continue() endif() get_property(was_set TARGET ${target} PROPERTY ${property} SET) if(was_set) get_target_property(value ${target} ${property}) message("${target} ${property} = ${value}") endif() endforeach() endfunction()
am46iovg2#
这并不是一个真正的竞争答案,只是一个扩展的答案由AlwaysTraining(并编辑了Dawid Drozd)!如果目标是一个INTERFACE_LIBRARY,这将打印出一大堆关于白名单属性的错误。不幸的是,似乎没有一个好的方法来动态查询白名单属性是什么-通过检查cmTargetPropertyComputer::WhiteListedInterfaceProperty的源代码,我能够得到一个regexp,但它可能会随着版本的不同而变化(我在看cmake-3.11的源代码)。无论如何,这是我的修订版本,支持INTERFACE_LIBRARY目标-我还删除了重复的内容,并在循环之外对LOCATION属性进行了一次过滤。(我已经对原始问题进行了建议编辑,但在此提供此建议,以防未被接受...)感谢AlwaysTraining和Dawid Drozd!
INTERFACE_LIBRARY
cmTargetPropertyComputer::WhiteListedInterfaceProperty
# Get all propreties that cmake supports execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE CMAKE_PROPERTY_LIST) # Convert command output into a CMake list STRING(REGEX REPLACE ";" "\\\\;" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") STRING(REGEX REPLACE "\n" ";" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") # Fix https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i list(FILTER CMAKE_PROPERTY_LIST EXCLUDE REGEX "^LOCATION$|^LOCATION_|_LOCATION$") # For some reason, "TYPE" shows up twice - others might too? list(REMOVE_DUPLICATES CMAKE_PROPERTY_LIST) # build whitelist by filtering down from CMAKE_PROPERTY_LIST in case cmake is # a different version, and one of our hardcoded whitelisted properties # doesn't exist! unset(CMAKE_WHITELISTED_PROPERTY_LIST) foreach(prop ${CMAKE_PROPERTY_LIST}) if(prop MATCHES "^(INTERFACE|[_a-z]|IMPORTED_LIBNAME_|MAP_IMPORTED_CONFIG_)|^(COMPATIBLE_INTERFACE_(BOOL|NUMBER_MAX|NUMBER_MIN|STRING)|EXPORT_NAME|IMPORTED(_GLOBAL|_CONFIGURATIONS|_LIBNAME)?|NAME|TYPE|NO_SYSTEM_FROM_IMPORTED)$") list(APPEND CMAKE_WHITELISTED_PROPERTY_LIST ${prop}) endif() endforeach(prop) function(print_properties) message ("CMAKE_PROPERTY_LIST = ${CMAKE_PROPERTY_LIST}") endfunction(print_properties) function(print_whitelisted_properties) message ("CMAKE_WHITELISTED_PROPERTY_LIST = ${CMAKE_WHITELISTED_PROPERTY_LIST}") endfunction(print_whitelisted_properties) function(print_target_properties tgt) if(NOT TARGET ${tgt}) message("There is no target named '${tgt}'") return() endif() get_target_property(target_type ${tgt} TYPE) if(target_type STREQUAL "INTERFACE_LIBRARY") set(PROP_LIST ${CMAKE_WHITELISTED_PROPERTY_LIST}) else() set(PROP_LIST ${CMAKE_PROPERTY_LIST}) endif() foreach (prop ${PROP_LIST}) string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" prop ${prop}) # message ("Checking ${prop}") get_property(propval TARGET ${tgt} PROPERTY ${prop} SET) if (propval) get_target_property(propval ${tgt} ${prop}) message ("${tgt} ${prop} = ${propval}") endif() endforeach(prop) endfunction(print_target_properties)
to94eoyn3#
改进了@AlwaysTraining和@PaulMolodowitch的答案。解决kyb注解中描述的INTERFACE_LIBRARY问题从功能上讲,我的实现和@PaulMolodowitch的实现差不多,但是它更简洁。
## https://stackoverflow.com/questions/32183975/how-to-print-all-the-properties-of-a-target-in-cmake/56738858#56738858 ## https://stackoverflow.com/a/56738858/3743145 ## Get all properties that cmake supports execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE CMAKE_PROPERTY_LIST) ## Convert command output into a CMake list STRING(REGEX REPLACE ";" "\\\\;" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") STRING(REGEX REPLACE "\n" ";" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") list(REMOVE_DUPLICATES CMAKE_PROPERTY_LIST) function(print_target_properties tgt) if(NOT TARGET ${tgt}) message("There is no target named '${tgt}'") return() endif() foreach (prop ${CMAKE_PROPERTY_LIST}) string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" prop ${prop}) get_target_property(propval ${tgt} ${prop}) if (propval) message ("${tgt} ${prop} = ${propval}") endif() endforeach(prop) endfunction(print_target_properties)
7gs2gvoe4#
此版本使用David Drozd和Paul Molodowitch的答案中的想法,但包括对cmake --help-property-list返回的文本的处理:
cmake --help-property-list
# Sets the AVAILABLE_CONFIGURATION_TYPES variable to the default available configurations # (For some reason, CMAKE_CONFIGURATION_TYPES tends to be empty) function(get_available_configuration_types) # Get all variables that cmake cache defines by default execute_process(COMMAND cmake -LAH -N OUTPUT_VARIABLE CMAKE_CACHE_VARIABLE_LIST) # Convert command output into a CMake list string(REGEX REPLACE ";" "[:semicolon:]" CMAKE_CACHE_VARIABLE_LIST "${CMAKE_CACHE_VARIABLE_LIST}") string(REGEX REPLACE "\n" ";" CMAKE_CACHE_VARIABLE_LIST "${CMAKE_CACHE_VARIABLE_LIST}") # filter down to the variables list(FILTER CMAKE_CACHE_VARIABLE_LIST EXCLUDE REGEX "^$|^//.*$|^\-\-$") # Get the configuration types set(AVAILABLE_CONFIGURATION_TYPES ${CMAKE_CACHE_VARIABLE_LIST}) list(FILTER AVAILABLE_CONFIGURATION_TYPES INCLUDE REGEX "^CMAKE_CONFIGURATION_TYPES") list(GET AVAILABLE_CONFIGURATION_TYPES 0 AVAILABLE_CONFIGURATION_TYPES) string(REGEX REPLACE ".*=" "" AVAILABLE_CONFIGURATION_TYPES "${AVAILABLE_CONFIGURATION_TYPES}") string(REPLACE "[:semicolon:]" ";" AVAILABLE_CONFIGURATION_TYPES "${AVAILABLE_CONFIGURATION_TYPES}") string(TOUPPER "${AVAILABLE_CONFIGURATION_TYPES}" AVAILABLE_CONFIGURATION_TYPES) # Add the current build type if it isn't already there string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) list(FILTER AVAILABLE_CONFIGURATION_TYPES EXCLUDE REGEX ${BUILD_TYPE}) list(APPEND AVAILABLE_CONFIGURATION_TYPES ${BUILD_TYPE}) list(SORT AVAILABLE_CONFIGURATION_TYPES) # make AVAILABLE_CONFIGURATION_TYPES available to parent set(AVAILABLE_CONFIGURATION_TYPES ${AVAILABLE_CONFIGURATION_TYPES} PARENT_SCOPE) endfunction() # Sets the CMAKE_PROPERTY_LIST and CMAKE_WHITELISTED_PROPERTY_LIST variables to # the list of properties function(get_cmake_property_list) # See https://stackoverflow.com/a/44477728/240845 set(LANGS ASM-ATT ASM ASM_MASM ASM_NASM C CSHARP CUDA CXX FORTRAN HIP ISPC JAVA OBJC OBJCXX RC SWIFT) get_available_configuration_types() # Get all propreties that cmake supports execute_process(COMMAND cmake --help-property-list OUTPUT_VARIABLE CMAKE_PROPERTY_LIST) # Convert command output into a CMake list string(REGEX REPLACE ";" "\\\\;" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") string(REGEX REPLACE "\n" ";" CMAKE_PROPERTY_LIST "${CMAKE_PROPERTY_LIST}") # Populate "<CONFIG>" with AVAILBLE_CONFIG_TYPES set(CONFIG_LINES ${CMAKE_PROPERTY_LIST}) list(FILTER CONFIG_LINES INCLUDE REGEX "<CONFIG>") list(FILTER CMAKE_PROPERTY_LIST EXCLUDE REGEX "<CONFIG>") foreach(CONFIG_LINE IN LISTS CONFIG_LINES) foreach(CONFIG_VALUE IN LISTS AVAILABLE_CONFIGURATION_TYPES) string(REPLACE "<CONFIG>" "${CONFIG_VALUE}" FIXED "${CONFIG_LINE}") list(APPEND CMAKE_PROPERTY_LIST ${FIXED}) endforeach() endforeach() # Populate "<LANG>" with LANGS set(LANG_LINES ${CMAKE_PROPERTY_LIST}) list(FILTER LANG_LINES INCLUDE REGEX "<LANG>") list(FILTER CMAKE_PROPERTY_LIST EXCLUDE REGEX "<LANG>") foreach(LANG_LINE IN LISTS LANG_LINES) foreach(LANG IN LISTS LANGS) string(REPLACE "<LANG>" "${LANG}" FIXED "${LANG_LINE}") list(APPEND CMAKE_PROPERTY_LIST ${FIXED}) endforeach() endforeach() # no repeats list(REMOVE_DUPLICATES CMAKE_PROPERTY_LIST) # Fix https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i list(FILTER CMAKE_PROPERTY_LIST EXCLUDE REGEX "^LOCATION$|^LOCATION_|_LOCATION$") list(SORT CMAKE_PROPERTY_LIST) # Whitelisted property list for use with interface libraries to reduce warnings set(CMAKE_WHITELISTED_PROPERTY_LIST ${CMAKE_PROPERTY_LIST}) # regex from https://stackoverflow.com/a/51987470/240845 list(FILTER CMAKE_WHITELISTED_PROPERTY_LIST INCLUDE REGEX "^(INTERFACE|[_a-z]|IMPORTED_LIBNAME_|MAP_IMPORTED_CONFIG_)|^(COMPATIBLE_INTERFACE_(BOOL|NUMBER_MAX|NUMBER_MIN|STRING)|EXPORT_NAME|IMPORTED(_GLOBAL|_CONFIGURATIONS|_LIBNAME)?|NAME|TYPE|NO_SYSTEM_FROM_IMPORTED)$") # make the lists available set(CMAKE_PROPERTY_LIST ${CMAKE_PROPERTY_LIST} PARENT_SCOPE) set(CMAKE_WHITELISTED_PROPERTY_LIST ${CMAKE_WHITELISTED_PROPERTY_LIST} PARENT_SCOPE) endfunction() get_cmake_property_list() function(print_target_properties tgt) if(NOT TARGET ${tgt}) message("There is no target named '${tgt}'") return() endif() get_target_property(target_type ${tgt} TYPE) if(target_type STREQUAL "INTERFACE_LIBRARY") set(PROPERTIES ${CMAKE_WHITELISTED_PROPERTY_LIST}) else() set(PROPERTIES ${CMAKE_PROPERTY_LIST}) endif() foreach (prop ${PROPERTIES}) #message ("Checking ${prop}") get_property(propval TARGET ${tgt} PROPERTY ${prop} SET) if (propval) get_target_property(propval ${tgt} ${prop}) message ("${tgt} ${prop} = ${propval}") endif() endforeach(prop) endfunction(print_target_properties)
4条答案
按热度按时间roejwanj1#
对于明显缺乏动态查询目标属性的能力,我采用了以下解决方案,但收效有限。
我调用cmake命令列出所有属性,然后在目标上尝试每个属性。
am46iovg2#
这并不是一个真正的竞争答案,只是一个扩展的答案由AlwaysTraining(并编辑了Dawid Drozd)!
如果目标是一个
INTERFACE_LIBRARY
,这将打印出一大堆关于白名单属性的错误。不幸的是,似乎没有一个好的方法来动态查询白名单属性是什么-通过检查cmTargetPropertyComputer::WhiteListedInterfaceProperty
的源代码,我能够得到一个regexp,但它可能会随着版本的不同而变化(我在看cmake-3.11的源代码)。无论如何,这是我的修订版本,支持INTERFACE_LIBRARY
目标-我还删除了重复的内容,并在循环之外对LOCATION属性进行了一次过滤。(我已经对原始问题进行了建议编辑,但在此提供此建议,以防未被接受...)
感谢AlwaysTraining和Dawid Drozd!
to94eoyn3#
改进了@AlwaysTraining和@PaulMolodowitch的答案。
解决kyb注解中描述的
INTERFACE_LIBRARY
问题从功能上讲,我的实现和@PaulMolodowitch的实现差不多,但是它更简洁。
7gs2gvoe4#
此版本使用David Drozd和Paul Molodowitch的答案中的想法,但包括对
cmake --help-property-list
返回的文本的处理: