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 components58a50a3a0a
VS: Fix '-T version=14.28' under VS 16.909f59da7f0
cmGlobalVisualStudioVersionedGenerator: Clarify local variable name Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !5903
This commit is contained in:
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user