Pārlūkot izejas kodu

Autogen: Refactor Qt executable name computation

In AUTOGEN a common new  base class cmQtAutoGenInitializer::GenVarsT for
mo/uic/rcc generator variables allows to generalize variable computation
functions.
Sebastian Holtermann 6 gadi atpakaļ
vecāks
revīzija
d9893fb594
2 mainītis faili ar 166 papildinājumiem un 141 dzēšanām
  1. 124 124
      Source/cmQtAutoGenInitializer.cxx
  2. 42 17
      Source/cmQtAutoGenInitializer.h

+ 124 - 124
Source/cmQtAutoGenInitializer.cxx

@@ -36,25 +36,9 @@
 #include <set>
 #include <sstream>
 #include <string>
-#include <type_traits>
 #include <utility>
 #include <vector>
 
-std::string GetQtExecutableTargetName(
-  const cmQtAutoGen::IntegerVersion& qtVersion, std::string const& executable)
-{
-  if (qtVersion.Major == 6) {
-    return ("Qt6::" + executable);
-  }
-  if (qtVersion.Major == 5) {
-    return ("Qt5::" + executable);
-  }
-  if (qtVersion.Major == 4) {
-    return ("Qt4::" + executable);
-  }
-  return ("");
-}
-
 static std::size_t GetParallelCPUCount()
 {
   static std::size_t count = 0;
@@ -399,16 +383,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     }
 
     // Init uic specific settings
-    if (this->Uic.Enabled) {
-      if (InitUic()) {
-        auto* uicTarget = makefile->FindTargetToUse(
-          GetQtExecutableTargetName(this->QtVersion, "uic"));
-        if (uicTarget != nullptr) {
-          this->AutogenTarget.DependTargets.insert(uicTarget);
-        }
-      } else {
-        return false;
-      }
+    if (this->Uic.Enabled && !InitUic()) {
+      return false;
     }
 
     // Autogen target name
@@ -449,12 +425,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
       this->AutogenTarget.DependOrigin =
         this->Target->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");
 
-      auto* mocTarget = makefile->FindTargetToUse(
-        GetQtExecutableTargetName(this->QtVersion, "moc"));
-      if (mocTarget != nullptr) {
-        this->AutogenTarget.DependTargets.insert(mocTarget);
-      }
-
       std::string const deps =
         this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
       if (!deps.empty()) {
@@ -575,7 +545,18 @@ bool cmQtAutoGenInitializer::InitMoc()
   }
 
   // Moc executable
-  return GetMocExecutable();
+  {
+    if (!this->GetQtExecutable(this->Moc, "moc", false, nullptr)) {
+      return false;
+    }
+    // Let the _autogen target depend on the moc executable
+    if (this->Moc.ExecutableTarget != nullptr) {
+      this->AutogenTarget.DependTargets.insert(
+        this->Moc.ExecutableTarget->Target);
+    }
+  }
+
+  return true;
 }
 
 bool cmQtAutoGenInitializer::InitUic()
@@ -618,12 +599,39 @@ bool cmQtAutoGenInitializer::InitUic()
   }
 
   // Uic executable
-  return GetUicExecutable();
+  {
+    if (!this->GetQtExecutable(this->Uic, "uic", true, nullptr)) {
+      return false;
+    }
+    // Let the _autogen target depend on the uic executable
+    if (this->Uic.ExecutableTarget != nullptr) {
+      this->AutogenTarget.DependTargets.insert(
+        this->Uic.ExecutableTarget->Target);
+    }
+  }
+
+  return true;
 }
 
 bool cmQtAutoGenInitializer::InitRcc()
 {
-  return GetRccExecutable();
+  // Rcc executable
+  {
+    std::string stdOut;
+    if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) {
+      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 {
+        this->Rcc.ListOptions.emplace_back("-list");
+      }
+    }
+  }
+
+  return true;
 }
 
 bool cmQtAutoGenInitializer::InitScanFiles()
@@ -1109,7 +1117,6 @@ bool cmQtAutoGenInitializer::InitRccTargets()
 {
   cmMakefile* makefile = this->Target->Target->GetMakefile();
   cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
-  auto rccTargetName = GetQtExecutableTargetName(this->QtVersion, "rcc");
 
   for (Qrc const& qrc : this->Rcc.Qrcs) {
     // Register info file as generated by CMake
@@ -1174,8 +1181,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
         if (!this->TargetsFolder.empty()) {
           autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
         }
-        if (!rccTargetName.empty()) {
-          autoRccTarget->AddUtility(rccTargetName, makefile);
+        if (!this->Rcc.ExecutableTargetName.empty()) {
+          autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, makefile);
         }
       }
       // Add autogen target to the origin target dependencies
@@ -1195,8 +1202,8 @@ bool cmQtAutoGenInitializer::InitRccTargets()
           // Add resource file to the custom command dependencies
           ccDepends.push_back(fileName);
         }
-        if (!rccTargetName.empty()) {
-          ccDepends.push_back(rccTargetName);
+        if (!this->Rcc.ExecutableTargetName.empty()) {
+          ccDepends.push_back(this->Rcc.ExecutableTargetName);
         }
         makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
                                            /*main_dependency*/ std::string(),
@@ -1383,8 +1390,12 @@ static unsigned int CharPtrToUInt(const char* const input)
 static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
   cmGeneratorTarget const* target)
 {
-  cmMakefile* makefile = target->Target->GetMakefile();
+  // Qt version variable prefixes
+  static std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core",
+                                                      "QT" } };
+
   std::vector<cmQtAutoGen::IntegerVersion> result;
+  result.reserve(prefixes.size() * 2);
   // Adds a version to the result (nullptr safe)
   auto addVersion = [&result](const char* major, const char* minor) {
     cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
@@ -1393,8 +1404,7 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
       result.emplace_back(ver);
     }
   };
-  // Qt version variable prefixes
-  std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core", "QT" } };
+  cmMakefile* makefile = target->Target->GetMakefile();
 
   // Read versions from variables
   for (const std::string& prefix : prefixes) {
@@ -1438,99 +1448,89 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
   return res;
 }
 
-std::pair<bool, std::string> cmQtAutoGenInitializer::GetQtExecutable(
-  const std::string& executable, bool ignoreMissingTarget, std::string* output)
+bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
+                                             const std::string& executable,
+                                             bool ignoreMissingTarget,
+                                             std::string* output) const
 {
-  const std::string upperExecutable = cmSystemTools::UpperCase(executable);
-  std::string result = this->Target->Target->GetSafeProperty(
-    "AUTO" + upperExecutable + "_EXECUTABLE");
-  if (!result.empty()) {
-    cmListFileBacktrace lfbt =
-      this->Target->Target->GetMakefile()->GetBacktrace();
-    cmGeneratorExpression ge(lfbt);
-    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(result);
-    result = cge->Evaluate(this->Target->GetLocalGenerator(), "");
-
-    return std::make_pair(true, result);
-  }
+  auto print_err = [this, &genVars](std::string const& err) {
+    std::string msg = genVars.GenNameUpper;
+    msg += " for target ";
+    msg += this->Target->GetName();
+    msg += ": ";
+    msg += err;
+    cmSystemTools::Error(msg);
+  };
 
-  std::string err;
+  // Custom executable
+  {
+    std::string const prop = genVars.GenNameUpper + "_EXECUTABLE";
+    std::string const val = this->Target->Target->GetSafeProperty(prop);
+    if (!val.empty()) {
+      // Evaluate generator expression
+      {
+        cmListFileBacktrace lfbt =
+          this->Target->Target->GetMakefile()->GetBacktrace();
+        cmGeneratorExpression ge(lfbt);
+        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);
+        genVars.Executable =
+          cge->Evaluate(this->Target->GetLocalGenerator(), "");
+      }
+      if (genVars.Executable.empty() && !ignoreMissingTarget) {
+        print_err(prop + " evaluates to an empty value");
+        return false;
+      }
+      return true;
+    }
+  }
 
-  // Find executable
+  // Find executable target
   {
-    const std::string targetName =
-      GetQtExecutableTargetName(this->QtVersion, executable);
-    if (targetName.empty()) {
-      err = "The AUTO" + upperExecutable + " feature ";
-      err += "supports only Qt 4, Qt 5 and Qt 6.";
-    } else {
-      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
-      if (tgt != nullptr) {
-        if (tgt->IsImported()) {
-          result = tgt->ImportedGetLocation("");
-        } else {
-          result = tgt->GetLocation("");
-        }
+    // Find executable target name
+    std::string targetName;
+    if (this->QtVersion.Major == 4) {
+      targetName = "Qt4::";
+    } else if (this->QtVersion.Major == 5) {
+      targetName = "Qt5::";
+    } else if (this->QtVersion.Major == 6) {
+      targetName = "Qt6::";
+    }
+    targetName += executable;
+
+    // Find target
+    cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+    cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(targetName);
+    if (target != nullptr) {
+      genVars.ExecutableTargetName = targetName;
+      genVars.ExecutableTarget = target;
+      if (target->IsImported()) {
+        genVars.Executable = target->ImportedGetLocation("");
       } else {
-        if (ignoreMissingTarget) {
-          return std::make_pair(true, "");
-        }
-
-        err = "Could not find target " + targetName;
+        genVars.Executable = target->GetLocation("");
       }
+    } else {
+      if (ignoreMissingTarget) {
+        return true;
+      }
+      std::string err = "Could not find ";
+      err += executable;
+      err += " executable target ";
+      err += targetName;
+      print_err(err);
+      return false;
     }
   }
 
   // Test executable
-  if (err.empty()) {
-    this->GlobalInitializer->GetExecutableTestOutput(executable, result, err,
-                                                     output);
-  }
-
-  // Print error
-  if (!err.empty()) {
-    std::string msg = "AutoGen (";
-    msg += this->Target->GetName();
-    msg += "): ";
-    msg += err;
-    cmSystemTools::Error(msg);
-    return std::make_pair(false, "");
-  }
-
-  return std::make_pair(true, result);
-}
-
-bool cmQtAutoGenInitializer::GetMocExecutable()
-{
-  const auto result = this->GetQtExecutable("moc", false, nullptr);
-  this->Moc.Executable = result.second;
-  return result.first;
-}
-
-bool cmQtAutoGenInitializer::GetUicExecutable()
-{
-  const auto result = this->GetQtExecutable("uic", true, nullptr);
-  this->Uic.Executable = result.second;
-  return result.first;
-}
-
-bool cmQtAutoGenInitializer::GetRccExecutable()
-{
-  std::string stdOut;
-  const auto result = this->GetQtExecutable("rcc", false, &stdOut);
-  this->Rcc.Executable = result.second;
-  if (!result.first) {
-    return false;
-  }
-
-  if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
-    if (stdOut.find("--list") != std::string::npos) {
-      this->Rcc.ListOptions.emplace_back("--list");
-    } else {
-      this->Rcc.ListOptions.emplace_back("-list");
+  {
+    std::string err;
+    if (!this->GlobalInitializer->GetExecutableTestOutput(
+          executable, genVars.Executable, err, output)) {
+      print_err(err);
+      return false;
     }
   }
+
   return true;
 }
 

+ 42 - 17
Source/cmQtAutoGenInitializer.h

@@ -40,6 +40,27 @@ public:
     std::vector<std::string> Resources;
   };
 
+  /// @brief Abstract moc/uic/rcc generator variables base class
+  struct GenVarsT
+  {
+    bool Enabled = false;
+    // Generator type/name
+    GenT Gen;
+    std::string const& GenName;
+    std::string const& GenNameUpper;
+    // Executable
+    std::string ExecutableTargetName;
+    cmGeneratorTarget* ExecutableTarget = nullptr;
+    std::string Executable;
+
+    /// @brief Constructor
+    GenVarsT(GenT gen, std::string const& genName,
+             std::string const& genNameUpper)
+      : Gen(gen)
+      , GenName(genName)
+      , GenNameUpper(genNameUpper){};
+  };
+
   /// @brief Writes a CMake info file
   class InfoWriter
   {
@@ -102,18 +123,13 @@ private:
   void AddGeneratedSource(std::string const& filename, GenT genType,
                           bool prepend = false);
 
-  bool GetMocExecutable();
-  bool GetUicExecutable();
-  bool GetRccExecutable();
+  bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
+                       bool ignoreMissingTarget, std::string* output) const;
 
   bool RccListInputs(std::string const& fileName,
                      std::vector<std::string>& files,
                      std::string& errorMessage);
 
-  std::pair<bool, std::string> GetQtExecutable(const std::string& executable,
-                                               bool ignoreMissingTarget,
-                                               std::string* output);
-
 private:
   cmQtAutoGenGlobalInitializer* GlobalInitializer;
   cmGeneratorTarget* Target;
@@ -159,10 +175,8 @@ private:
   } AutogenTarget;
 
   /// @brief Moc only variables
-  struct
+  struct MocT : public GenVarsT
   {
-    bool Enabled = false;
-    std::string Executable;
     std::string PredefsCmd;
     std::set<std::string> Skip;
     std::vector<std::string> Includes;
@@ -170,29 +184,40 @@ private:
     std::set<std::string> Defines;
     std::map<std::string, std::set<std::string>> ConfigDefines;
     std::string MocsCompilation;
+
+    /// @brief Constructor
+    MocT()
+      : GenVarsT(cmQtAutoGen::GenT::MOC, cmQtAutoGen::GenNameMoc,
+                 cmQtAutoGen::GenNameMocUpper){};
   } Moc;
 
-  ///@brief Uic only variables
-  struct
+  /// @brief Uic only variables
+  struct UicT : public GenVarsT
   {
-    bool Enabled = false;
-    std::string Executable;
     std::set<std::string> Skip;
     std::vector<std::string> SearchPaths;
     std::vector<std::string> Options;
     std::map<std::string, std::vector<std::string>> ConfigOptions;
     std::vector<std::string> FileFiles;
     std::vector<std::vector<std::string>> FileOptions;
+
+    /// @brief Constructor
+    UicT()
+      : GenVarsT(cmQtAutoGen::GenT::UIC, cmQtAutoGen::GenNameUic,
+                 cmQtAutoGen::GenNameUicUpper){};
   } Uic;
 
   /// @brief Rcc only variables
-  struct
+  struct RccT : public GenVarsT
   {
-    bool Enabled = false;
     bool GlobalTarget = false;
-    std::string Executable;
     std::vector<std::string> ListOptions;
     std::vector<Qrc> Qrcs;
+
+    /// @brief Constructor
+    RccT()
+      : GenVarsT(cmQtAutoGen::GenT::RCC, cmQtAutoGen::GenNameRcc,
+                 cmQtAutoGen::GenNameRccUpper){};
   } Rcc;
 };