1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

Merge topic 'vs-toolset-version' into release-3.20

30c835428f VS: Accept and translate '-T version=' values with three components
58a50a3a0a VS: Fix '-T version=14.28' under VS 16.9
09f59da7f0 cmGlobalVisualStudioVersionedGenerator: Clarify local variable name

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5903
This commit is contained in:
Brad King
2021-03-15 12:49:43 +00:00
committed by Kitware Robot
7 changed files with 170 additions and 96 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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
cmGlobalVisualStudio10Generator::AuxToolset
cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&,
std::string&) const
{
return true;
}
std::string cmGlobalVisualStudio10Generator::GetAuxiliaryToolset() const
{
return {};
return AuxToolset::None;
}
bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)

View File

@@ -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);

View File

@@ -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"
@@ -392,27 +397,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.
@@ -447,29 +431,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;
}
}
}
}
}
std::string toolsetPath =
cmStrCat(toolsetDir, sep, version, "/Microsoft.VCToolsVersion.", version,
".props");
cmSystemTools::ConvertToUnixSlashes(toolsetPath);
return toolsetPath;
}
return {};
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;
}
}
}
return AuxToolset::PropsMissing;
}
bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf)

View File

@@ -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;

View File

@@ -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)