From ee9da769725c3e58bbb002d648cfe75de94f7a78 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Fri, 22 Jan 2021 18:49:17 +1100 Subject: Unity: Generate reproducible unity IDs for anonymous namespaces Fixes: #21564 --- Source/cmLocalGenerator.cxx | 35 +++++++++++++++------- Source/cmLocalGenerator.h | 14 +++++++++ Tests/RunCMake/UnityBuild/f.cxx | 5 ++++ .../unitybuild_anon_ns-build-check.cmake | 10 +++++++ Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake | 2 +- 5 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 Tests/RunCMake/UnityBuild/f.cxx create mode 100644 Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 86eddc2..a6d898d 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2768,17 +2768,32 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, target->AddSourceFileToUnityBatch(sf->ResolveFullPath()); sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str()); } +} -inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, - std::string const& sf_full_path, - cmProp beforeInclude, - cmProp afterInclude, cmProp uniqueIdName) +void cmLocalGenerator::IncludeFileInUnitySources( + cmGeneratedFileStream& unity_file, std::string const& sf_full_path, + cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) { - if (uniqueIdName && !uniqueIdName->empty()) { - unity_file << "#undef " << *uniqueIdName << "\n" + std::string pathToHash; + auto PathEqOrSubDir = [](std::string const& a, std::string const& b) { + return (cmSystemTools::ComparePath(a, b) || + cmSystemTools::IsSubDirectory(a, b)); + }; + const auto path = cmSystemTools::GetFilenamePath(sf_full_path); + if (PathEqOrSubDir(path, this->GetBinaryDirectory())) { + pathToHash = "BLD_" + + cmSystemTools::RelativePath(this->GetBinaryDirectory(), sf_full_path); + } else if (PathEqOrSubDir(path, this->GetSourceDirectory())) { + pathToHash = "SRC_" + + cmSystemTools::RelativePath(this->GetSourceDirectory(), sf_full_path); + } else { + pathToHash = "ABS_" + sf_full_path; + } + unity_file << "/* " << pathToHash << " */\n" + << "#undef " << *uniqueIdName << "\n" << "#define " << *uniqueIdName << " unity_" - << cmSystemTools::ComputeStringMD5(sf_full_path) << "\n"; + << cmSystemTools::ComputeStringMD5(pathToHash) << "\n"; } if (beforeInclude) { @@ -2790,9 +2805,10 @@ inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, if (afterInclude) { unity_file << *afterInclude << "\n"; } + unity_file << "\n"; } -std::vector AddUnityFilesModeAuto( +std::vector cmLocalGenerator::AddUnityFilesModeAuto( cmGeneratorTarget* target, std::string const& lang, std::vector const& filtered_sources, cmProp beforeInclude, cmProp afterInclude, std::string const& filename_base, size_t batchSize) @@ -2835,7 +2851,7 @@ std::vector AddUnityFilesModeAuto( return unity_files; } -std::vector AddUnityFilesModeGroup( +std::vector cmLocalGenerator::AddUnityFilesModeGroup( cmGeneratorTarget* target, std::string const& lang, std::vector const& filtered_sources, cmProp beforeInclude, cmProp afterInclude, std::string const& filename_base) @@ -2883,7 +2899,6 @@ std::vector AddUnityFilesModeGroup( return unity_files; } -} void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 91dd8ae..a3610fd 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -27,6 +28,7 @@ class cmComputeLinkInformation; class cmCustomCommand; class cmCustomCommandGenerator; class cmCustomCommandLines; +class cmGeneratedFileStream; class cmGeneratorTarget; class cmGlobalGenerator; class cmImplicitDependsList; @@ -651,6 +653,18 @@ private: const std::string& ReuseFrom, cmGeneratorTarget* reuseTarget, std::vector const& extensions); + void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, + std::string const& sf_full_path, + cmProp beforeInclude, cmProp afterInclude, + cmProp uniqueIdName); + std::vector AddUnityFilesModeAuto( + cmGeneratorTarget* target, std::string const& lang, + std::vector const& filtered_sources, cmProp beforeInclude, + cmProp afterInclude, std::string const& filename_base, size_t batchSize); + std::vector AddUnityFilesModeGroup( + cmGeneratorTarget* target, std::string const& lang, + std::vector const& filtered_sources, cmProp beforeInclude, + cmProp afterInclude, std::string const& filename_base); }; #if !defined(CMAKE_BOOTSTRAP) diff --git a/Tests/RunCMake/UnityBuild/f.cxx b/Tests/RunCMake/UnityBuild/f.cxx new file mode 100644 index 0000000..d5813c6 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/f.cxx @@ -0,0 +1,5 @@ +int f(int x) +{ + (void)x; + return 0; +} diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake new file mode 100644 index 0000000..746be32 --- /dev/null +++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns-build-check.cmake @@ -0,0 +1,10 @@ +set(unitybuild_0 "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/tgt.dir/Unity/unity_0_cxx.cxx") + +file(STRINGS ${unitybuild_0} src) + +foreach(expectedRegex IN ITEMS "SRC_f\\.cxx" "BLD_s1\\.cpp") + if(NOT "${src}" MATCHES "${expectedRegex}") + set(RunCMake_TEST_FAILED "Generated unity file doesn't have a match for expected unity ID regex ${expectedRegex}") + return() + endif() +endforeach() diff --git a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake index 6f4878f..e05863d 100644 --- a/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake +++ b/Tests/RunCMake/UnityBuild/unitybuild_anon_ns.cmake @@ -4,7 +4,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/unitybuild_anon_ns_test_files.cmake) write_unity_build_anon_ns_test_files(srcs) -add_library(tgt SHARED ${srcs}) +add_library(tgt SHARED f.cxx ${srcs}) set_target_properties(tgt PROPERTIES UNITY_BUILD ON) -- cgit v0.12