diff options
author | Brad King <brad.king@kitware.com> | 2024-01-10 15:14:58 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2024-01-10 15:15:46 (GMT) |
commit | 446abdf324621fe7c0df14301b418cd5ceddf0f5 (patch) | |
tree | 7fd077dfcb2f071d4a96fe99cdcfb2b324098bed | |
parent | 8c4f0bf6a3c45d7442b851dd3e9ee28ced2e730f (diff) | |
parent | 63bbb3768d3cf87459b6b66effa8726f38cc745a (diff) | |
download | CMake-446abdf324621fe7c0df14301b418cd5ceddf0f5.zip CMake-446abdf324621fe7c0df14301b418cd5ceddf0f5.tar.gz CMake-446abdf324621fe7c0df14301b418cd5ceddf0f5.tar.bz2 |
Merge topic 'cxxmodules-no-unity'
63bbb3768d cmLocalGenerator: ignore scanned sources for unity builds
76b5383123 cmGlobalGenerator: add unity sources after computing target compile features
7fc2a83fe6 Tests/CXXModules: add a test with unity build support
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !9118
-rw-r--r-- | Help/manual/cmake-cxxmodules.7.rst | 4 | ||||
-rw-r--r-- | Help/prop_sf/SKIP_UNITY_BUILD_INCLUSION.rst | 4 | ||||
-rw-r--r-- | Help/prop_tgt/UNITY_BUILD.rst | 5 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 30 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 9 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/CMakeLists.txt | 26 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/importable.cxx | 10 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/main.cxx | 6 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/unity.h | 7 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/unity1.cxx | 8 | ||||
-rw-r--r-- | Tests/RunCMake/CXXModules/examples/unity-build/unity2.cxx | 10 |
13 files changed, 120 insertions, 1 deletions
diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index b4c9cf1..3ee6645 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -30,6 +30,10 @@ following queries. The first query that provides a yes/no answer is used. - Otherwise, the source file will be scanned if the compiler and generator support scanning. See policy :policy:`CMP0155`. +Note that any scanned source will be excluded from any unity build (see +:prop_tgt:`UNITY_BUILD`) because module-related statements can only happen at +one place within a C++ translation unit. + Compiler Support ================ diff --git a/Help/prop_sf/SKIP_UNITY_BUILD_INCLUSION.rst b/Help/prop_sf/SKIP_UNITY_BUILD_INCLUSION.rst index ae526ac..38a0a78 100644 --- a/Help/prop_sf/SKIP_UNITY_BUILD_INCLUSION.rst +++ b/Help/prop_sf/SKIP_UNITY_BUILD_INCLUSION.rst @@ -11,3 +11,7 @@ in the same way as it would with unity builds disabled. This property helps with "ODR (One definition rule)" problems where combining a particular source file with others might lead to build errors or other unintended side effects. + +Note that sources which are scanned for C++ modules (see +:manual:`cmake-cxxmodules(7)`) are not eligible for unity build inclusion and +will automatically be excluded. diff --git a/Help/prop_tgt/UNITY_BUILD.rst b/Help/prop_tgt/UNITY_BUILD.rst index 52f4714..577b0c9 100644 --- a/Help/prop_tgt/UNITY_BUILD.rst +++ b/Help/prop_tgt/UNITY_BUILD.rst @@ -76,6 +76,11 @@ a number of measures to help address such problems: :prop_sf:`INCLUDE_DIRECTORIES` source property will not be combined into a unity source. +* Any source file which is scanned for C++ module sources via + :prop_tgt:`CXX_SCAN_FOR_MODULES`, :prop_sf:`CXX_SCAN_FOR_MODULES`, or + membership of a ``CXX_MODULES`` file set will not be combined into a unity + source. See :manual:`cmake-cxxmodules(7)` for details. + * Projects can prevent an individual source file from being combined into a unity source by setting its :prop_sf:`SKIP_UNITY_BUILD_INCLUSION` source property to true. This can be a more effective way to prevent diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index e74a8b0..8a07073 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1612,6 +1612,13 @@ bool cmGlobalGenerator::Compute() } } + // Add unity sources after computing compile features. Unity sources do + // not change the set of languages or features, but we need to know them + // to filter out sources that are scanned for C++ module dependencies. + if (!this->AddUnitySources()) { + return false; + } + for (const auto& localGen : this->LocalGenerators) { cmMakefile* mf = localGen->GetMakefile(); for (const auto& g : mf->GetInstallGenerators()) { @@ -1888,7 +1895,6 @@ bool cmGlobalGenerator::AddAutomaticSources() if (!gt->CanCompileSources()) { continue; } - lg->AddUnityBuild(gt.get()); lg->AddISPCDependencies(gt.get()); // Targets that reuse a PCH are handled below. if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { @@ -1920,6 +1926,28 @@ bool cmGlobalGenerator::AddAutomaticSources() return true; } +bool cmGlobalGenerator::AddUnitySources() +{ + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { + if (!gt->CanCompileSources()) { + continue; + } + lg->AddUnityBuild(gt.get()); + } + } + // The above transformation may have changed the classification of sources. + // Clear the source list and classification cache (KindedSources) of all + // targets so that it will be recomputed correctly by the generators later + // now that the above transformations are done for all targets. + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { + gt->ClearSourcesCache(); + } + } + return true; +} + std::unique_ptr<cmLinkLineComputer> cmGlobalGenerator::CreateLinkLineComputer( cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index d83b669..b1ce323 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -679,6 +679,7 @@ protected: bool AddHeaderSetVerification(); bool AddAutomaticSources(); + bool AddUnitySources(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 38c49ed..ab1de4f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -3210,6 +3210,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<cmSourceFile*> sources; target->GetSourceFiles(sources, configs[ci]); for (cmSourceFile* sf : sources) { + // Files which need C++ scanning cannot participate in unity builds as + // there is a single place in TUs that may perform module-dependency bits + // and a unity source cannot `#include` them in-order and represent a + // valid TU. + if (sf->GetLanguage() == "CXX"_s && + target->NeedDyndepForSource("CXX", configs[ci], sf)) { + continue; + } + auto mi = index.find(sf); if (mi == index.end()) { unitySources.emplace_back(sf); diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index fcfa60a..cd7527a 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -171,6 +171,7 @@ run_cxx_module_test(scan-with-pch) if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(simple) run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF) + run_cxx_module_test(unity-build) run_cxx_module_test(object-library) run_cxx_module_test(generated) run_cxx_module_test(deep-chain) diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/unity-build/CMakeLists.txt new file mode 100644 index 0000000..ce1751d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.28) +project(cxx_modules_unity CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_UNITY_BUILD 1) + +add_executable(unity) +target_sources(unity + PRIVATE + main.cxx + unity1.cxx + unity2.cxx + PRIVATE + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(unity PUBLIC cxx_std_20) + +set_property(SOURCE unity1.cxx unity2.cxx + PROPERTY + CXX_SCAN_FOR_MODULES 0) + +add_test(NAME unity COMMAND unity) diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/unity-build/importable.cxx new file mode 100644 index 0000000..148b033 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/importable.cxx @@ -0,0 +1,10 @@ +module; + +#include "unity.h" + +export module importable; + +export int from_import() +{ + return unity1() + unity2(); +} diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/main.cxx b/Tests/RunCMake/CXXModules/examples/unity-build/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/unity.h b/Tests/RunCMake/CXXModules/examples/unity-build/unity.h new file mode 100644 index 0000000..4a65a4b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/unity.h @@ -0,0 +1,7 @@ +#ifndef unity_h +#define unity_h + +int unity1(); +int unity2(); + +#endif diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/unity1.cxx b/Tests/RunCMake/CXXModules/examples/unity-build/unity1.cxx new file mode 100644 index 0000000..fd1cbb3 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/unity1.cxx @@ -0,0 +1,8 @@ +#include "unity.h" + +#define DETECT_UNITY + +int unity1() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/unity-build/unity2.cxx b/Tests/RunCMake/CXXModules/examples/unity-build/unity2.cxx new file mode 100644 index 0000000..0f25cff --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/unity-build/unity2.cxx @@ -0,0 +1,10 @@ +#include "unity.h" + +#ifndef DETECT_UNITY +# error "Should have detected a unity build" +#endif + +int unity2() +{ + return 0; +} |