From 82683ae8b0a8bcc363bf67cd787996380745accd Mon Sep 17 00:00:00 2001 From: Vito Gamberini Date: Wed, 15 Jul 2026 11:19:06 -0400 Subject: [PATCH] c++modules: discover synth targets for all configs Fixes: #26312 --- Source/cmCommonTargetGenerator.cxx | 4 +- Source/cmGeneratorTarget.cxx | 9 ++-- Source/cmGeneratorTarget.h | 4 +- .../CXXModulesCompile/RunCMakeTest.cmake | 8 ++- .../multi-config-synth/CMakeLists.txt | 54 +++++++++++++++++++ .../consumer/CMakeLists.txt | 10 ++++ .../multi-config-synth/consumer/main.cxx | 5 ++ .../multi-config-synth/importable.cxx | 5 ++ 8 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 Tests/RunCMake/CXXModulesCompile/multi-config-synth/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/main.cxx create mode 100644 Tests/RunCMake/CXXModulesCompile/multi-config-synth/importable.cxx diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index fa68e1e39f..f219c6e1c9 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -193,7 +193,7 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories( auto const& synthDeps = this->GeneratorTarget->GetSyntheticDeps(config); auto it = synthDeps.find(linkee); if (it != synthDeps.end() && !it->second.empty()) { - return it->second.front(); + return *it->second.begin(); } // Check linked targets to find synthetic targets for transitive deps @@ -227,7 +227,7 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories( auto itLinkeeSynth = transitiveSynthDeps.find(linkee); if (itLinkeeSynth != transitiveSynthDeps.end() && !itLinkeeSynth->second.empty()) { - return itLinkeeSynth->second.front(); + return *itLinkeeSynth->second.begin(); } for (auto const& entry : transitiveSynthDeps) { for (auto const* synth : entry.second) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 39ac753d1e..ed12e562b1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5590,8 +5590,11 @@ cmGeneratorTarget const* cmGeneratorTarget::GetCxxSyntheticTarget( lg->AddGeneratorTarget(std::move(gtp)); this->SynthCxxTargets[usageHash] = syntheticTarget; - if (!syntheticTarget->DiscoverSyntheticTargets(config, &bmiConsumer)) { - return nullptr; + for (auto const& innerConfig : allConfigs) { + if (!syntheticTarget->DiscoverSyntheticTargets(innerConfig, + &bmiConsumer)) { + return nullptr; + } } return syntheticTarget; @@ -5629,7 +5632,7 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets( return false; } if (dep->IsSynthetic()) { - SyntheticDeps[gt].push_back(dep); + SyntheticDeps[gt].insert(dep); } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index d0bcdcc164..4503247aef 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1155,7 +1155,7 @@ public: std::string const& config, cmGeneratorTarget const* bmiConsumer = nullptr); using SyntheticDepsMap = - std::map>; + std::map>; SyntheticDepsMap const& GetSyntheticDeps(std::string const& config) const; class CustomTransitiveProperty : public TransitiveProperty @@ -1613,7 +1613,7 @@ public: private: struct InfoByConfig { - std::map> + std::map> SyntheticDeps; std::map SourceFlags; }; diff --git a/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake b/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake index 3e30b89b62..d37cdbe3f2 100644 --- a/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModulesCompile/RunCMakeTest.cmake @@ -219,11 +219,15 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(scan_props) run_cxx_module_test(target-objects) - # mixed-bmi-compatibility requires a generator that implements per-importer - # BMI generation + # Requires a generator that implements per-importer BMI generation if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND RunCMake_GENERATOR MATCHES "Ninja") run_cxx_module_test(mixed-bmi-compatibility) + if (RunCMake_GENERATOR_IS_MULTI_CONFIG AND + "collation" IN_LIST CMake_TEST_MODULE_COMPILATION AND + "bmionly" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(multi-config-synth) + endif() endif() if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND diff --git a/Tests/RunCMake/CXXModulesCompile/multi-config-synth/CMakeLists.txt b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/CMakeLists.txt new file mode 100644 index 0000000000..fb343a065f --- /dev/null +++ b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.24...3.28) +project(cxx_modules_multi_config_synth CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(importable) +target_sources(importable + PUBLIC FILE_SET CXX_MODULES FILES importable.cxx) +target_compile_features(importable PUBLIC cxx_std_20) + +export(TARGETS importable + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/importable-targets.cmake" + CXX_MODULES_DIRECTORY "importable-cxx-modules" + ) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importable-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/importable-targets.cmake\")\n" + ) + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME multi_config_synth_consumer + COMMAND + "${CMAKE_COMMAND}" + "-DCMAKE_PREFIX_PATH=${CMAKE_CURRENT_BINARY_DIR}" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/consumer" + -B "${CMAKE_CURRENT_BINARY_DIR}/consumer" + ) +add_test(NAME multi_config_synth_build_debug + COMMAND + "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/consumer" --config Debug + ) +add_test(NAME multi_config_synth_build_release + COMMAND + "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/consumer" --config Release + ) +set_tests_properties( + multi_config_synth_build_debug + multi_config_synth_build_release + PROPERTIES DEPENDS multi_config_synth_consumer) +add_test(NAME multi_config_synth_run + COMMAND "${CMAKE_CTEST_COMMAND}" -C Debug --test-dir "${CMAKE_CURRENT_BINARY_DIR}/consumer" + ) +set_tests_properties(multi_config_synth_run + PROPERTIES DEPENDS multi_config_synth_build_debug) diff --git a/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/CMakeLists.txt b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/CMakeLists.txt new file mode 100644 index 0000000000..141b739458 --- /dev/null +++ b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.24...3.28) +project(cxx_modules_multi_config_consumer CXX) + +find_package(importable REQUIRED) + +add_executable(consumer main.cxx) +target_link_libraries(consumer PRIVATE CXXModules::importable) +target_compile_features(consumer PRIVATE cxx_std_20) + +add_test(NAME consumer COMMAND consumer) diff --git a/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/main.cxx b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/main.cxx new file mode 100644 index 0000000000..5ff7dc2ac3 --- /dev/null +++ b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/consumer/main.cxx @@ -0,0 +1,5 @@ +import importable; +int main() +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModulesCompile/multi-config-synth/importable.cxx b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/importable.cxx new file mode 100644 index 0000000000..ad83965376 --- /dev/null +++ b/Tests/RunCMake/CXXModulesCompile/multi-config-synth/importable.cxx @@ -0,0 +1,5 @@ +export module importable; +export int from_import() +{ + return 0; +}