diff options
author | Brad King <brad.king@kitware.com> | 2021-11-10 12:16:22 -0500 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-11-11 07:16:11 -0500 |
commit | 129e3c65400a96c1f99b0fd6d445f1b9dc38ad51 (patch) | |
tree | 602ca13d34bb8746548b3b56ecf2577ac9e050a0 /Source/cmLocalGenerator.cxx | |
parent | ea289314ef473d6bcdc1ca858aac6cdb15ecf56a (diff) | |
download | cmake-129e3c65400a96c1f99b0fd6d445f1b9dc38ad51.tar.gz |
Unity Build: Fix per-config sources in multi-config generators
Single-config generators already support unity builds with per-config
sources because they compute sources using `CMAKE_BUILD_TYPE` as the
configuration. Each original source is either included in the unity
build source, or not.
Teach multi-config generators to compute the list of sources for
inclusion in unity builds using all configurations. Previously they
only used the empty string as the configuration. Each original source
may be included in some configurations, but not others. Use
preprocessor conditions to guard their inclusion when necessary.
Fixes: #22892
Diffstat (limited to 'Source/cmLocalGenerator.cxx')
-rw-r--r-- | Source/cmLocalGenerator.cxx | 87 |
1 files changed, 58 insertions, 29 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3ac77c197b..c106137e13 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2808,7 +2808,7 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, } cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource( - cmGeneratorTarget* target, + cmGeneratorTarget* target, std::vector<std::string> const& configs, cmRange<std::vector<UnityBatchedSource>::const_iterator> sources, cmValue beforeInclude, cmValue afterInclude, std::string filename) const { @@ -2818,21 +2818,36 @@ cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource( file.SetCopyIfDifferent(true); file << "/* generated by CMake */\n\n"; + bool perConfig = false; for (UnityBatchedSource const& ubs : sources) { + cm::optional<std::string> cond; + if (ubs.Configs.size() != configs.size()) { + perConfig = true; + cond = std::string(); + cm::string_view sep; + for (size_t ci : ubs.Configs) { + cond = cmStrCat(*cond, sep, "defined(CMAKE_UNITY_CONFIG_", + cmSystemTools::UpperCase(configs[ci]), ")"); + sep = " || "_s; + } + } RegisterUnitySources(target, ubs.Source, filename); - WriteUnitySourceInclude(file, ubs.Source->ResolveFullPath(), beforeInclude, - afterInclude, uniqueIdName); + WriteUnitySourceInclude(file, cond, ubs.Source->ResolveFullPath(), + beforeInclude, afterInclude, uniqueIdName); } - return UnitySource(std::move(filename)); + return UnitySource(std::move(filename), perConfig); } -void cmLocalGenerator::WriteUnitySourceInclude(std::ostream& unity_file, - std::string const& sf_full_path, - cmValue beforeInclude, - cmValue afterInclude, - cmValue uniqueIdName) const +void cmLocalGenerator::WriteUnitySourceInclude( + std::ostream& unity_file, cm::optional<std::string> const& cond, + std::string const& sf_full_path, cmValue beforeInclude, cmValue afterInclude, + cmValue uniqueIdName) const { + if (cond) { + unity_file << "#if " << *cond << "\n"; + } + if (cmNonempty(uniqueIdName)) { std::string pathToHash; auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { @@ -2867,12 +2882,16 @@ void cmLocalGenerator::WriteUnitySourceInclude(std::ostream& unity_file, if (afterInclude) { unity_file << *afterInclude << "\n"; } + if (cond) { + unity_file << "#endif\n"; + } unity_file << "\n"; } std::vector<cmLocalGenerator::UnitySource> cmLocalGenerator::AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base, size_t batchSize) @@ -2891,9 +2910,9 @@ cmLocalGenerator::AddUnityFilesModeAuto( (lang == "C") ? "_c.c" : "_cxx.cxx"); auto const begin = filtered_sources.begin() + batch * batchSize; auto const end = begin + chunk; - unity_files.emplace_back( - this->WriteUnitySource(target, cmMakeRange(begin, end), beforeInclude, - afterInclude, std::move(filename))); + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(begin, end), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; } @@ -2901,6 +2920,7 @@ cmLocalGenerator::AddUnityFilesModeAuto( std::vector<cmLocalGenerator::UnitySource> cmLocalGenerator::AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, + std::vector<std::string> const& configs, std::vector<UnityBatchedSource> const& filtered_sources, cmValue beforeInclude, cmValue afterInclude, std::string const& filename_base) @@ -2927,9 +2947,9 @@ cmLocalGenerator::AddUnityFilesModeGroup( auto const& name = item.first; std::string filename = cmStrCat(filename_base, "unity_", name, (lang == "C") ? "_c.c" : "_cxx.cxx"); - unity_files.emplace_back( - this->WriteUnitySource(target, cmMakeRange(item.second), beforeInclude, - afterInclude, std::move(filename))); + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(item.second), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; @@ -2943,19 +2963,24 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<UnityBatchedSource> unitySources; - { - // FIXME: Handle all configurations in multi-config generators. - std::string config; - if (!this->GetGlobalGenerator()->IsMultiConfig()) { - config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - } + std::vector<std::string> configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + + std::map<cmSourceFile const*, size_t> index; + for (size_t ci = 0; ci < configs.size(); ++ci) { // FIXME: Refactor collection of sources to not evaluate object libraries. std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, config); - + target->GetSourceFiles(sources, configs[ci]); for (cmSourceFile* sf : sources) { - unitySources.emplace_back(sf); + auto mi = index.find(sf); + if (mi == index.end()) { + unitySources.emplace_back(sf); + std::map<cmSourceFile const*, size_t>::value_type entry( + sf, unitySources.size() - 1); + mi = index.insert(entry).first; + } + unitySources[mi->second].Configs.emplace_back(ci); } } @@ -2990,13 +3015,13 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) std::vector<UnitySource> unity_files; if (!unityMode || *unityMode == "BATCH") { - unity_files = - AddUnityFilesModeAuto(target, lang, filtered_sources, beforeInclude, - afterInclude, filename_base, unityBatchSize); + unity_files = AddUnityFilesModeAuto( + target, lang, configs, filtered_sources, beforeInclude, afterInclude, + filename_base, unityBatchSize); } else if (unityMode && *unityMode == "GROUP") { unity_files = - AddUnityFilesModeGroup(target, lang, filtered_sources, beforeInclude, - afterInclude, filename_base); + AddUnityFilesModeGroup(target, lang, configs, filtered_sources, + beforeInclude, afterInclude, filename_base); } else { // unity mode is set to an unsupported value std::string e("Invalid UNITY_BUILD_MODE value of " + *unityMode + @@ -3010,6 +3035,10 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) target->AddSource(file.Path, true); unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON"); unity->SetProperty("UNITY_SOURCE_FILE", file.Path); + if (file.PerConfig) { + unity->SetProperty("COMPILE_DEFINITIONS", + "CMAKE_UNITY_CONFIG_$<UPPER_CASE:$<CONFIG>>"); + } } } } |