summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-03-12 14:26:25 (GMT)
committerBrad King <brad.king@kitware.com>2021-03-12 14:26:25 (GMT)
commitc540b611b826a0aa1dc8411c3cbf2db3d59229ae (patch)
tree7ef8665102eaae79f7a8a67850f387caa27bf515
parentacdbf64047d1c7e84ec673c92407a0840d9b7230 (diff)
parent30c835428fffbf91191ebb1150d7fec00803523c (diff)
downloadCMake-c540b611b826a0aa1dc8411c3cbf2db3d59229ae.zip
CMake-c540b611b826a0aa1dc8411c3cbf2db3d59229ae.tar.gz
CMake-c540b611b826a0aa1dc8411c3cbf2db3d59229ae.tar.bz2
Merge branch 'vs-toolset-version' into release-3.19
Merge-request: !5903
-rw-r--r--Help/release/3.19.rst8
-rw-r--r--Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst20
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx73
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h22
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx127
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx12
7 files changed, 170 insertions, 96 deletions
diff --git a/Help/release/3.19.rst b/Help/release/3.19.rst
index 1d55f1e..49c6793 100644
--- a/Help/release/3.19.rst
+++ b/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.
diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst
index 64f2e39..c4369ee 100644
--- a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst
+++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION.rst
@@ -11,3 +11,23 @@ may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of
the form ``version=14.11``. If none is specified CMake will choose a default
toolset. The value may be empty if no minor version was selected and the
default is used.
+
+If the value is not empty, it is the version number that MSBuild uses in
+its ``Microsoft.VCToolsVersion.*.props`` file names.
+
+.. versionadded:: 3.19.7
+
+ 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.
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 7794df3..badce2e 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -3,6 +3,7 @@
#include "cmGlobalVisualStudio10Generator.h"
#include <algorithm>
+#include <utility>
#include <cm/memory>
@@ -302,16 +303,16 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
// If a specific minor version of the toolset was requested, verify that it
// is compatible to the major version and that is exists on disk.
// If not clear the value.
- std::string version = this->GeneratorToolsetVersion;
+ std::string versionToolset = this->GeneratorToolsetVersion;
cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9][0-9]");
- if (regex.find(version)) {
- version = "v" + version.erase(2, 1);
+ if (regex.find(versionToolset)) {
+ versionToolset = "v" + versionToolset.erase(2, 1);
} else {
// Version not recognized. Clear it.
- version.clear();
+ versionToolset.clear();
}
- if (!cmHasPrefix(version, this->GetPlatformToolsetString())) {
+ if (!cmHasPrefix(versionToolset, this->GetPlatformToolsetString())) {
std::ostringstream e;
/* clang-format off */
e <<
@@ -329,15 +330,20 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
this->GeneratorToolsetVersion.clear();
}
- bool const isDefaultToolset =
- this->IsDefaultToolset(this->GeneratorToolsetVersion);
- if (isDefaultToolset) {
- // If the given version is the default toolset, remove the setting
- this->GeneratorToolsetVersion.clear();
- } else {
- std::string const toolsetPath = this->GetAuxiliaryToolset();
- if (!toolsetPath.empty() && !cmSystemTools::FileExists(toolsetPath)) {
-
+ std::string auxProps;
+ switch (this->FindAuxToolset(this->GeneratorToolsetVersion, auxProps)) {
+ case AuxToolset::None:
+ this->GeneratorToolsetVersionProps = {};
+ break;
+ case AuxToolset::Default:
+ // The given version is the default toolset. Remove the setting.
+ this->GeneratorToolsetVersion.clear();
+ this->GeneratorToolsetVersionProps = {};
+ break;
+ case AuxToolset::PropsExist:
+ this->GeneratorToolsetVersionProps = std::move(auxProps);
+ break;
+ case AuxToolset::PropsMissing: {
std::ostringstream e;
/* clang-format off */
e <<
@@ -347,22 +353,24 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
" " << this->GetPlatformToolsetString() << ",version=" <<
this->GeneratorToolsetVersion << "\n"
"does not seem to be installed at\n" <<
- " " << toolsetPath;
+ " " << auxProps;
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
// Clear the configured tool-set
this->GeneratorToolsetVersion.clear();
- }
+ this->GeneratorToolsetVersionProps = {};
+ } break;
}
}
if (const char* toolset = this->GetPlatformToolset()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
}
- if (const char* version = this->GetPlatformToolsetVersion()) {
- mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION", version);
+ if (!this->GeneratorToolsetVersion.empty()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION",
+ this->GeneratorToolsetVersion);
}
if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
@@ -719,23 +727,10 @@ std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString()
return empty;
}
-const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetVersion() const
-{
- std::string const& version = this->GetPlatformToolsetVersionString();
- if (version.empty()) {
- return nullptr;
- }
- return version.c_str();
-}
-
std::string const&
-cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionString() const
+cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionProps() const
{
- if (!this->GeneratorToolsetVersion.empty()) {
- return this->GeneratorToolsetVersion;
- }
- static std::string const empty;
- return empty;
+ return this->GeneratorToolsetVersionProps;
}
const char*
@@ -792,15 +787,11 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
return this->GeneratorToolsetCudaCustomDir;
}
-bool cmGlobalVisualStudio10Generator::IsDefaultToolset(
- const std::string&) const
-{
- return true;
-}
-
-std::string cmGlobalVisualStudio10Generator::GetAuxiliaryToolset() const
+cmGlobalVisualStudio10Generator::AuxToolset
+cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&,
+ std::string&) const
{
- return {};
+ return AuxToolset::None;
}
bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 65ea33f..8d30ef8 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -61,9 +61,8 @@ public:
const char* GetPlatformToolset() const;
std::string const& GetPlatformToolsetString() const;
- /** The toolset version. */
- const char* GetPlatformToolsetVersion() const;
- std::string const& GetPlatformToolsetVersionString() const;
+ /** The toolset version props file, if any. */
+ std::string const& GetPlatformToolsetVersionProps() const;
/** The toolset host architecture name (e.g. x64 for 64-bit host tools). */
const char* GetPlatformToolsetHostArchitecture() const;
@@ -120,9 +119,6 @@ public:
std::string Encoding() override;
const char* GetToolsVersion() const;
- virtual bool IsDefaultToolset(const std::string& version) const;
- virtual std::string GetAuxiliaryToolset() const;
-
bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; }
bool FindMakeProgram(cmMakefile* mf) override;
@@ -168,6 +164,16 @@ protected:
virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ enum class AuxToolset
+ {
+ None,
+ Default,
+ PropsExist,
+ PropsMissing
+ };
+ virtual AuxToolset FindAuxToolset(std::string& version,
+ std::string& props) const;
+
std::string const& GetMSBuildCommand();
cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName,
@@ -176,7 +182,7 @@ protected:
std::string const& table) const;
std::string GeneratorToolset;
- std::string GeneratorToolsetVersion;
+ std::string GeneratorToolsetVersionProps;
std::string GeneratorToolsetHostArchitecture;
std::string GeneratorToolsetCustomVCTargetsDir;
std::string GeneratorToolsetCuda;
@@ -230,6 +236,8 @@ private:
std::string FindDevEnvCommand() override;
std::string GetVSMakeProgram() override { return this->GetMSBuildCommand(); }
+ std::string GeneratorToolsetVersion;
+
bool PlatformToolsetNeedsDebugEnum;
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 84f870e..fb518a2 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -2,6 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudioVersionedGenerator.h"
+#include <cmext/string_view>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio10Generator.h"
@@ -391,27 +396,6 @@ bool cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion(
return vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion);
}
-bool cmGlobalVisualStudioVersionedGenerator::IsDefaultToolset(
- const std::string& version) const
-{
- if (version.empty()) {
- return true;
- }
-
- std::string vcToolsetVersion;
- if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) {
-
- cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+");
- if (regex.find(version) && regex.find(vcToolsetVersion)) {
- const auto majorMinorEnd = vcToolsetVersion.find('.', 3);
- const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd);
- return version == majorMinor;
- }
- }
-
- return false;
-}
-
bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const
{
// Supported from Visual Studio 16.7 Preview 3.
@@ -446,29 +430,92 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
return "";
}
-std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const
+cmGlobalVisualStudioVersionedGenerator::AuxToolset
+cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
+ std::string& version, std::string& props) const
{
- const char* version = this->GetPlatformToolsetVersion();
- if (version) {
- std::string instancePath;
- GetVSInstance(instancePath);
- std::string toolsetDir = instancePath + "/VC/Auxiliary/Build";
- char sep = '/';
- if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {
- std::string toolsetDot =
- cmStrCat(toolsetDir, '.', version, "/Microsoft.VCToolsVersion.",
- version, ".props");
- if (cmSystemTools::PathExists(toolsetDot)) {
- sep = '.';
+ if (version.empty()) {
+ return AuxToolset::None;
+ }
+
+ std::string instancePath;
+ 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);
+ if (cmSystemTools::PathExists(props)) {
+ return AuxToolset::PropsExist;
+ }
+ }
+ props = cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, version,
+ "/Microsoft.VCToolsVersion."_s, version, ".props"_s);
+ if (cmSystemTools::PathExists(props)) {
+ return AuxToolset::PropsExist;
+ }
+
+ // Accept the toolset version that is default in the current VS version
+ // by matching the name later VS versions will use for the SxS props files.
+ std::string vcToolsetVersion;
+ if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) {
+ // Accept an exact-match (three-component version).
+ if (version == vcToolsetVersion) {
+ return AuxToolset::Default;
+ }
+
+ // Accept known SxS props file names using four version components
+ // in VS versions later than the current.
+ if (version == "14.28.16.9" && vcToolsetVersion == "14.28.29910") {
+ return AuxToolset::Default;
+ }
+
+ // The first two components of the default toolset version typically
+ // match the name used by later VS versions for the SxS props files.
+ cmsys::RegularExpression twoComponent("^([0-9]+\\.[0-9]+)");
+ if (twoComponent.find(version)) {
+ std::string const versionPrefix = cmStrCat(twoComponent.match(1), '.');
+ if (cmHasPrefix(vcToolsetVersion, versionPrefix)) {
+ return AuxToolset::Default;
}
}
- std::string toolsetPath =
- cmStrCat(toolsetDir, sep, version, "/Microsoft.VCToolsVersion.", version,
- ".props");
- cmSystemTools::ConvertToUnixSlashes(toolsetPath);
- return toolsetPath;
}
- return {};
+
+ return AuxToolset::PropsMissing;
}
bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf)
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
index 46a5f40..cee129e 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.h
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -30,8 +30,8 @@ public:
bool GetVSInstanceVersion(unsigned long long& vsInstanceVersion) const;
- bool IsDefaultToolset(const std::string& version) const override;
- std::string GetAuxiliaryToolset() const override;
+ AuxToolset FindAuxToolset(std::string& version,
+ std::string& props) const override;
bool IsStdOutEncodingSupported() const override;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 4eb3b7f..489e42d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -623,14 +623,14 @@ void cmVisualStudio10TargetGenerator::Generate()
}
switch (this->ProjectType) {
- case vcxproj:
- if (this->GlobalGenerator->GetPlatformToolsetVersion()) {
- Elem(e0, "Import")
- .Attribute("Project",
- this->GlobalGenerator->GetAuxiliaryToolset());
+ case vcxproj: {
+ std::string const& props =
+ this->GlobalGenerator->GetPlatformToolsetVersionProps();
+ if (!props.empty()) {
+ Elem(e0, "Import").Attribute("Project", props);
}
Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
- break;
+ } break;
case csproj:
Elem(e0, "Import")
.Attribute("Project", VS10_CSharp_DEFAULT_PROPS)