How to print all the properties of a target in cmake?
CmakeCmake Problem Overview
With the following cmake scrpt:
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
We can print all the variables in the CMake project. Then my question is: is there a function that can print all the properties of a target?
Cmake Solutions
Solution 1 - Cmake
I have had limited success with the following work-around to the apparent lack of ability to dynamically query for the properties of a target.
I invoke the cmake command to list all properties, and then try each one on the target.
# 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()
Solution 2 - Cmake
This isn't really intended to be a competing answer, just an expansion on the answer by AlwaysTraining (and edited by Dawid Drozd)!
If the target is an INTERFACE_LIBRARY
, this will print out a whole bunch of errors about whitelisted properties. Unfortunately, there doesn't seem to be a good way to dynamically query what the whitelisted properties are - by checking the source for cmTargetPropertyComputer::WhiteListedInterfaceProperty
I was able to come up with a regexp, but it could change from version to version (I was looking at the source for cmake-3.11). Anyway, here's my revised version, with support for INTERFACE_LIBRARY
targets - I also removes duplicate, and made the filtering of LOCATION properties happen once, outside of the loop.
(I've made a suggested edit to the original question, but this is here in case it isn't accepted...)
Thanks AlwaysTraining and Dawid Drozd!
# 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)
Solution 3 - Cmake
Improved @AlwaysTraining's and @PaulMolodowitch's answers.
Solves problem with INTERFACE_LIBRARY
described in kyb's comment
Functionally my implementation does at most the same as @PaulMolodowitch's implementation. But it is more laconic.
## 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)
Solution 4 - Cmake
This version uses ideas from David Drozd's and Paul Molodowitch's answers but includes processing for <CONFIG> and <LANG> text returned by 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 EXCLUDE 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)