浏览代码

Merge topic 'ifw-depends-name-version-parsing'

a43783a08d CPackIFW: Fix parsing of name and version in component DEPENDS
f536e6f3fb CPackIFW: Remove redundant variable assignment

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5929
Brad King 4 年之前
父节点
当前提交
d9b8acd238
共有 3 个文件被更改,包括 95 次插入33 次删除
  1. 7 0
      Help/release/dev/ifw-default-version-operator.rst
  2. 10 0
      Modules/CPackIFW.cmake
  3. 78 33
      Source/CPack/IFW/cmCPackIFWPackage.cxx

+ 7 - 0
Help/release/dev/ifw-default-version-operator.rst

@@ -0,0 +1,7 @@
+ifw-default-version-operator
+----------------------------
+
+* Names given as ``DEPENDS`` or ``DEPENDENCIES`` arguments to
+  :command:`cpack_ifw_configure_component` or
+  :command:`cpack_ifw_configure_component_group` may now contain hyphens.
+  This requires QtIFW 3.1 or later.

+ 10 - 0
Modules/CPackIFW.cmake

@@ -125,6 +125,11 @@ The module defines the following commands:
     list of dependency component or component group identifiers in
     QtIFW style.
 
+    .. versionadded:: 3.21
+
+    Component or group names listed as dependencies may contain hyphens.
+    This requires QtIFW 3.1 or later.
+
   ``AUTO_DEPEND_ON``
     .. versionadded:: 3.8
 
@@ -260,6 +265,11 @@ The module defines the following commands:
     list of dependency component or component group identifiers in
     QtIFW style.
 
+    .. versionadded:: 3.21
+
+    Component or group names listed as dependencies may contain hyphens.
+    This requires QtIFW 3.1 or later.
+
   ``AUTO_DEPEND_ON``
     .. versionadded:: 3.8
 

+ 78 - 33
Source/CPack/IFW/cmCPackIFWPackage.cxx

@@ -7,6 +7,8 @@
 #include <sstream>
 #include <utility>
 
+#include <cm/string_view>
+
 #include "cmCPackComponentGroup.h"
 #include "cmCPackIFWCommon.h"
 #include "cmCPackIFWGenerator.h"
@@ -30,44 +32,67 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default;
 cmCPackIFWPackage::DependenceStruct::DependenceStruct(
   const std::string& dependence)
 {
-  // Search compare section
-  size_t pos = std::string::npos;
-  if ((pos = dependence.find("<=")) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
-    this->Compare.Value = dependence.substr(pos + 2);
-  } else if ((pos = dependence.find(">=")) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
-    this->Compare.Value = dependence.substr(pos + 2);
-  } else if ((pos = dependence.find('<')) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareLess;
-    this->Compare.Value = dependence.substr(pos + 1);
-  } else if ((pos = dependence.find('=')) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareEqual;
-    this->Compare.Value = dependence.substr(pos + 1);
-  } else if ((pos = dependence.find('>')) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareGreater;
-    this->Compare.Value = dependence.substr(pos + 1);
-  } else if ((pos = dependence.find('-')) != std::string::npos) {
-    this->Compare.Type = cmCPackIFWPackage::CompareNone;
-    this->Compare.Value = dependence.substr(pos + 1);
-  }
-  size_t dashPos = dependence.find('-');
-  if (dashPos != std::string::npos) {
-    pos = dashPos;
-  }
-  this->Name = dependence.substr(0, pos);
+  // Preferred format is name and version are separated by a colon (:), but
+  // note that this is only supported with QtIFW 3.1 or later. Backward
+  // compatibility allows a hyphen (-) as a separator instead, but names then
+  // cannot contain a hyphen.
+  size_t pos;
+  if ((pos = dependence.find(':')) == std::string::npos) {
+    pos = dependence.find('-');
+  }
+
+  if (pos != std::string::npos) {
+    this->Name = dependence.substr(0, pos);
+    ++pos;
+    if (pos == dependence.size()) {
+      // Nothing after the separator. Treat this as no version constraint.
+      return;
+    }
+
+    const auto versionPart =
+      cm::string_view(dependence.data() + pos, dependence.size() - pos);
+
+    if (cmHasLiteralPrefix(versionPart, "<=")) {
+      this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
+      this->Compare.Value = std::string(versionPart.substr(2));
+    } else if (cmHasLiteralPrefix(versionPart, ">=")) {
+      this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
+      this->Compare.Value = std::string(versionPart.substr(2));
+    } else if (cmHasPrefix(versionPart, '<')) {
+      this->Compare.Type = cmCPackIFWPackage::CompareLess;
+      this->Compare.Value = std::string(versionPart.substr(1));
+    } else if (cmHasPrefix(versionPart, '=')) {
+      this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+      this->Compare.Value = std::string(versionPart.substr(1));
+    } else if (cmHasPrefix(versionPart, '>')) {
+      this->Compare.Type = cmCPackIFWPackage::CompareGreater;
+      this->Compare.Value = std::string(versionPart.substr(1));
+    } else {
+      // We found no operator but a version specification is still expected to
+      // follow. The default behavior is to treat this the same as =. We
+      // explicitly record that as our type (it simplifies our logic a little
+      // and is also clearer).
+      this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+      this->Compare.Value = std::string(versionPart);
+    }
+  } else {
+    this->Name = dependence;
+  }
 }
 
 std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
 {
-  if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
-    return this->Name;
-  }
-
   std::string result = this->Name;
-
-  if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
-      !this->Compare.Value.empty()) {
+  if (this->Name.find('-') != std::string::npos) {
+    // When a name contains a hyphen, we must use a colon after the name to
+    // prevent the hyphen from being parsed by QtIFW as the separator between
+    // the name and the version. Note that a colon is only supported with
+    // QtIFW 3.1 or later.
+    result += ":";
+  } else if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
+             !this->Compare.Value.empty()) {
+    // No hyphen in the name and we know a version part will follow. Use a
+    // hyphen as a separator since this works for all QtIFW versions.
     result += "-";
   }
 
@@ -609,6 +634,9 @@ void cmCPackIFWPackage::GeneratePackageFile()
   }
 
   // Dependencies
+  const bool hyphensInNamesUnsupported = this->Generator &&
+    !this->Generator->FrameworkVersion.empty() && this->IsVersionLess("3.1");
+  bool warnUnsupportedNames = false;
   std::set<DependenceStruct> compDepSet;
   for (DependenceStruct* ad : this->AlienDependencies) {
     compDepSet.insert(*ad);
@@ -620,9 +648,13 @@ void cmCPackIFWPackage::GeneratePackageFile()
   if (!compDepSet.empty()) {
     std::ostringstream dependencies;
     auto it = compDepSet.begin();
+    warnUnsupportedNames |=
+      hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
     dependencies << it->NameWithCompare();
     ++it;
     while (it != compDepSet.end()) {
+      warnUnsupportedNames |=
+        hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
       dependencies << "," << it->NameWithCompare();
       ++it;
     }
@@ -638,15 +670,28 @@ void cmCPackIFWPackage::GeneratePackageFile()
   if (!compAutoDepSet.empty()) {
     std::ostringstream dependencies;
     auto it = compAutoDepSet.begin();
+    warnUnsupportedNames |=
+      hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
     dependencies << it->NameWithCompare();
     ++it;
     while (it != compAutoDepSet.end()) {
+      warnUnsupportedNames |=
+        hyphensInNamesUnsupported && it->Name.find('-') != std::string::npos;
       dependencies << "," << it->NameWithCompare();
       ++it;
     }
     xout.Element("AutoDependOn", dependencies.str());
   }
 
+  if (warnUnsupportedNames) {
+    cmCPackIFWLogger(
+      WARNING,
+      "The dependencies for component \""
+        << this->Name << "\" specify names that contain hyphens. "
+        << "This requires QtIFW 3.1 or later, but you are using version "
+        << this->Generator->FrameworkVersion << std::endl);
+  }
+
   // Licenses (copy to meta dir)
   std::vector<std::string> licenses = this->Licenses;
   for (size_t i = 1; i < licenses.size(); i += 2) {