CPS: Import per-configuration attributes

This commit is contained in:
Taylor Sasser
2025-09-03 14:05:35 -04:00
parent 00185a62cf
commit e23f0748d8
16 changed files with 249 additions and 11 deletions

View File

@@ -231,15 +231,14 @@ void AppendProperty(cmMakefile* makefile, cmTarget* target,
cm::string_view property, cm::string_view configuration,
std::string const& value)
{
std::string fullprop;
if (configuration.empty()) {
fullprop = cmStrCat("INTERFACE_"_s, property);
std::string const fullprop = cmStrCat("INTERFACE_", property);
if (!configuration.empty()) {
std::string const genexValue =
cmStrCat("$<$<CONFIG:", configuration, ">:", value, '>');
target->AppendProperty(fullprop, genexValue, makefile->GetBacktrace());
} else {
fullprop = cmStrCat("INTERFACE_"_s, property, '_',
cmSystemTools::UpperCase(configuration));
target->AppendProperty(fullprop, value, makefile->GetBacktrace());
}
target->AppendProperty(fullprop, value, makefile->GetBacktrace());
}
template <typename Transform>

View File

@@ -160,15 +160,15 @@ elseif(NOT TARGET Foo::Empty)
message(SEND_ERROR "Foo::Empty missing !")
else()
get_property(pt_includes
TARGET Foo::PrefixTest PROPERTY INTERFACE_INCLUDE_DIRECTORIES_DEFAULT)
if(NOT "${CMAKE_CURRENT_SOURCE_DIR}/include" PATH_EQUAL "${pt_includes}")
TARGET Foo::PrefixTest PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
if(NOT "${pt_includes}" STREQUAL "$<$<CONFIG:default>:${CMAKE_CURRENT_SOURCE_DIR}/include>" )
message(SEND_ERROR "Foo::PrefixTest has wrong includes '${pt_includes}' !")
endif()
set(pt_includes)
get_property(rt_includes
TARGET Foo::RelativeTest PROPERTY INTERFACE_INCLUDE_DIRECTORIES_DEFAULT)
if(NOT "${CMAKE_CURRENT_SOURCE_DIR}/cps/../include" PATH_EQUAL "${rt_includes}")
TARGET Foo::RelativeTest PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
if(NOT "${rt_includes}" STREQUAL "$<$<CONFIG:default>:${CMAKE_CURRENT_SOURCE_DIR}/cps/../include>")
message(SEND_ERROR "Foo::RelativeTest has wrong includes '${rt_includes}' !")
endif()
set(rt_includes)

View File

@@ -0,0 +1,9 @@
include(Setup.cmake)
# Verify that CMake respects the preferred configurations as specified by a
# CPS package
find_package(ConfigDefault REQUIRED)
add_library(config-test config_test.cxx)
target_compile_definitions(config-test PRIVATE EXPECTED_MARKER=2)
target_link_libraries(config-test ConfigDefault::target)

View File

@@ -0,0 +1,9 @@
include(Setup.cmake)
# Verify that the first observed configuration of a component is selected when
# nothing else influences configuration selection
find_package(ConfigFirst REQUIRED)
add_library(config-test config_test.cxx)
target_compile_definitions(config-test PRIVATE EXPECTED_MARKER=1)
target_link_libraries(config-test ConfigFirst::target)

View File

@@ -0,0 +1,14 @@
include(Setup.cmake)
# Verify that MAP_IMPORTED_CONFIG_${CMAKE_BUILD_TYPE} can be used to select a
# configuration of a target imported via CPS
find_package(ConfigMapped REQUIRED)
set_target_properties(
ConfigMapped::target PROPERTIES
MAP_IMPORTED_CONFIG_RELEASE test
)
add_library(config-test STATIC config_test.cxx)
target_compile_definitions(config-test PRIVATE EXPECTED_MARKER=4)
target_link_libraries(config-test PUBLIC ConfigMapped::target)

View File

@@ -0,0 +1,9 @@
include(Setup.cmake)
# Verify that CMake will select a configuration matching the current build
# type, regardless of the package's preferred configurations
find_package(ConfigMatchBuildType REQUIRED)
add_library(config-test STATIC config_test.cxx)
target_compile_definitions(config-test PRIVATE EXPECTED_MARKER=4)
target_link_libraries(config-test ConfigMatchBuildType::target)

View File

@@ -8,6 +8,27 @@ set(RunCMake_TEST_OPTIONS
"-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
)
function(run_cmake_build test)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
if(${ARGC} EQUAL 2)
set(_build_type ${ARGV1})
else()
set(_build_type Release)
endif()
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=${_build_type})
else()
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=${_build_type})
endif()
run_cmake(${test})
set(RunCMake_TEST_NO_CLEAN TRUE)
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config ${_build_type})
endfunction()
# Version-matching tests
run_cmake(ExactVersion)
run_cmake(CompatVersion)
@@ -33,3 +54,9 @@ run_cmake(MissingComponentDependency)
run_cmake(MissingTransitiveComponentCPS)
run_cmake(MissingTransitiveComponentCMake)
run_cmake(MissingTransitiveComponentDependency)
# Configuration selection tests
run_cmake_build(ConfigDefault)
run_cmake_build(ConfigFirst)
run_cmake_build(ConfigMapped)
run_cmake_build(ConfigMatchBuildType Test)

View File

@@ -1,3 +1,5 @@
enable_language(CXX)
# Protect tests from running inside the default install prefix.
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/NotDefaultPrefix")

View File

@@ -0,0 +1,32 @@
#ifndef NAME
# error "NAME is not defined"
#endif
#ifndef MARKER
# error "MARKER is not defined"
#endif
#ifndef EXPECTED_MARKER
# error "EXPECTED_MARKER is not defined"
#endif
#define STRINGIFY_IMPL(x) #x
#define STRINGIFY(x) STRINGIFY_IMPL(x)
#if EXPECTED_MARKER > 0
# if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
static_assert(MARKER + 0 == EXPECTED_MARKER,
"MARKER has unexpected value " STRINGIFY(MARKER));
static_assert(MARKER + 0 == EXPECTED_MARKER, "CONFIG is " STRINGIFY(NAME));
# else
# if (MARKER + 0) != (EXPECTED_MARKER)
# error "MARKER has unexpected value"
# error "CONFIG mismatch for NAME"
# endif
# endif
#endif
#ifdef _WIN32
__declspec(dllexport)
#endif
void dummy_symbol()
{
}

View File

@@ -0,0 +1,21 @@
{
"cps_version": "0.13",
"name": "ConfigDefault",
"cps_path": "@prefix@/cps",
"configurations": [ "second", "first" ],
"components": {
"target": {
"type": "interface",
"configurations": {
"first": {
"definitions": {
"*": {
"NAME": "first",
"MARKER": "1"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
{
"cps_version": "0.13",
"name": "ConfigDefault",
"configuration": "second",
"components": {
"target": {
"definitions": {
"*": {
"NAME": "second",
"MARKER": "2"
}
}
}
}
}

View File

@@ -0,0 +1,20 @@
{
"cps_version": "0.13",
"name": "ConfigFirst",
"cps_path": "@prefix@/cps",
"components": {
"target": {
"type": "interface",
"configurations": {
"first": {
"definitions": {
"*": {
"NAME": "first",
"MARKER": "1"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
{
"cps_version": "0.13",
"name": "ConfigFirst",
"configuration": "second",
"components": {
"target": {
"definitions": {
"*": {
"NAME": "second",
"MARKER": "2"
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
{
"cps_version": "0.13",
"name": "ConfigMapped",
"cps_path": "@prefix@/cps",
"configurations": [ "default" ],
"components": {
"target": {
"type": "interface",
"configurations": {
"default": {
"definitions": {
"*": {
"NAME": "default",
"MARKER": "1"
}
}
},
"test": {
"definitions": {
"*": {
"NAME": "test",
"MARKER": "4"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
{
"cps_version": "0.13",
"name": "ConfigMatchBuildType",
"cps_path": "@prefix@/cps",
"configurations": [ "release", "debug"],
"components": {
"target": {
"type": "interface",
"configurations": {
"debug": {
"definitions": {
"*": {
"NAME": "debug",
"MARKER": "1"
}
}
},
"release": {
"definitions": {
"*": {
"NAME": "release",
"MARKER": "2"
}
}
},
"test": {
"definitions": {
"*": {
"NAME": "test",
"MARKER": "4"
}
}
}
}
}
}
}