Browse Source

Autogen: Add cmQtAutogeneratorCommon class with shared types and functions

Sebastian Holtermann 8 năm trước cách đây
mục cha
commit
47dbe9267e

+ 2 - 0
Source/CMakeLists.txt

@@ -344,6 +344,8 @@ set(SRCS
   cmPropertyDefinitionMap.h
   cmPropertyMap.cxx
   cmPropertyMap.h
+  cmQtAutoGeneratorCommon.cxx
+  cmQtAutoGeneratorCommon.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
   cmQtAutoGenerators.cxx

+ 166 - 0
Source/cmQtAutoGeneratorCommon.cxx

@@ -0,0 +1,166 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGeneratorCommon.h"
+#include "cmAlgorithms.h"
+#include "cmSystemTools.h"
+
+#include <cmsys/FStream.hxx>
+#include <cmsys/RegularExpression.hxx>
+
+#include <sstream>
+
+// - Static functions
+
+static std::string utilStripCR(std::string const& line)
+{
+  // Strip CR characters rcc may have printed (possibly more than one!).
+  std::string::size_type cr = line.find('\r');
+  if (cr != line.npos) {
+    return line.substr(0, cr);
+  }
+  return line;
+}
+
+/// @brief Reads the resource files list from from a .qrc file - Qt4 version
+/// @return True if the .qrc file was successfully parsed
+static bool RccListInputsQt4(const std::string& fileName,
+                             std::vector<std::string>& files)
+{
+  // Qrc file directory
+  std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
+  if (!qrcDir.empty()) {
+    qrcDir += '/';
+  }
+
+  // Read file into string
+  std::string qrcContents;
+  {
+    std::ostringstream stream;
+    stream << cmsys::ifstream(fileName).rdbuf();
+    qrcContents = stream.str();
+  }
+
+  cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
+  cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
+
+  size_t offset = 0;
+  while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
+    std::string qrcEntry = fileMatchRegex.match(1);
+    offset += qrcEntry.size();
+    {
+      fileReplaceRegex.find(qrcEntry);
+      std::string tag = fileReplaceRegex.match(1);
+      qrcEntry = qrcEntry.substr(tag.size());
+    }
+    if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
+      qrcEntry = qrcDir + qrcEntry;
+    }
+    files.push_back(qrcEntry);
+  }
+  return true;
+}
+
+/// @brief Reads the resource files list from from a .qrc file - Qt5 version
+/// @return True if the .qrc file was successfully parsed
+static bool RccListInputsQt5(const std::string& rccCommand,
+                             const std::string& fileName,
+                             std::vector<std::string>& files)
+{
+  if (rccCommand.empty()) {
+    cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
+    return false;
+  }
+
+  // Read rcc features
+  bool hasDashDashList = false;
+  {
+    std::vector<std::string> command;
+    command.push_back(rccCommand);
+    command.push_back("--help");
+    std::string rccStdOut;
+    std::string rccStdErr;
+    int retVal = 0;
+    bool result =
+      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
+                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
+    if (result && retVal == 0 &&
+        rccStdOut.find("--list") != std::string::npos) {
+      hasDashDashList = true;
+    }
+  }
+
+  // Run rcc list command
+  bool result = false;
+  int retVal = 0;
+  std::string rccStdOut;
+  std::string rccStdErr;
+  {
+    std::vector<std::string> command;
+    command.push_back(rccCommand);
+    command.push_back(hasDashDashList ? "--list" : "-list");
+    command.push_back(fileName);
+    result =
+      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
+                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
+  }
+  if (!result || retVal) {
+    std::ostringstream err;
+    err << "AUTOGEN: error: Rcc list process for " << fileName << " failed:\n"
+        << rccStdOut << "\n"
+        << rccStdErr << std::endl;
+    cmSystemTools::Error(err.str().c_str());
+    return false;
+  }
+
+  // Parse rcc std output
+  {
+    std::istringstream ostr(rccStdOut);
+    std::string oline;
+    while (std::getline(ostr, oline)) {
+      oline = utilStripCR(oline);
+      if (!oline.empty()) {
+        files.push_back(oline);
+      }
+    }
+  }
+  // Parse rcc error output
+  {
+    std::istringstream estr(rccStdErr);
+    std::string eline;
+    while (std::getline(estr, eline)) {
+      eline = utilStripCR(eline);
+      if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
+        static std::string searchString = "Cannot find file '";
+
+        std::string::size_type pos = eline.find(searchString);
+        if (pos == std::string::npos) {
+          std::ostringstream err;
+          err << "AUTOGEN: error: Rcc lists unparsable output " << eline
+              << std::endl;
+          cmSystemTools::Error(err.str().c_str());
+          return false;
+        }
+        pos += searchString.length();
+        std::string::size_type sz = eline.size() - pos - 1;
+        files.push_back(eline.substr(pos, sz));
+      }
+    }
+  }
+
+  return true;
+}
+
+// - Class definitions
+
+const char* cmQtAutoGeneratorCommon::listSep = "@list_sep@";
+
+bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
+                                            const std::string& rccCommand,
+                                            const std::string& fileName,
+                                            std::vector<std::string>& files)
+{
+  if (qtMajorVersion == "4") {
+    return RccListInputsQt4(fileName, files);
+  }
+  return RccListInputsQt5(rccCommand, fileName, files);
+}

+ 29 - 0
Source/cmQtAutoGeneratorCommon.h

@@ -0,0 +1,29 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGeneratorCommon_h
+#define cmQtAutoGeneratorCommon_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+
+class cmQtAutoGeneratorCommon
+{
+  // - Types and statics
+public:
+  static const char* listSep;
+
+public:
+  /// @brief Reads the resource files list from from a .qrc file
+  /// @arg fileName Must be the absolute path of the .qrc file
+  /// @return True if the rcc file was successfully parsed
+  static bool RccListInputs(const std::string& qtMajorVersion,
+                            const std::string& rccCommand,
+                            const std::string& fileName,
+                            std::vector<std::string>& files);
+};
+
+#endif

+ 24 - 162
Source/cmQtAutoGeneratorInitializer.cxx

@@ -1,6 +1,7 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGeneratorInitializer.h"
+#include "cmQtAutoGeneratorCommon.h"
 
 #include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
@@ -44,16 +45,6 @@ static void utilCopyTargetProperty(cmTarget* destinationTarget,
   }
 }
 
-static std::string utilStripCR(std::string const& line)
-{
-  // Strip CR characters rcc may have printed (possibly more than one!).
-  std::string::size_type cr = line.find('\r');
-  if (cr != line.npos) {
-    return line.substr(0, cr);
-  }
-  return line;
-}
-
 static std::string GetSafeProperty(cmGeneratorTarget const* target,
                                    const char* key)
 {
@@ -361,7 +352,8 @@ static void UicSetupAutoTarget(
           uiFileFiles.push_back(absFile);
           {
             std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
-            cmSystemTools::ReplaceString(opts, ";", "@list_sep@");
+            cmSystemTools::ReplaceString(opts, ";",
+                                         cmQtAutoGeneratorCommon::listSep);
             uiFileOptions.push_back(opts);
           }
         }
@@ -469,146 +461,12 @@ static void RccMergeOptions(std::vector<std::string>& opts,
   opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
 }
 
-/// @brief Reads the resource files list from from a .qrc file - Qt5 version
-/// @return True if the .qrc file was successfully parsed
-static bool RccListInputsQt5(cmSourceFile* sf, cmGeneratorTarget const* target,
-                             std::vector<std::string>& depends)
-{
-  const std::string rccCommand = RccGetExecutable(target, "5");
-  if (rccCommand.empty()) {
-    cmSystemTools::Error("AUTOGEN: error: rcc executable not available\n");
-    return false;
-  }
-
-  bool hasDashDashList = false;
-  // Read rcc features
-  {
-    std::vector<std::string> command;
-    command.push_back(rccCommand);
-    command.push_back("--help");
-    std::string rccStdOut;
-    std::string rccStdErr;
-    int retVal = 0;
-    bool result =
-      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
-                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
-    if (result && retVal == 0 &&
-        rccStdOut.find("--list") != std::string::npos) {
-      hasDashDashList = true;
-    }
-  }
-  // Run rcc list command
-  std::vector<std::string> command;
-  command.push_back(rccCommand);
-  command.push_back(hasDashDashList ? "--list" : "-list");
-
-  std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-  command.push_back(absFile);
-
-  std::string rccStdOut;
-  std::string rccStdErr;
-  int retVal = 0;
-  bool result =
-    cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
-                                    CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
-  if (!result || retVal) {
-    std::ostringstream err;
-    err << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath()
-        << " failed:\n"
-        << rccStdOut << "\n"
-        << rccStdErr << std::endl;
-    cmSystemTools::Error(err.str().c_str());
-    return false;
-  }
-
-  // Parse rcc list output
-  {
-    std::istringstream ostr(rccStdOut);
-    std::string oline;
-    while (std::getline(ostr, oline)) {
-      oline = utilStripCR(oline);
-      if (!oline.empty()) {
-        depends.push_back(oline);
-      }
-    }
-  }
-
-  {
-    std::istringstream estr(rccStdErr);
-    std::string eline;
-    while (std::getline(estr, eline)) {
-      eline = utilStripCR(eline);
-      if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
-        static std::string searchString = "Cannot find file '";
-
-        std::string::size_type pos = eline.find(searchString);
-        if (pos == std::string::npos) {
-          std::ostringstream err;
-          err << "AUTOGEN: error: Rcc lists unparsable output " << eline
-              << std::endl;
-          cmSystemTools::Error(err.str().c_str());
-          return false;
-        }
-        pos += searchString.length();
-        std::string::size_type sz = eline.size() - pos - 1;
-        depends.push_back(eline.substr(pos, sz));
-      }
-    }
-  }
-
-  return true;
-}
-
-/// @brief Reads the resource files list from from a .qrc file - Qt4 version
-/// @return True if the .qrc file was successfully parsed
-static bool RccListInputsQt4(cmSourceFile* sf,
-                             std::vector<std::string>& depends)
-{
-  // Read file into string
-  std::string qrcContents;
-  {
-    std::ostringstream stream;
-    stream << cmsys::ifstream(sf->GetFullPath().c_str()).rdbuf();
-    qrcContents = stream.str();
-  }
-
-  cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
-  cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
-
-  size_t offset = 0;
-  while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
-    std::string qrcEntry = fileMatchRegex.match(1);
-    offset += qrcEntry.size();
-    {
-      fileReplaceRegex.find(qrcEntry);
-      std::string tag = fileReplaceRegex.match(1);
-      qrcEntry = qrcEntry.substr(tag.size());
-    }
-    if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
-      qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
-    }
-    depends.push_back(qrcEntry);
-  }
-  return true;
-}
-
-/// @brief Reads the resource files list from from a .qrc file
-/// @return True if the rcc file was successfully parsed
-static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf,
-                          cmGeneratorTarget const* target,
-                          std::vector<std::string>& depends)
-{
-  if (qtMajorVersion == "5") {
-    return RccListInputsQt5(sf, target, depends);
-  }
-  return RccListInputsQt4(sf, depends);
-}
-
 static void RccSetupAutoTarget(cmGeneratorTarget const* target,
                                const std::string& qtMajorVersion)
 {
   cmMakefile* makefile = target->Target->GetMakefile();
   const bool qtMajorVersion5 = (qtMajorVersion == "5");
+  const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
   std::vector<std::string> _rcc_files;
   std::vector<std::string> _rcc_inputs;
   std::vector<std::string> rccFileFiles;
@@ -636,9 +494,10 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target,
         {
           std::string entriesList;
           if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-            std::vector<std::string> depends;
-            if (RccListInputs(qtMajorVersion, sf, target, depends)) {
-              entriesList = cmJoin(depends, "@list_sep@");
+            std::vector<std::string> files;
+            if (cmQtAutoGeneratorCommon::RccListInputs(
+                  qtMajorVersion, rccCommand, absFile, files)) {
+              entriesList = cmJoin(files, cmQtAutoGeneratorCommon::listSep);
             } else {
               return;
             }
@@ -657,19 +516,19 @@ static void RccSetupAutoTarget(cmGeneratorTarget const* target,
           // Only store non empty options lists
           if (!rccOptions.empty()) {
             rccFileFiles.push_back(absFile);
-            rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@"));
+            rccFileOptions.push_back(
+              cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
           }
         }
       }
     }
   }
 
+  AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand);
   AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files);
   AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs);
   AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
   AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
-  AddDefinitionEscaped(makefile, "_qt_rcc_executable",
-                       RccGetExecutable(target, qtMajorVersion));
 }
 
 void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
@@ -696,6 +555,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   const std::string workingDirectory =
     cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
   const std::string qtMajorVersion = GetQtMajorVersion(target);
+  const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
   std::vector<std::string> autogenOutputFiles;
 
   // Remove old settings on cleanup
@@ -825,20 +685,22 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
           target->AddSource(rccOutputFile);
           // Register rcc output file as generated
           autogenOutputFiles.push_back(rccOutputFile);
-        }
-        if (lg->GetGlobalGenerator()->GetName() == "Ninja"
+
+          if (lg->GetGlobalGenerator()->GetName() == "Ninja"
 #if defined(_WIN32) && !defined(__CYGWIN__)
-            || usePRE_BUILD
+              || usePRE_BUILD
 #endif
-            ) {
-          if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-            RccListInputs(qtMajorVersion, sf, target, depends);
+              ) {
+            if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
+              cmQtAutoGeneratorCommon::RccListInputs(
+                qtMajorVersion, rccCommand, absFile, depends);
 #if defined(_WIN32) && !defined(__CYGWIN__)
-            // Cannot use PRE_BUILD because the resource files themselves
-            // may not be sources within the target so VS may not know the
-            // target needs to re-build at all.
-            usePRE_BUILD = false;
+              // Cannot use PRE_BUILD because the resource files themselves
+              // may not be sources within the target so VS may not know the
+              // target needs to re-build at all.
+              usePRE_BUILD = false;
 #endif
+            }
           }
         }
       }

+ 8 - 4
Source/cmQtAutoGenerators.cxx

@@ -1,6 +1,7 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorCommon.h"
 
 #include <algorithm>
 #include <assert.h>
@@ -178,7 +179,7 @@ static std::string JoinOptionsMap(
   for (std::map<std::string, std::string>::const_iterator it = opts.begin();
        it != opts.end(); ++it) {
     if (it != opts.begin()) {
-      result += "@list_sep@";
+      result += cmQtAutoGeneratorCommon::listSep;
     }
     result += it->first;
     result += "===";
@@ -424,7 +425,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
                fileIt = uicFilesVec.begin(),
                optionIt = uicOptionsVec.begin();
              fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
-          cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
+          cmSystemTools::ReplaceString(*optionIt,
+                                       cmQtAutoGeneratorCommon::listSep, ";");
           this->UicOptions[*fileIt] = *optionIt;
         }
       } else {
@@ -453,7 +455,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
       for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(),
                                               optionIt = rccOptionsVec.begin();
            fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
-        cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
+        cmSystemTools::ReplaceString(*optionIt,
+                                     cmQtAutoGeneratorCommon::listSep, ";");
         this->RccOptions[*fileIt] = *optionIt;
       }
     }
@@ -475,7 +478,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
              fileIt = this->RccSources.begin(),
              inputIt = rccInputLists.begin();
            fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
-        cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";");
+        cmSystemTools::ReplaceString(*inputIt,
+                                     cmQtAutoGeneratorCommon::listSep, ";");
         std::vector<std::string> rccInputFiles;
         cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
         this->RccInputs[*fileIt] = rccInputFiles;