Forráskód Böngészése

QtAutogen: Use checksum based subdirectories to avoid name collisions

Sebastian Holtermann 9 éve
szülő
commit
057ac11bfb

+ 2 - 2
Source/CMakeLists.txt

@@ -243,8 +243,8 @@ set(SRCS
   cmFileLockPool.h
   cmFileLockResult.cxx
   cmFileLockResult.h
-  cmFilePathUuid.cxx
-  cmFilePathUuid.h
+  cmFilePathChecksum.cxx
+  cmFilePathChecksum.h
   cmFileTimeComparison.cxx
   cmFileTimeComparison.h
   cmFortranLexer.cxx

+ 88 - 0
Source/cmFilePathChecksum.cxx

@@ -0,0 +1,88 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFilePathChecksum.h"
+
+#include "cmBase32.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include <vector>
+
+cmFilePathChecksum::cmFilePathChecksum()
+{
+}
+
+cmFilePathChecksum::cmFilePathChecksum(const std::string& currentSrcDir,
+                                       const std::string& currentBinDir,
+                                       const std::string& projectSrcDir,
+                                       const std::string& projectBinDir)
+{
+  setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
+}
+
+cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
+{
+  setupParentDirs(makefile->GetCurrentSourceDirectory(),
+                  makefile->GetCurrentBinaryDirectory(),
+                  makefile->GetHomeDirectory(),
+                  makefile->GetHomeOutputDirectory());
+}
+
+void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir,
+                                         const std::string& currentBinDir,
+                                         const std::string& projectSrcDir,
+                                         const std::string& projectBinDir)
+{
+  parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
+  parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
+  parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
+  parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
+
+  parentDirs[0].second = "CurrentSource";
+  parentDirs[1].second = "CurrentBinary";
+  parentDirs[2].second = "ProjectSource";
+  parentDirs[3].second = "ProjectBinary";
+}
+
+std::string cmFilePathChecksum::get(const std::string& filePath)
+{
+  std::string relPath;
+  std::string relSeed;
+  {
+    const std::string fileReal = cmsys::SystemTools::GetRealPath(filePath);
+    std::string parentDir;
+    // Find closest project parent directory
+    for (size_t ii = 0; ii != numParentDirs; ++ii) {
+      const std::string& pDir = parentDirs[ii].first;
+      if (!pDir.empty() &&
+          cmsys::SystemTools::IsSubDirectory(fileReal, pDir)) {
+        relSeed = parentDirs[ii].second;
+        parentDir = pDir;
+        break;
+      }
+    }
+    // Use file system root as fallback parent directory
+    if (parentDir.empty()) {
+      relSeed = "FileSystemRoot";
+      cmsys::SystemTools::SplitPathRootComponent(fileReal, &parentDir);
+    }
+    // Calculate relative path from project parent directory
+    relPath = cmsys::SystemTools::RelativePath(
+      parentDir, cmsys::SystemTools::GetParentDirectory(fileReal));
+  }
+
+  // Calculate the file ( seed + relative path ) binary checksum
+  std::vector<unsigned char> hashBytes =
+    cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
+
+  // Convert binary checksum to string
+  return cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(),
+                                        false);
+}
+
+std::string cmFilePathChecksum::getPart(const std::string& filePath,
+                                        size_t length)
+{
+  return get(filePath).substr(0, length);
+}

+ 65 - 0
Source/cmFilePathChecksum.h

@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFilePathChecksum_h
+#define cmFilePathChecksum_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <stddef.h>
+#include <string>
+#include <utility>
+
+class cmMakefile;
+
+/** \class cmFilePathChecksum
+ * @brief Generates a checksum for the parent directory of a file
+ *
+ * The checksum is calculated from the relative file path to the
+ * closest known project directory. This guarantees reproducibility
+ * when source and build directory differ e.g. for different project
+ * build directories.
+ */
+class cmFilePathChecksum
+{
+public:
+  /// Maximum number of characters to use from the path checksum
+  static const size_t partLengthDefault = 10;
+
+  /// @brief Parent directories are empty
+  cmFilePathChecksum();
+
+  /// @brief Initilizes the parent directories manually
+  cmFilePathChecksum(const std::string& currentSrcDir,
+                     const std::string& currentBinDir,
+                     const std::string& projectSrcDir,
+                     const std::string& projectBinDir);
+
+  /// @brief Initilizes the parent directories from a makefile
+  cmFilePathChecksum(cmMakefile* makefile);
+
+  /// @brief Allows parent directories setup after construction
+  ///
+  void setupParentDirs(const std::string& currentSrcDir,
+                       const std::string& currentBinDir,
+                       const std::string& projectSrcDir,
+                       const std::string& projectBinDir);
+
+  /* @brief Calculates the path checksum for the parent directory of a file
+   *
+   */
+  std::string get(const std::string& filePath);
+
+  /* @brief Same as get() but returns only the first length characters
+   *
+   */
+  std::string getPart(const std::string& filePath,
+                      size_t length = partLengthDefault);
+
+private:
+  /// Size of the parent directory list
+  static const size_t numParentDirs = 4;
+  /// List of (directory name, seed name) pairs
+  std::pair<std::string, std::string> parentDirs[numParentDirs];
+};
+
+#endif

+ 0 - 118
Source/cmFilePathUuid.cxx

@@ -1,118 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmFilePathUuid.h"
-
-#include "cmBase32.h"
-#include "cmCryptoHash.h"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
-
-#include <vector>
-
-cmFilePathUuid::cmFilePathUuid(cmMakefile* makefile)
-{
-  initParentDirs(makefile->GetCurrentSourceDirectory(),
-                 makefile->GetCurrentBinaryDirectory(),
-                 makefile->GetHomeDirectory(),
-                 makefile->GetHomeOutputDirectory());
-}
-
-cmFilePathUuid::cmFilePathUuid(const std::string& currentSrcDir,
-                               const std::string& currentBinDir,
-                               const std::string& projectSrcDir,
-                               const std::string& projectBinDir)
-{
-  initParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
-}
-
-void cmFilePathUuid::initParentDirs(const std::string& currentSrcDir,
-                                    const std::string& currentBinDir,
-                                    const std::string& projectSrcDir,
-                                    const std::string& projectBinDir)
-{
-  parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
-  parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
-  parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
-  parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
-
-  parentDirs[0].second = "CurrentSource";
-  parentDirs[1].second = "CurrentBinary";
-  parentDirs[2].second = "ProjectSource";
-  parentDirs[3].second = "ProjectBinary";
-}
-
-std::string cmFilePathUuid::get(const std::string& filePath,
-                                const char* outputPrefix,
-                                const char* outputSuffix)
-{
-  std::string sourceFilename = cmsys::SystemTools::GetFilenameName(filePath);
-  std::string sourceBasename =
-    cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFilename);
-
-  // Acquire checksum string
-  std::string checksum;
-  {
-    std::string sourceRelPath;
-    std::string sourceRelSeed;
-    GetRelPathSeed(filePath, sourceRelPath, sourceRelSeed);
-    checksum = GetChecksumString(sourceFilename, sourceRelPath, sourceRelSeed);
-  }
-
-  // Compose the file name
-  std::string uuid;
-  if (outputPrefix) {
-    uuid += outputPrefix;
-  }
-  uuid += sourceBasename.substr(0, partLengthName);
-  uuid += "_";
-  uuid += checksum.substr(0, partLengthCheckSum);
-  if (outputSuffix) {
-    uuid += outputSuffix;
-  }
-  return uuid;
-}
-
-void cmFilePathUuid::GetRelPathSeed(const std::string& filePath,
-                                    std::string& sourceRelPath,
-                                    std::string& sourceRelSeed)
-{
-  const std::string sourceNameReal = cmsys::SystemTools::GetRealPath(filePath);
-  std::string parentDirectory;
-  // Find closest project parent directory
-  for (size_t ii = 0; ii != numParentDirs; ++ii) {
-    const std::string& pDir = parentDirs[ii].first;
-    if (!pDir.empty() &&
-        cmsys::SystemTools::IsSubDirectory(sourceNameReal, pDir)) {
-      sourceRelSeed = parentDirs[ii].second;
-      parentDirectory = pDir;
-      break;
-    }
-  }
-  // Check if the file path is below a known project directory
-  if (parentDirectory.empty()) {
-    // Use file syste root as fallback parent directory
-    sourceRelSeed = "FileSystemRoot";
-    cmsys::SystemTools::SplitPathRootComponent(sourceNameReal,
-                                               &parentDirectory);
-  }
-  sourceRelPath = cmsys::SystemTools::RelativePath(
-    parentDirectory, cmsys::SystemTools::GetParentDirectory(sourceNameReal));
-}
-
-std::string cmFilePathUuid::GetChecksumString(
-  const std::string& sourceFilename, const std::string& sourceRelPath,
-  const std::string& sourceRelSeed)
-{
-  std::string checksumBase32;
-  {
-    // Calculate the file ( seed + relative path + name ) checksum
-    std::vector<unsigned char> hashBytes =
-      cmCryptoHash(cmCryptoHash::AlgoSHA256)
-        .ByteHashString(sourceRelSeed + sourceRelPath + sourceFilename);
-
-    checksumBase32 =
-      cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false);
-  }
-
-  return checksumBase32;
-}

+ 0 - 69
Source/cmFilePathUuid.h

@@ -1,69 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmFilePathUuid_h
-#define cmFilePathUuid_h
-
-#include <cmConfigure.h> // IWYU pragma: keep
-
-#include <stddef.h>
-#include <string>
-#include <utility>
-
-class cmMakefile;
-
-/** \class cmFilePathUuid
- * @brief Generates a unique pathless file name with a checksum component
- *        calculated from the file path.
- *
- * The checksum is calculated from the relative file path to the
- * closest known project directory. This guarantees reproducibility
- * when source and build directory differ e.g. for different project
- * build directories.
- */
-class cmFilePathUuid
-{
-public:
-  /// Maximum number of characters to use from the file name
-  static const size_t partLengthName = 14;
-  /// Maximum number of characters to use from the path checksum
-  static const size_t partLengthCheckSum = 14;
-
-  /// @brief Initilizes the parent directories from a makefile
-  cmFilePathUuid(cmMakefile* makefile);
-
-  /// @brief Initilizes the parent directories manually
-  cmFilePathUuid(const std::string& currentSrcDir,
-                 const std::string& currentBinDir,
-                 const std::string& projectSrcDir,
-                 const std::string& projectBinDir);
-
-  /* @brief Calculates and returns the uuid for a file path
-   *
-   * @arg outputPrefix optional string to prepend to the result
-   * @arg outputSuffix optional string to append to the result
-   */
-  std::string get(const std::string& filePath,
-                  const char* outputPrefix = CM_NULLPTR,
-                  const char* outputSuffix = CM_NULLPTR);
-
-private:
-  void initParentDirs(const std::string& currentSrcDir,
-                      const std::string& currentBinDir,
-                      const std::string& projectSrcDir,
-                      const std::string& projectBinDir);
-
-  /// Returns the relative path and the parent directory key string (seed)
-  void GetRelPathSeed(const std::string& filePath, std::string& sourceRelPath,
-                      std::string& sourceRelSeed);
-
-  std::string GetChecksumString(const std::string& sourceFilename,
-                                const std::string& sourceRelPath,
-                                const std::string& sourceRelSeed);
-
-  /// Size of the parent directory list
-  static const size_t numParentDirs = 4;
-  /// List of (directory name, seed name) pairs
-  std::pair<std::string, std::string> parentDirs[numParentDirs];
-};
-
-#endif

+ 26 - 14
Source/cmQtAutoGeneratorInitializer.cxx

@@ -4,7 +4,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
-#include "cmFilePathUuid.h"
+#include "cmFilePathChecksum.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
@@ -96,7 +96,7 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
 
   std::vector<std::string> newRccFiles;
 
-  cmFilePathUuid fpathUuid(makefile);
+  cmFilePathChecksum fpathCheckSum(makefile);
   for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
        fileIt != srcFiles.end(); ++fileIt) {
     cmSourceFile* sf = *fileIt;
@@ -115,15 +115,21 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
       if (ext == "qrc" &&
           !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
 
-        std::string rcc_output_file = GetAutogenTargetBuildDir(target);
-        // Create output directory
-        cmSystemTools::MakeDirectory(rcc_output_file.c_str());
-        rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
+        std::string rccOutputFile = GetAutogenTargetBuildDir(target);
+        rccOutputFile += fpathCheckSum.getPart(absFile);
+        rccOutputFile += "/qrc_";
+        rccOutputFile +=
+          cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
+        rccOutputFile += ".cpp";
 
         makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
-                                 rcc_output_file.c_str(), false);
-        makefile->GetOrCreateSource(rcc_output_file, true);
-        newRccFiles.push_back(rcc_output_file);
+                                 rccOutputFile.c_str(), false);
+        makefile->GetOrCreateSource(rccOutputFile, true);
+        newRccFiles.push_back(rccOutputFile);
+
+        // Create output directory
+        cmSystemTools::MakeDirectory(
+          cmsys::SystemTools::GetFilenamePath(rccOutputFile));
       }
     }
 
@@ -755,9 +761,9 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
 #endif
       ) {
     if (target->GetPropertyAsBool("AUTORCC")) {
+      cmFilePathChecksum fpathCheckSum(makefile);
       std::vector<cmSourceFile*> srcFiles;
       target->GetConfigCommonSourceFiles(srcFiles);
-      cmFilePathUuid fpathUuid(makefile);
       for (std::vector<cmSourceFile*>::const_iterator fileIt =
              srcFiles.begin();
            fileIt != srcFiles.end(); ++fileIt) {
@@ -767,11 +773,17 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
           {
             const std::string absFile =
               cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-            std::string rcc_output_file = GetAutogenTargetBuildDir(target);
+
+            std::string rccOutputFile = GetAutogenTargetBuildDir(target);
+            rccOutputFile += fpathCheckSum.getPart(absFile);
+            rccOutputFile += "/qrc_";
+            rccOutputFile +=
+              cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
+            rccOutputFile += ".cpp";
+            rcc_output.push_back(rccOutputFile);
             // Create output directory
-            cmSystemTools::MakeDirectory(rcc_output_file.c_str());
-            rcc_output_file += fpathUuid.get(absFile, "qrc_", ".cpp");
-            rcc_output.push_back(rcc_output_file);
+            cmSystemTools::MakeDirectory(
+              cmsys::SystemTools::GetFilenamePath(rccOutputFile));
           }
           if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
             RccListInputs(qtMajorVersion, sf, target, depends);

+ 21 - 26
Source/cmQtAutoGenerators.cxx

@@ -15,7 +15,6 @@
 #include <utility>
 
 #include "cmAlgorithms.h"
-#include "cmFilePathUuid.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
@@ -397,6 +396,11 @@ void cmQtAutoGenerators::Init()
 
   this->OutMocCppFilenameAbs = this->Builddir + this->OutMocCppFilenameRel;
 
+  // Init file path checksum generator
+  fpathCheckSum.setupParentDirs(this->Srcdir, this->Builddir,
+                                this->ProjectSourceDir,
+                                this->ProjectBinaryDir);
+
   std::vector<std::string> cdefList;
   cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
   for (std::vector<std::string>::const_iterator it = cdefList.begin();
@@ -967,8 +971,6 @@ void cmQtAutoGenerators::ParseHeaders(
   std::map<std::string, std::string>& notIncludedMocs,
   std::map<std::string, std::vector<std::string> >& includedUis)
 {
-  cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
-                           this->ProjectSourceDir, this->ProjectBinaryDir);
   for (std::set<std::string>::const_iterator hIt = absHeaders.begin();
        hIt != absHeaders.end(); ++hIt) {
     const std::string& headerName = *hIt;
@@ -984,8 +986,10 @@ void cmQtAutoGenerators::ParseHeaders(
 
       std::string macroName;
       if (requiresMocing(contents, macroName)) {
-        notIncludedMocs[headerName] =
-          this->TargetBuildSubDir + fpathUuid.get(headerName, "moc_", ".cpp");
+        notIncludedMocs[headerName] = this->TargetBuildSubDir +
+          fpathCheckSum.getPart(headerName) + "/moc_" +
+          cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) +
+          ".cpp";
       }
     }
     this->ParseForUic(headerName, contents, includedUis);
@@ -1318,18 +1322,13 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
 {
   // generate single map with input / output names
   std::map<std::string, std::string> qrcGenMap;
-  {
-    cmFilePathUuid fpathUuid(this->Srcdir, this->Builddir,
-                             this->ProjectSourceDir, this->ProjectBinaryDir);
-    for (std::vector<std::string>::const_iterator si =
-           this->RccSources.begin();
-         si != this->RccSources.end(); ++si) {
-      const std::string ext =
-        cmsys::SystemTools::GetFilenameLastExtension(*si);
-      if (ext == ".qrc") {
-        qrcGenMap[*si] =
-          (this->TargetBuildSubDir + fpathUuid.get(*si, "qrc_", ".cpp"));
-      }
+  for (std::vector<std::string>::const_iterator si = this->RccSources.begin();
+       si != this->RccSources.end(); ++si) {
+    const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si);
+    if (ext == ".qrc") {
+      qrcGenMap[*si] = this->TargetBuildSubDir + fpathCheckSum.getPart(*si) +
+        "/qrc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(*si) +
+        ".cpp";
     }
   }
 
@@ -1368,15 +1367,11 @@ bool cmQtAutoGenerators::GenerateQrc(const std::string& qrcInputFile,
                                      const std::string& qrcOutputFile,
                                      bool unique_n)
 {
-  std::string symbolName;
-  if (unique_n) {
-    symbolName =
-      cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
-  } else {
-    symbolName =
-      cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcOutputFile);
-    // Remove "qrc_" at string begin
-    symbolName.erase(0, 4);
+  std::string symbolName =
+    cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
+  if (!unique_n) {
+    symbolName += "_";
+    symbolName += fpathCheckSum.getPart(qrcInputFile);
   }
   // Replace '-' with '_'. The former is valid for
   // file names but not for symbol names.

+ 3 - 0
Source/cmQtAutoGenerators.h

@@ -4,6 +4,7 @@
 #define cmQtAutoGenerators_h
 
 #include <cmConfigure.h> // IWYU pragma: keep
+#include <cmFilePathChecksum.h>
 
 #include <list>
 #include <map>
@@ -130,6 +131,8 @@ private:
   std::map<std::string, std::string> RccOptions;
   std::map<std::string, std::vector<std::string> > RccInputs;
 
+  cmFilePathChecksum fpathCheckSum;
+
   bool IncludeProjectDirsBefore;
   bool Verbose;
   bool ColorOutput;