set(all_target_types "EXECUTABLE" "IMPORTED_EXECUTABLE" "INTERFACE" "MODULE" "OBJECT" "SHARED" "STATIC" "IMPORTED_INTERFACE" "IMPORTED_MODULE" "IMPORTED_OBJECT" "IMPORTED_SHARED" "IMPORTED_STATIC" "CUSTOM") function (prepare_target_types name) set("${name}" "${ARGN}" PARENT_SCOPE) list(REMOVE_ITEM all_target_types ${ARGN}) set("not_${name}" "${all_target_types}" PARENT_SCOPE) endfunction () function (per_config variable) prepare_properties("${property_table}" properties expected_values expected_alias) get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (is_multi_config) set(configs "${CMAKE_CONFIGURATION_TYPES}") else () if (NOT CMAKE_BUILD_TYPE STREQUAL "") set(configs "${CMAKE_BUILD_TYPE}") endif () endif () foreach (property expected alias IN ZIP_LISTS expected_properties expected_values expected_alias) if (property MATCHES "^_") set(prepend 1) elseif (property MATCHES "_$") set(prepend 0) else () message(SEND_ERROR "Per-config properties must have a `_` at one end of their name: '${property}'") endif () foreach (config IN LISTS configs) if (prepend) list(APPEND "${variable}" "${config}_${property}" "${value}/${config}" "${alias}") else () list(APPEND "${variable}" "${property}_${config}" "${value}/${config}" "${alias}") endif () endforeach () endforeach () set("${variable}" "${${variable}}" PARENT_SCOPE) endfunction () function (make_target name type) if (type STREQUAL "EXECUTABLE") add_executable("${name}") target_sources("${name}" PRIVATE ${main_sources}) elseif (type STREQUAL "IMPORTED_EXECUTABLE") add_executable("${name}" IMPORTED) set_property(TARGET "${name}" PROPERTY IMPORTED_LOCATION "${CMAKE_COMMAND}") elseif (type STREQUAL "CUSTOM") add_custom_target("${name}" COMMAND "${CMAKE_EXECUTABLE}" -E echo "${name}") elseif (type MATCHES "IMPORTED_") string(REPLACE "IMPORTED_" "" type "${type}") add_library("${name}" IMPORTED ${type}) if (NOT type STREQUAL "INTERFACE") set_property(TARGET "${name}" PROPERTY IMPORTED_LOCATION "${default_library_location}") endif () else () add_library("${name}" ${type}) target_sources("${name}" PRIVATE ${library_sources}) endif () if (type MATCHES "EXECUTABLE") add_executable("alias::${name}" ALIAS "${name}") elseif (NOT type STREQUAL "CUSTOM") add_library("alias::${name}" ALIAS "${name}") endif () endfunction () function (check_property target property expected) if (NOT TARGET "${target}") message(SEND_ERROR "No such target '${target}'") return () endif () get_property(is_set TARGET "${target}" PROPERTY "${property}" SET) if (is_set) get_property(actual TARGET "${target}" PROPERTY "${property}") endif () if (expected STREQUAL "") if (is_set) message(SEND_ERROR "Target '${target}' should not have '${property}' set at all, but is '${actual}'") endif () elseif (is_set AND NOT expected STREQUAL actual) message(SEND_ERROR "Target '${target}' should have '${property}' set to '${expected}', but is '${actual}'") elseif (NOT is_set) message(SEND_ERROR "Target '${target}' should have '${property}' set to '${expected}', but is not set at all") endif () endfunction () function (prepare_properties table output_properties output_expected output_alias) set(_properties) set(_expected) set(_alias) set(variable "_properties") foreach (item IN LISTS "${table}") list(APPEND "${variable}" "${item}") if (variable STREQUAL "_properties") set(variable "_expected") elseif (variable STREQUAL "_expected") set(variable "_alias") elseif (variable STREQUAL "_alias") set(variable "_properties") else () message(FATAL_ERROR "Failed to track property table parsing") endif () endforeach () if (NOT variable STREQUAL "_properties") message(FATAL_ERROR "Table does not have a multiple of 3 items") endif () set("${output_properties}" "${_properties}" PARENT_SCOPE) set("${output_expected}" "${_expected}" PARENT_SCOPE) set("${output_alias}" "${_alias}" PARENT_SCOPE) endfunction () # Contextual variables: # iteration: make unique target names # with_defaults: if set, do not set variables, but instead test internal # default calculations function (run_property_tests applied_types property_table) prepare_properties("${property_table}" expected_properties expected_values expected_alias) if (NOT with_defaults) foreach (property expected IN ZIP_LISTS expected_properties expected_values) string(REPLACE "" ";" expected "${expected}") set("CMAKE_${property}" "${expected}") endforeach () endif () foreach (target_type IN LISTS "${applied_types}") set(target_name "${RunCMake_TEST}${iteration}-${target_type}") if (with_defaults) string(APPEND target_name "-defaults") endif () make_target("${target_name}" "${target_type}") foreach (property expected alias IN ZIP_LISTS expected_properties expected_values expected_alias) string(REPLACE "" ";" expected "${expected}") check_property("${target_name}" "${property}" "${expected}") if (NOT target_type STREQUAL "CUSTOM") if (alias STREQUAL "") check_property("alias::${target_name}" "${property}" "${expected}") elseif (alias STREQUAL "") check_property("alias::${target_name}" "${property}" "") else () message(FATAL_ERROR "Invalid `alias` entry for property '${property}': '${alias}'") endif () endif () endforeach () endforeach () foreach (target_type IN LISTS "not_${applied_types}") set(target_name "${RunCMake_TEST}${iteration}-${target_type}-unset") if (with_defaults) string(APPEND target_name "-defaults") endif () make_target("${target_name}" "${target_type}") foreach (property IN LISTS expected_properties) check_property("${target_name}" "${property}" "") if (NOT target_type STREQUAL "CUSTOM") check_property("alias::${target_name}" "${property}" "") endif () endforeach () endforeach () endfunction ()