|
|
@@ -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,
|