Browse Source

Merge topic 'autogen_compiler_features'

71d6a1455e Autogen: Evaluate compiler features for the same exectuable only once

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3359
Brad King 6 năm trước cách đây
mục cha
commit
d7e70d01fe

+ 10 - 0
Source/cmQtAutoGen.h

@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory> // IWYU pragma: keep
 #include <string>
 #include <vector>
 
@@ -40,6 +41,15 @@ public:
     }
   };
 
+  class CompilerFeatures
+  {
+  public:
+    bool Evaluated = false;
+    std::string HelpOutput;
+    std::vector<std::string> ListOptions;
+  };
+  typedef std::shared_ptr<CompilerFeatures> CompilerFeaturesHandle;
+
   /// @brief AutoGen generator type
   enum class GenT
   {

+ 17 - 20
Source/cmQtAutoGenGlobalInitializer.cxx

@@ -203,19 +203,16 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
   }
 }
 
-bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput(
+cmQtAutoGen::CompilerFeaturesHandle
+cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
   std::string const& generator, std::string const& executable,
-  std::string& error, std::string* output)
+  std::string& error)
 {
-  // Check if we have cached output
+  // Check if we have cached features
   {
-    auto it = this->ExecutableTestOutputs_.find(executable);
-    if (it != this->ExecutableTestOutputs_.end()) {
-      // Return output on demand
-      if (output != nullptr) {
-        *output = it->second;
-      }
-      return true;
+    auto it = this->CompilerFeatures_.find(executable);
+    if (it != this->CompilerFeatures_.end()) {
+      return it->second;
     }
   }
 
@@ -226,7 +223,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput(
     error += "\" executable ";
     error += cmQtAutoGen::Quoted(executable);
     error += " does not exist.";
-    return false;
+    return cmQtAutoGen::CompilerFeaturesHandle();
   }
 
   // Test the executable
@@ -234,7 +231,7 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput(
   {
     std::string stdErr;
     std::vector<std::string> command;
-    command.push_back(executable);
+    command.emplace_back(executable);
     command.emplace_back("-h");
     int retVal = 0;
     const bool runResult = cmSystemTools::RunSingleCommand(
@@ -250,19 +247,19 @@ bool cmQtAutoGenGlobalInitializer::GetExecutableTestOutput(
       error += stdOut;
       error += "\n";
       error += stdErr;
-      return false;
+      return cmQtAutoGen::CompilerFeaturesHandle();
     }
   }
 
-  // Return executable output on demand
-  if (output != nullptr) {
-    *output = stdOut;
-  }
+  // Create valid handle
+  cmQtAutoGen::CompilerFeaturesHandle res =
+    std::make_shared<cmQtAutoGen::CompilerFeatures>();
+  res->HelpOutput = std::move(stdOut);
 
-  // Register executable and output
-  this->ExecutableTestOutputs_.emplace(executable, std::move(stdOut));
+  // Register compiler features
+  this->CompilerFeatures_.emplace(executable, res);
 
-  return true;
+  return res;
 }
 
 bool cmQtAutoGenGlobalInitializer::generate()

+ 7 - 4
Source/cmQtAutoGenGlobalInitializer.h

@@ -5,6 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmQtAutoGen.h"
+
 #include <map>
 #include <memory> // IWYU pragma: keep
 #include <string>
@@ -68,15 +70,16 @@ private:
   void AddToGlobalAutoRcc(cmLocalGenerator* localGen,
                           std::string const& targetName);
 
-  bool GetExecutableTestOutput(std::string const& generator,
-                               std::string const& executable,
-                               std::string& error, std::string* output);
+  cmQtAutoGen::CompilerFeaturesHandle GetCompilerFeatures(
+    std::string const& generator, std::string const& executable,
+    std::string& error);
 
 private:
   std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_;
   std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
   std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
-  std::unordered_map<std::string, std::string> ExecutableTestOutputs_;
+  std::unordered_map<std::string, cmQtAutoGen::CompilerFeaturesHandle>
+    CompilerFeatures_;
   Keywords const Keywords_;
 };
 

+ 30 - 21
Source/cmQtAutoGenInitializer.cxx

@@ -511,7 +511,7 @@ bool cmQtAutoGenInitializer::InitMoc()
 
   // Moc executable
   {
-    if (!this->GetQtExecutable(this->Moc, "moc", false, nullptr)) {
+    if (!this->GetQtExecutable(this->Moc, "moc", false)) {
       return false;
     }
     // Let the _autogen target depend on the moc executable
@@ -565,7 +565,7 @@ bool cmQtAutoGenInitializer::InitUic()
 
   // Uic executable
   {
-    if (!this->GetQtExecutable(this->Uic, "uic", true, nullptr)) {
+    if (!this->GetQtExecutable(this->Uic, "uic", true)) {
       return false;
     }
     // Let the _autogen target depend on the uic executable
@@ -582,17 +582,22 @@ bool cmQtAutoGenInitializer::InitRcc()
 {
   // Rcc executable
   {
-    std::string stdOut;
-    if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) {
+    if (!this->GetQtExecutable(this->Rcc, "rcc", false)) {
       return false;
     }
-    // Evaluate test output
-    if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
-      if (stdOut.find("--list") != std::string::npos) {
-        this->Rcc.ListOptions.emplace_back("--list");
-      } else if (stdOut.find("-list") != std::string::npos) {
-        this->Rcc.ListOptions.emplace_back("-list");
+    // Evaluate test output on demand
+    CompilerFeatures& features = *this->Rcc.ExecutableFeatures;
+    if (!features.Evaluated) {
+      // Look for list options
+      if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
+        if (features.HelpOutput.find("--list") != std::string::npos) {
+          features.ListOptions.emplace_back("--list");
+        } else if (features.HelpOutput.find("-list") != std::string::npos) {
+          features.ListOptions.emplace_back("-list");
+        }
       }
+      // Evaluation finished
+      features.Evaluated = true;
     }
   }
 
@@ -931,7 +936,8 @@ bool cmQtAutoGenInitializer::InitScanFiles()
     for (Qrc& qrc : this->Rcc.Qrcs) {
       if (!qrc.Generated) {
         std::string error;
-        RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions);
+        RccLister const lister(this->Rcc.Executable,
+                               this->Rcc.ExecutableFeatures->ListOptions);
         if (!lister.list(qrc.QrcFile, qrc.Resources, error)) {
           cmSystemTools::Error(error);
           return false;
@@ -1437,7 +1443,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo()
 
       ofs.Write("# Rcc executable\n");
       ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
-      ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions);
+      ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS",
+                       this->Rcc.ExecutableFeatures->ListOptions);
 
       ofs.Write("# Rcc job\n");
       ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
@@ -1600,8 +1607,7 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
 
 bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
                                              const std::string& executable,
-                                             bool ignoreMissingTarget,
-                                             std::string* output) const
+                                             bool ignoreMissingTarget) const
 {
   auto print_err = [this, &genVars](std::string const& err) {
     std::string msg = genVars.GenNameUpper;
@@ -1631,9 +1637,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
         return false;
       }
 
-      // Check if the provided executable already exists (it's possible for it
-      // not to exist when building Qt itself).
-      genVars.ExecutableExists = cmSystemTools::FileExists(genVars.Executable);
+      // Create empty compiler features.
+      genVars.ExecutableFeatures =
+        std::make_shared<cmQtAutoGen::CompilerFeatures>();
       return true;
     }
   }
@@ -1664,6 +1670,9 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
       }
     } else {
       if (ignoreMissingTarget) {
+        // Create empty compiler features.
+        genVars.ExecutableFeatures =
+          std::make_shared<cmQtAutoGen::CompilerFeatures>();
         return true;
       }
       std::string err = "Could not find ";
@@ -1675,15 +1684,15 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
     }
   }
 
-  // Test executable
+  // Get executable features
   {
     std::string err;
-    if (!this->GlobalInitializer->GetExecutableTestOutput(
-          executable, genVars.Executable, err, output)) {
+    genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures(
+      executable, genVars.Executable, err);
+    if (!genVars.ExecutableFeatures) {
       print_err(err);
       return false;
     }
-    genVars.ExecutableExists = true;
   }
 
   return true;

+ 2 - 3
Source/cmQtAutoGenInitializer.h

@@ -67,7 +67,7 @@ public:
     std::string ExecutableTargetName;
     cmGeneratorTarget* ExecutableTarget = nullptr;
     std::string Executable;
-    bool ExecutableExists = false;
+    CompilerFeaturesHandle ExecutableFeatures;
 
     /// @brief Constructor
     GenVarsT(GenT gen)
@@ -148,7 +148,7 @@ private:
   void AddCleanFile(std::string const& fileName);
 
   bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
-                       bool ignoreMissingTarget, std::string* output) const;
+                       bool ignoreMissingTarget) const;
 
 private:
   cmQtAutoGenGlobalInitializer* GlobalInitializer;
@@ -230,7 +230,6 @@ private:
   struct RccT : public GenVarsT
   {
     bool GlobalTarget = false;
-    std::vector<std::string> ListOptions;
     std::vector<Qrc> Qrcs;
 
     /// @brief Constructor