From 58d99508421d6a767d8d7c4aa6eb2db54ccba1fa Mon Sep 17 00:00:00 2001 From: Vito Gamberini Date: Mon, 30 Jun 2025 11:11:06 -0400 Subject: [PATCH] CPS: Fix empty configuration field on noconfig builds Fixes: #27044 --- Source/cmExportBuildPackageInfoGenerator.cxx | 3 ++- .../cmExportInstallPackageInfoGenerator.cxx | 2 +- .../ExportPackageInfo/Assertions.cmake | 5 ++++ .../PerConfigGeneration-check.cmake | 14 +++++++++++ .../PerConfigGeneration.cmake | 13 ++++++++++ .../ExportPackageInfo/RunCMakeTest.cmake | 1 + .../InstallPackageInfo/Assertions.cmake | 5 ++++ .../PerConfigGeneration-check.cmake | 24 +++++++++++++++++++ .../PerConfigGeneration.cmake | 13 ++++++++++ .../InstallPackageInfo/RunCMakeTest.cmake | 1 + 10 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 Tests/RunCMake/ExportPackageInfo/PerConfigGeneration-check.cmake create mode 100644 Tests/RunCMake/ExportPackageInfo/PerConfigGeneration.cmake create mode 100644 Tests/RunCMake/InstallPackageInfo/PerConfigGeneration-check.cmake create mode 100644 Tests/RunCMake/InstallPackageInfo/PerConfigGeneration.cmake diff --git a/Source/cmExportBuildPackageInfoGenerator.cxx b/Source/cmExportBuildPackageInfoGenerator.cxx index 775360194d..980bb299f0 100644 --- a/Source/cmExportBuildPackageInfoGenerator.cxx +++ b/Source/cmExportBuildPackageInfoGenerator.cxx @@ -103,7 +103,8 @@ void cmExportBuildPackageInfoGenerator::GenerateInterfacePropertiesConfig( Json::Value component = this->GenerateInterfaceConfigProperties(suffix, properties); if (!component.empty()) { - configurations[config] = std::move(component); + configurations[config.empty() ? std::string{ "noconfig" } : config] = + std::move(component); } } diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx index 1571c50b2a..5a660c4e35 100644 --- a/Source/cmExportInstallPackageInfoGenerator.cxx +++ b/Source/cmExportInstallPackageInfoGenerator.cxx @@ -117,7 +117,7 @@ void cmExportInstallPackageInfoGenerator::GenerateImportTargetsConfig( { Json::Value root; root["name"] = this->GetPackageName(); - root["configuration"] = config; + root["configuration"] = (config.empty() ? "noconfig" : config); Json::Value& components = root["components"]; diff --git a/Tests/RunCMake/ExportPackageInfo/Assertions.cmake b/Tests/RunCMake/ExportPackageInfo/Assertions.cmake index 815761841a..068074da2a 100644 --- a/Tests/RunCMake/ExportPackageInfo/Assertions.cmake +++ b/Tests/RunCMake/ExportPackageInfo/Assertions.cmake @@ -20,6 +20,11 @@ function(expect_array content expected_length) _expect("length" EQUAL "${actual_length}" "${expected_length}" ${ARGN}) endfunction() +function(expect_object content) + string(JSON actual_type TYPE "${content}" ${ARGN}) + _expect("type" STREQUAL "${actual_type}" "OBJECT" ${ARGN}) +endfunction() + function(expect_null content) string(JSON actual_type TYPE "${content}" ${ARGN}) _expect("type" STREQUAL "${actual_type}" "NULL" ${ARGN}) diff --git a/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration-check.cmake b/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration-check.cmake new file mode 100644 index 0000000000..221942fe5a --- /dev/null +++ b/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration-check.cmake @@ -0,0 +1,14 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/PerConfigGeneration-build") + +file(READ "${out_dir}/foo.cps" content) + +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + foreach(config ${CMAKE_CONFIGURATION_TYPES}) + expect_object("${content}" "components" "foo" "configurations" ${config}) + endforeach() +else() + include(${RunCMake_TEST_BINARY_DIR}/build_type.cmake) + expect_object("${content}" "components" "foo" "configurations" ${config}) +endif() diff --git a/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration.cmake b/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration.cmake new file mode 100644 index 0000000000..ed9b29ae9a --- /dev/null +++ b/Tests/RunCMake/ExportPackageInfo/PerConfigGeneration.cmake @@ -0,0 +1,13 @@ +project(PerConfigGeneration CXX) + +set(config ${CMAKE_BUILD_TYPE}) +if(NOT config) + set(config noconfig) +endif() + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/build_type.cmake" "set(config \"${config}\")") + +add_library(foo foo.cxx) + +install(TARGETS foo EXPORT foo) +export(EXPORT foo PACKAGE_INFO foo) diff --git a/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake index 486d5cee5d..6fee4ac24b 100644 --- a/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake @@ -40,3 +40,4 @@ run_cmake(Requirements) run_cmake(TargetTypes) run_cmake(DependsMultiple) run_cmake(LinkOnly) +run_cmake(PerConfigGeneration) diff --git a/Tests/RunCMake/InstallPackageInfo/Assertions.cmake b/Tests/RunCMake/InstallPackageInfo/Assertions.cmake index 815761841a..068074da2a 100644 --- a/Tests/RunCMake/InstallPackageInfo/Assertions.cmake +++ b/Tests/RunCMake/InstallPackageInfo/Assertions.cmake @@ -20,6 +20,11 @@ function(expect_array content expected_length) _expect("length" EQUAL "${actual_length}" "${expected_length}" ${ARGN}) endfunction() +function(expect_object content) + string(JSON actual_type TYPE "${content}" ${ARGN}) + _expect("type" STREQUAL "${actual_type}" "OBJECT" ${ARGN}) +endfunction() + function(expect_null content) string(JSON actual_type TYPE "${content}" ${ARGN}) _expect("type" STREQUAL "${actual_type}" "NULL" ${ARGN}) diff --git a/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration-check.cmake b/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration-check.cmake new file mode 100644 index 0000000000..5ff99a5f6b --- /dev/null +++ b/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration-check.cmake @@ -0,0 +1,24 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/PerConfigGeneration-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +macro(check_config) + string(TOLOWER "${config}" config_lower) + if(NOT EXISTS "${out_dir}/foo@${config_lower}.cps") + set(RunCMake_TEST_FAILED + "Configuration file for '${config}' does not exist") + return() + endif() + + file(READ "${out_dir}/foo@${config_lower}.cps" content) + expect_value("${content}" "${config}" "configuration") +endmacro() + +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + foreach(config ${CMAKE_CONFIGURATION_TYPES}) + check_config() + endforeach() +else() + include(${RunCMake_TEST_BINARY_DIR}/build_type.cmake) + check_config() +endif() diff --git a/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration.cmake b/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration.cmake new file mode 100644 index 0000000000..4f4c149c0d --- /dev/null +++ b/Tests/RunCMake/InstallPackageInfo/PerConfigGeneration.cmake @@ -0,0 +1,13 @@ +project(PerConfigGeneration CXX) + +set(config ${CMAKE_BUILD_TYPE}) +if(NOT config) + set(config noconfig) +endif() + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/build_type.cmake" "set(config \"${config}\")") + +add_library(foo foo.cxx) + +install(TARGETS foo EXPORT foo) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo) diff --git a/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake index c31a289f55..bcd2ef81a5 100644 --- a/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake +++ b/Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake @@ -48,4 +48,5 @@ run_cmake(Requirements) run_cmake(TargetTypes) run_cmake(DependsMultiple) run_cmake(DependsMultipleNotInstalled) +run_cmake(PerConfigGeneration) run_cmake_install(Destination)