Browse Source

Unity: Generate reproducible unity IDs for anonymous namespaces

Fixes: #21564
Craig Scott 4 năm trước cách đây
mục cha
commit
ee9da76972

+ 25 - 10
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<std::string> AddUnityFilesModeAuto(
+std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
   cmGeneratorTarget* target, std::string const& lang,
   std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
   cmProp afterInclude, std::string const& filename_base, size_t batchSize)
@@ -2835,7 +2851,7 @@ std::vector<std::string> AddUnityFilesModeAuto(
   return unity_files;
 }
 
-std::vector<std::string> AddUnityFilesModeGroup(
+std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
   cmGeneratorTarget* target, std::string const& lang,
   std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
   cmProp afterInclude, std::string const& filename_base)
@@ -2883,7 +2899,6 @@ std::vector<std::string> AddUnityFilesModeGroup(
 
   return unity_files;
 }
-}
 
 void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
 {

+ 14 - 0
Source/cmLocalGenerator.h

@@ -4,6 +4,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <cstddef>
 #include <iosfwd>
 #include <map>
 #include <memory>
@@ -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<std::string> const& extensions);
+  void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
+                                 std::string const& sf_full_path,
+                                 cmProp beforeInclude, cmProp afterInclude,
+                                 cmProp uniqueIdName);
+  std::vector<std::string> AddUnityFilesModeAuto(
+    cmGeneratorTarget* target, std::string const& lang,
+    std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
+    cmProp afterInclude, std::string const& filename_base, size_t batchSize);
+  std::vector<std::string> AddUnityFilesModeGroup(
+    cmGeneratorTarget* target, std::string const& lang,
+    std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
+    cmProp afterInclude, std::string const& filename_base);
 };
 
 #if !defined(CMAKE_BOOTSTRAP)

+ 5 - 0
Tests/RunCMake/UnityBuild/f.cxx

@@ -0,0 +1,5 @@
+int f(int x)
+{
+  (void)x;
+  return 0;
+}

+ 10 - 0
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()

+ 1 - 1
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)