Przeglądaj źródła

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 lat temu
rodzic
commit
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.
   This was mistakenly allowed by the implementation in CMake 3.19.0 through
   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.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 "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
 #include "cmLocalVisualStudio10Generator.h"
@@ -439,6 +442,40 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
   this->GetVSInstance(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")) {
     props = cmStrCat(instancePath, "/VC/Auxiliary/Build."_s, version,
                      "/Microsoft.VCToolsVersion."_s, version, ".props"_s);