diff options
Diffstat (limited to 'Source/cmLocalGenerator.cxx')
-rw-r--r-- | Source/cmLocalGenerator.cxx | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7177694..6fade3e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -38,6 +38,7 @@ #include <algorithm> #include <assert.h> +#include <cstdlib> #include <functional> #include <initializer_list> #include <iterator> @@ -2202,6 +2203,90 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target, } } +void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target, + const std::string& config) +{ + if (!target->GetPropertyAsBool("UNITY_BUILD")) { + return; + } + + const std::string buildType = cmSystemTools::UpperCase(config); + + std::string filename_base = + cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", + target->GetName(), ".dir/Unity/"); + + std::vector<cmSourceFile*> sources; + target->GetSourceFiles(sources, buildType); + + auto batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE"); + const size_t unityBatchSize = + static_cast<size_t>(std::atoi(batchSizeString)); + + auto beforeInclude = target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE"); + auto afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE"); + + 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) { + return sf->GetLanguage() == lang && + !sf->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION") && + !sf->GetPropertyAsBool("GENERATED") && + !sf->GetProperty("COMPILE_OPTIONS") && + !sf->GetProperty("COMPILE_DEFINITIONS") && + !sf->GetProperty("COMPILE_FLAGS") && + !sf->GetProperty("INCLUDE_DIRECTORIES"); + }); + + size_t batchSize = unityBatchSize; + if (unityBatchSize == 0) { + batchSize = filtered_sources.size(); + } + + for (size_t itemsLeft = filtered_sources.size(), chunk = batchSize, + batch = 0; + itemsLeft > 0; itemsLeft -= chunk, ++batch) { + + chunk = std::min(itemsLeft, batchSize); + + std::string filename = cmStrCat(filename_base, "unity_", batch, + (lang == "C") ? ".c" : ".cxx"); + + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + size_t begin = batch * batchSize; + size_t end = begin + chunk; + + cmGeneratedFileStream file( + filename_tmp, false, + this->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + + for (; begin != end; ++begin) { + cmSourceFile* sf = filtered_sources[begin]; + + sf->SetProperty("HEADER_FILE_ONLY", "ON"); + + if (beforeInclude) { + file << beforeInclude << "\n"; + } + + file << "#include \"" << sf->GetFullPath() << "\"\n"; + + if (afterInclude) { + file << afterInclude << "\n"; + } + } + } + cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); + cmSystemTools::RemoveFile(filename_tmp); + + target->AddSource(filename, true); + } + } +} + void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, const std::string& config, |