diff options
author | Brad King <brad.king@kitware.com> | 2021-11-12 14:03:22 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2021-11-12 14:03:39 (GMT) |
commit | ea5d3f4d4c3094971e3938bf5b8b3abda99c53a5 (patch) | |
tree | b0ed9f80f822f9f87f887fef8c0d972cd3f86d48 /Source | |
parent | ad6da2d83f4897adf4108b6fc623ea11ee58feeb (diff) | |
parent | 129e3c65400a96c1f99b0fd6d445f1b9dc38ad51 (diff) | |
download | CMake-ea5d3f4d4c3094971e3938bf5b8b3abda99c53a5.zip CMake-ea5d3f4d4c3094971e3938bf5b8b3abda99c53a5.tar.gz CMake-ea5d3f4d4c3094971e3938bf5b8b3abda99c53a5.tar.bz2 |
Merge topic 'unity-build-per-config'
129e3c6540 Unity Build: Fix per-config sources in multi-config generators
ea289314ef VS: Fix pre-VS15.8 unity build exclusion of per-config sources
53990059da cmLocalGenerator: Add dedicated types to hold unity source info
de6e362a88 cmLocalGenerator: Clarify name of method to write unity source include lines
3017b3e7d4 cmLocalGenerator: Simplify unity source copy-if-different logic
0b56f92576 cmLocalGenerator: De-duplicate unity source file generation
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6720
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmLocalGenerator.cxx | 191 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 57 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 2 |
3 files changed, 160 insertions, 90 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 68a6a44..c106137 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -37,6 +37,7 @@ #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" #include "cmMakefile.h" +#include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" #include "cmSourceFileLocation.h" @@ -2806,10 +2807,47 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, } } -void cmLocalGenerator::IncludeFileInUnitySources( - cmGeneratedFileStream& unity_file, std::string const& sf_full_path, - cmValue beforeInclude, cmValue afterInclude, cmValue uniqueIdName) const +cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource( + cmGeneratorTarget* target, std::vector<std::string> const& configs, + cmRange<std::vector<UnityBatchedSource>::const_iterator> sources, + cmValue beforeInclude, cmValue afterInclude, std::string filename) const { + cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); + cmGeneratedFileStream file( + filename, false, target->GetGlobalGenerator()->GetMakefileEncoding()); + 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, cond, ubs.Source->ResolveFullPath(), + beforeInclude, afterInclude, uniqueIdName); + } + + return UnitySource(std::move(filename), perConfig); +} + +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) { @@ -2844,21 +2882,25 @@ void cmLocalGenerator::IncludeFileInUnitySources( if (afterInclude) { unity_file << *afterInclude << "\n"; } + if (cond) { + unity_file << "#endif\n"; + } unity_file << "\n"; } -std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto( +std::vector<cmLocalGenerator::UnitySource> +cmLocalGenerator::AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, - cmValue afterInclude, std::string const& filename_base, size_t batchSize) + std::vector<std::string> const& configs, + std::vector<UnityBatchedSource> const& filtered_sources, + cmValue beforeInclude, cmValue afterInclude, + std::string const& filename_base, size_t batchSize) { if (batchSize == 0) { batchSize = filtered_sources.size(); } - cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); - - std::vector<std::string> unity_files; + std::vector<UnitySource> unity_files; for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; itemsLeft > 0; itemsLeft -= chunk, ++batch) { @@ -2866,74 +2908,48 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto( std::string filename = cmStrCat(filename_base, "unity_", batch, (lang == "C") ? "_c.c" : "_cxx.cxx"); - - const std::string filename_tmp = cmStrCat(filename, ".tmp"); - { - size_t begin = batch * batchSize; - size_t end = begin + chunk; - - cmGeneratedFileStream file( - filename_tmp, false, - target->GetGlobalGenerator()->GetMakefileEncoding()); - file << "/* generated by CMake */\n\n"; - - for (; begin != end; ++begin) { - cmSourceFile* sf = filtered_sources[begin]; - RegisterUnitySources(target, sf, filename); - IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude, - afterInclude, uniqueIdName); - } - } - cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); - unity_files.emplace_back(std::move(filename)); + auto const begin = filtered_sources.begin() + batch * batchSize; + auto const end = begin + chunk; + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(begin, end), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; } -std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup( +std::vector<cmLocalGenerator::UnitySource> +cmLocalGenerator::AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, - cmValue afterInclude, std::string const& filename_base) + std::vector<std::string> const& configs, + std::vector<UnityBatchedSource> const& filtered_sources, + cmValue beforeInclude, cmValue afterInclude, + std::string const& filename_base) { - std::vector<std::string> unity_files; + std::vector<UnitySource> unity_files; // sources organized by group name. Drop any source // without a group - std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping; - for (cmSourceFile* sf : filtered_sources) { - if (cmValue value = sf->GetProperty("UNITY_GROUP")) { + std::unordered_map<std::string, std::vector<UnityBatchedSource>> + explicit_mapping; + for (UnityBatchedSource const& ubs : filtered_sources) { + if (cmValue value = ubs.Source->GetProperty("UNITY_GROUP")) { auto i = explicit_mapping.find(*value); if (i == explicit_mapping.end()) { - std::vector<cmSourceFile*> sources{ sf }; - explicit_mapping.emplace(*value, sources); + std::vector<UnityBatchedSource> sources{ ubs }; + explicit_mapping.emplace(*value, std::move(sources)); } else { - i->second.emplace_back(sf); + i->second.emplace_back(ubs); } } } - cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID"); - for (auto const& item : explicit_mapping) { auto const& name = item.first; std::string filename = cmStrCat(filename_base, "unity_", name, (lang == "C") ? "_c.c" : "_cxx.cxx"); - - const std::string filename_tmp = cmStrCat(filename, ".tmp"); - { - cmGeneratedFileStream file( - filename_tmp, false, - target->GetGlobalGenerator()->GetMakefileEncoding()); - file << "/* generated by CMake */\n\n"; - - for (cmSourceFile* sf : item.second) { - RegisterUnitySources(target, sf, filename); - IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude, - afterInclude, uniqueIdName); - } - } - cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); - unity_files.emplace_back(std::move(filename)); + unity_files.emplace_back(this->WriteUnitySource( + target, configs, cmMakeRange(item.second), beforeInclude, afterInclude, + std::move(filename))); } return unity_files; @@ -2945,20 +2961,33 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) return; } - // FIXME: Handle all configurations in multi-config generators. - std::string config; - if (!this->GetGlobalGenerator()->IsMultiConfig()) { - config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + std::vector<UnityBatchedSource> unitySources; + + 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, configs[ci]); + for (cmSourceFile* sf : sources) { + 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); + } } std::string filename_base = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", target->GetName(), ".dir/Unity/"); - // FIXME: Refactor collection of sources to not evaluate object libraries. - std::vector<cmSourceFile*> sources; - target->GetSourceFiles(sources, config); - cmValue batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE"); const size_t unityBatchSize = batchSizeString ? static_cast<size_t>(std::atoi(batchSizeString->c_str())) @@ -2970,9 +2999,11 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) cmValue unityMode = target->GetProperty("UNITY_BUILD_MODE"); for (std::string lang : { "C", "CXX" }) { - std::vector<cmSourceFile*> filtered_sources; - std::copy_if(sources.begin(), sources.end(), - std::back_inserter(filtered_sources), [&](cmSourceFile* sf) { + std::vector<UnityBatchedSource> filtered_sources; + std::copy_if(unitySources.begin(), unitySources.end(), + std::back_inserter(filtered_sources), + [&](UnityBatchedSource const& ubs) -> bool { + cmSourceFile* sf = ubs.Source; return sf->GetLanguage() == lang && !sf->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION") && !sf->GetPropertyAsBool("HEADER_FILE_ONLY") && @@ -2982,15 +3013,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) !sf->GetProperty("INCLUDE_DIRECTORIES"); }); - std::vector<std::string> unity_files; + 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 + @@ -2999,11 +3030,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) this->IssueMessage(MessageType::FATAL_ERROR, e); } - for (auto const& file : unity_files) { - auto* unity = this->GetMakefile()->GetOrCreateSource(file); - target->AddSource(file, true); + for (UnitySource const& file : unity_files) { + auto* unity = this->GetMakefile()->GetOrCreateSource(file.Path); + target->AddSource(file.Path, true); unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON"); - unity->SetProperty("UNITY_SOURCE_FILE", file); + unity->SetProperty("UNITY_SOURCE_FILE", file.Path); + if (file.PerConfig) { + unity->SetProperty("COMPILE_DEFINITIONS", + "CMAKE_UNITY_CONFIG_$<UPPER_CASE:$<CONFIG>>"); + } } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b86c8e8..726817a 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -11,8 +11,11 @@ #include <set> #include <string> #include <unordered_map> +#include <utility> #include <vector> +#include <cm/optional> + #include <cm3p/kwiml/int.h> #include "cmCustomCommandTypes.h" @@ -28,7 +31,6 @@ class cmComputeLinkInformation; class cmCustomCommand; class cmCustomCommandGenerator; class cmCustomCommandLines; -class cmGeneratedFileStream; class cmGeneratorTarget; class cmGlobalGenerator; class cmImplicitDependsList; @@ -40,6 +42,9 @@ class cmState; class cmTarget; class cmake; +template <typename Iter> +class cmRange; + /** Flag if byproducts shall also be considered. */ enum class cmSourceOutputKind { @@ -657,18 +662,48 @@ private: const std::string& ReuseFrom, cmGeneratorTarget* reuseTarget, std::vector<std::string> const& extensions); - void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, - std::string const& sf_full_path, - cmValue beforeInclude, cmValue afterInclude, - cmValue uniqueIdName) const; - std::vector<std::string> AddUnityFilesModeAuto( + + struct UnityBatchedSource + { + cmSourceFile* Source = nullptr; + std::vector<size_t> Configs; + UnityBatchedSource(cmSourceFile* sf) + : Source(sf) + { + } + }; + struct UnitySource + { + std::string Path; + bool PerConfig = false; + UnitySource(std::string path, bool perConfig) + : Path(std::move(path)) + , PerConfig(perConfig) + { + } + }; + + UnitySource WriteUnitySource( + cmGeneratorTarget* target, std::vector<std::string> const& configs, + cmRange<std::vector<UnityBatchedSource>::const_iterator> sources, + cmValue beforeInclude, cmValue afterInclude, std::string filename) const; + void WriteUnitySourceInclude(std::ostream& unity_file, + cm::optional<std::string> const& cond, + std::string const& sf_full_path, + cmValue beforeInclude, cmValue afterInclude, + cmValue uniqueIdName) const; + std::vector<UnitySource> AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, - cmValue afterInclude, std::string const& filename_base, size_t batchSize); - std::vector<std::string> AddUnityFilesModeGroup( + std::vector<std::string> const& configs, + std::vector<UnityBatchedSource> const& filtered_sources, + cmValue beforeInclude, cmValue afterInclude, + std::string const& filename_base, size_t batchSize); + std::vector<UnitySource> AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, - std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude, - cmValue afterInclude, std::string const& filename_base); + std::vector<std::string> const& configs, + std::vector<UnityBatchedSource> const& filtered_sources, + cmValue beforeInclude, cmValue afterInclude, + std::string const& filename_base); }; #if !defined(CMAKE_BOOTSTRAP) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index a7822b2..cd4326f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2351,7 +2351,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) // Visual Studio versions prior to 2017 15.8 do not know about unity // builds, thus we exclude the files already part of unity sources. if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) { - exclude_configs = si.Configs; + exclude_configs = all_configs; } } } |