浏览代码

VS: Accept and translate '-T version=' values with three components

The VS 16.8 and VS 16.9 toolset versions differ only in their third
component.  The `vcvarsall` option `-vcvars_ver=` accepts a three
component version, so accept this format for VS toolset selection too.

Issue: #21922
Brad King 4 年之前
父节点
当前提交
30c835428f

+ 8 - 0
Help/release/3.19.rst

@@ -432,3 +432,11 @@ Changes made since CMake 3.19.0 include the following.
   ``CMakePresets.json`` or ``CMakeUserPresets.json`` files.
   ``CMakePresets.json`` or ``CMakeUserPresets.json`` files.
   This was mistakenly allowed by the implementation in CMake 3.19.0 through
   This was mistakenly allowed by the implementation in CMake 3.19.0 through
   CMake 3.19.5, and was not documented.
   CMake 3.19.5, and was not documented.
+
+3.19.7
+------
+
+* With :ref:`Visual Studio Generators` for VS 2017 and higher, the
+  :variable:`CMAKE_GENERATOR_TOOLSET` field ``version=`` now accepts
+  three-component MSVC toolset versions such as ``14.28.29910``.
+  See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable.

+ 12 - 0
Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst

@@ -19,3 +19,15 @@ its ``Microsoft.VCToolsVersion.*.props`` file names.
 
 
    VS 16.9's toolset may also be specified as ``14.28.16.9`` because
    VS 16.9's toolset may also be specified as ``14.28.16.9`` because
    VS 16.10 uses the file name ``Microsoft.VCToolsVersion.14.28.16.9.props``.
    VS 16.10 uses the file name ``Microsoft.VCToolsVersion.14.28.16.9.props``.
+
+Three-Component MSVC Toolset Versions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.19.7
+
+The ``version=`` field may be given a three-component toolset version
+such as ``14.28.29910``, and CMake will convert it to the name used by
+MSBuild ``Microsoft.VCToolsVersion.*.props`` files.  This is useful
+to distinguish between VS 16.8's ``14.28.29333`` toolset and VS 16.9's
+``14.28.29910`` toolset.  It also matches ``vcvarsall``'s ``-vcvars_ver=``
+behavior.

+ 37 - 0
Source/cmGlobalVisualStudioVersionedGenerator.cxx

@@ -4,6 +4,9 @@
 
 
 #include <cmext/string_view>
 #include <cmext/string_view>
 
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
 #include "cmDocumentationEntry.h"
 #include "cmLocalVisualStudio10Generator.h"
 #include "cmLocalVisualStudio10Generator.h"
@@ -439,6 +442,40 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
   this->GetVSInstance(instancePath);
   this->GetVSInstance(instancePath);
   cmSystemTools::ConvertToUnixSlashes(instancePath);
   cmSystemTools::ConvertToUnixSlashes(instancePath);
 
 
+  // Translate three-component format accepted by "vcvarsall -vcvars_ver=".
+  cmsys::RegularExpression threeComponent(
+    "^([0-9]+\\.[0-9]+)\\.[0-9][0-9][0-9][0-9][0-9]$");
+  if (threeComponent.find(version)) {
+    // Load "VC/Auxiliary/Build/*/Microsoft.VCToolsVersion.*.txt" files
+    // with two matching components to check their three-component version.
+    std::string const& twoComponent = threeComponent.match(1);
+    std::string pattern =
+      cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent,
+               "*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s);
+    cmsys::Glob glob;
+    glob.SetRecurseThroughSymlinks(false);
+    if (glob.FindFiles(pattern)) {
+      for (std::string const& txt : glob.GetFiles()) {
+        std::string ver;
+        cmsys::ifstream fin(txt.c_str());
+        if (fin && std::getline(fin, ver)) {
+          // Strip trailing whitespace.
+          ver = ver.substr(0, ver.find_first_not_of("0123456789."));
+          // If the three-component version matches, translate it to
+          // that used by the "Microsoft.VCToolsVersion.*.txt" file name.
+          if (ver == version) {
+            cmsys::RegularExpression extractVersion(
+              "VCToolsVersion\\.([0-9.]+)\\.txt$");
+            if (extractVersion.find(txt)) {
+              version = extractVersion.match(1);
+              break;
+            }
+          }
+        }
+      }
+    }
+  }
+
   if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {
   if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {
     props = cmStrCat(instancePath, "/VC/Auxiliary/Build."_s, version,
     props = cmStrCat(instancePath, "/VC/Auxiliary/Build."_s, version,
                      "/Microsoft.VCToolsVersion."_s, version, ".props"_s);
                      "/Microsoft.VCToolsVersion."_s, version, ".props"_s);