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

Autogen: Add lock file to AUTORCC commands

By using a per .qrc lock file in AUTORCC, the same
`cmake -E cmake_autorcc ...` command can be called concurrently.
Sebastian Holtermann 7 éve
szülő
commit
2930a198f6

+ 6 - 0
Source/cmQtAutoGenInitializer.cxx

@@ -588,8 +588,13 @@ void cmQtAutoGenInitializer::InitCustomTargets()
           if (!qrc.Unique) {
             base += qrc.PathChecksum;
           }
+
+          qrc.LockFile = base;
+          qrc.LockFile += ".lock";
+
           qrc.InfoFile = base;
           qrc.InfoFile += "Info.cmake";
+
           qrc.SettingsFile = base;
           qrc.SettingsFile += "Settings.txt";
         }
@@ -1043,6 +1048,7 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
         CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
 
         ofs << "# Rcc job\n";
+        CWrite("ARCC_LOCK_FILE", qrc.LockFile);
         CWrite("ARCC_SOURCE", qrc.QrcFile);
         CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
         CWrite("ARCC_OUTPUT_NAME",

+ 1 - 0
Source/cmQtAutoGenInitializer.h

@@ -32,6 +32,7 @@ public:
     }
 
   public:
+    std::string LockFile;
     std::string QrcFile;
     std::string QrcName;
     std::string PathChecksum;

+ 3 - 2
Source/cmQtAutoGenerator.cxx

@@ -367,10 +367,11 @@ bool cmQtAutoGenerator::FileSystem::FileRemove(std::string const& filename)
   return cmSystemTools::RemoveFile(filename);
 }
 
-bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename)
+bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename,
+                                          bool create)
 {
   std::lock_guard<std::mutex> lock(Mutex_);
-  return cmSystemTools::Touch(filename, false);
+  return cmSystemTools::Touch(filename, create);
 }
 
 bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)

+ 1 - 1
Source/cmQtAutoGenerator.h

@@ -124,7 +124,7 @@ public:
     bool FileDiffers(std::string const& filename, std::string const& content);
 
     bool FileRemove(std::string const& filename);
-    bool Touch(std::string const& filename);
+    bool Touch(std::string const& filename, bool create = false);
 
     // -- Directory access
     bool MakeDirectory(std::string const& dirname);

+ 47 - 5
Source/cmQtAutoGeneratorRcc.cxx

@@ -5,6 +5,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
+#include "cmFileLockResult.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 #include "cmUVHandlePtr.h"
@@ -89,6 +90,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
   RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
 
   // - Job
+  LockFile_ = InfoGet("ARCC_LOCK_FILE");
   QrcFile_ = InfoGet("ARCC_SOURCE");
   QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
   QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
@@ -101,6 +103,10 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
   SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
 
   // - Validity checks
+  if (LockFile_.empty()) {
+    Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Lock file name missing");
+    return false;
+  }
   if (SettingsFile_.empty()) {
     Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
     return false;
@@ -170,8 +176,11 @@ void cmQtAutoGeneratorRcc::PollStage()
   switch (Stage_) {
     // -- Initialize
     case StageT::SETTINGS_READ:
-      SettingsFileRead();
-      SetStage(StageT::TEST_QRC_RCC_FILES);
+      if (SettingsFileRead()) {
+        SetStage(StageT::TEST_QRC_RCC_FILES);
+      } else {
+        SetStage(StageT::FINISH);
+      }
       break;
 
     // -- Change detection
@@ -252,7 +261,7 @@ std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
   return res;
 }
 
-void cmQtAutoGeneratorRcc::SettingsFileRead()
+bool cmQtAutoGeneratorRcc::SettingsFileRead()
 {
   // Compose current settings strings
   {
@@ -278,21 +287,51 @@ void cmQtAutoGeneratorRcc::SettingsFileRead()
     }
   }
 
+  // Make sure the settings file exists
+  if (!FileSys().FileExists(SettingsFile_, true)) {
+    // Touch the settings file to make sure it exists
+    FileSys().Touch(SettingsFile_, true);
+  }
+
+  // Lock the lock file
+  {
+    // Make sure the lock file exists
+    if (!FileSys().FileExists(LockFile_, true)) {
+      if (!FileSys().Touch(LockFile_, true)) {
+        Log().ErrorFile(GeneratorT::RCC, LockFile_,
+                        "Lock file creation failed");
+        Error_ = true;
+        return false;
+      }
+    }
+    // Lock the lock file
+    cmFileLockResult lockResult =
+      LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
+    if (!lockResult.IsOk()) {
+      Log().ErrorFile(GeneratorT::RCC, LockFile_,
+                      "File lock failed: " + lockResult.GetOutputMessage());
+      Error_ = true;
+      return false;
+    }
+  }
+
   // Read old settings
   {
     std::string content;
     if (FileSys().FileRead(content, SettingsFile_)) {
       SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
-      // In case any setting changed remove the old settings file.
+      // In case any setting changed clear the old settings file.
       // This triggers a full rebuild on the next run if the current
       // build is aborted before writing the current settings in the end.
       if (SettingsChanged_) {
-        FileSys().FileRemove(SettingsFile_);
+        FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, "");
       }
     } else {
       SettingsChanged_ = true;
     }
   }
+
+  return true;
 }
 
 void cmQtAutoGeneratorRcc::SettingsFileWrite()
@@ -315,6 +354,9 @@ void cmQtAutoGeneratorRcc::SettingsFileWrite()
       Error_ = true;
     }
   }
+
+  // Unlock the lock file
+  LockFileLock_.Release();
 }
 
 bool cmQtAutoGeneratorRcc::TestQrcRccFiles()

+ 4 - 1
Source/cmQtAutoGeneratorRcc.h

@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmFileLock.h"
 #include "cmQtAutoGenerator.h"
 #include "cm_uv.h"
 
@@ -48,7 +49,7 @@ private:
   void PollStage();
   void SetStage(StageT stage);
   // -- Settings file
-  void SettingsFileRead();
+  bool SettingsFileRead();
   void SettingsFileWrite();
   // -- Tests
   bool TestQrcRccFiles();
@@ -77,6 +78,8 @@ private:
   std::string RccExecutable_;
   std::vector<std::string> RccListOptions_;
   // -- Job
+  std::string LockFile_;
+  cmFileLock LockFileLock_;
   std::string QrcFile_;
   std::string QrcFileName_;
   std::string QrcFileDir_;