How to print all the properties of a target in cmake?

Cmake

Cmake 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_LIBRARYtargets - 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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfeelfreeView Question on Stackoverflow
Solution 1 - CmakeAlwaysTrainingView Answer on Stackoverflow
Solution 2 - CmakePaul MolodowitchView Answer on Stackoverflow
Solution 3 - CmakekybView Answer on Stackoverflow
Solution 4 - CmakemheymanView Answer on Stackoverflow