cmVSGenerator: Add support for two-part toolset versions for Visual Studio

Enables the Global Visual Studio Versioned Generator to use two-part toolset versions,
if only one toolset has that version number. For example, (14.32 is specified when
14.32.32142 and 14.32.23242 are installed). This change also add a unique return code
and message if a two-part version is used when multiple matching versions are present.

Fixes: #23933
This commit is contained in:
Nicholas Sinlock 2022-09-01 14:43:19 -07:00
parent 01e95efc34
commit f972e4fd3a
3 changed files with 57 additions and 4 deletions

View File

@ -385,6 +385,27 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
// Clear the configured tool-set
this->GeneratorToolsetVersion.clear();
this->GeneratorToolsetVersionProps = {};
} break;
case AuxToolset::PropsIndeterminate: {
std::ostringstream e;
/* clang-format off */
e <<
"Generator\n"
" " << this->GetName() << "\n"
"given toolset and version specification\n"
" " << this->GetPlatformToolsetString() << ",version=" <<
this->GeneratorToolsetVersion << "\n"
"has multiple matches installed at\n" <<
" " << auxProps << "\n" <<
"The toolset and version specification must resolve \n" <<
"to a single installed toolset";
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
// Clear the configured tool-set
this->GeneratorToolsetVersion.clear();
this->GeneratorToolsetVersionProps = {};

View File

@ -200,7 +200,8 @@ protected:
None,
Default,
PropsExist,
PropsMissing
PropsMissing,
PropsIndeterminate
};
virtual AuxToolset FindAuxToolset(std::string& version,
std::string& props) const;

View File

@ -770,12 +770,15 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
cmSystemTools::ConvertToUnixSlashes(instancePath);
// Translate three-component format accepted by "vcvarsall -vcvars_ver=".
cmsys::RegularExpression threeComponent(
cmsys::RegularExpression threeComponentRegex(
"^([0-9]+\\.[0-9]+)\\.[0-9][0-9][0-9][0-9][0-9]$");
if (threeComponent.find(version)) {
// The two-component format represents the two major components of the
// three-component format
cmsys::RegularExpression twoComponentRegex("^([0-9]+\\.[0-9]+)$");
if (threeComponentRegex.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 const& twoComponent = threeComponentRegex.match(1);
std::string pattern =
cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent,
"*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s);
@ -801,6 +804,34 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
}
}
}
} else if (twoComponentRegex.find(version)) {
std::string const& twoComponent = twoComponentRegex.match(1);
std::string pattern =
cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent,
"*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s);
cmsys::Glob glob;
glob.SetRecurseThroughSymlinks(false);
// Since we are only using the first two components of the toolset version,
// we require a definite match
if (glob.FindFiles(pattern) && glob.GetFiles().size() == 1) {
std::string const& txt = glob.GetFiles()[0];
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."));
// We assume the version is correct, since it is the only one that
// matched.
cmsys::RegularExpression extractVersion(
"VCToolsVersion\\.([0-9.]+)\\.txt$");
if (extractVersion.find(txt)) {
version = extractVersion.match(1);
}
}
} else {
props = cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s);
return AuxToolset::PropsIndeterminate;
}
}
if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {