From f972e4fd3acfb33888102ddc84b4e96db20998df Mon Sep 17 00:00:00 2001 From: Nicholas Sinlock Date: Thu, 1 Sep 2022 14:43:19 -0700 Subject: 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 --- Source/cmGlobalVisualStudio10Generator.cxx | 21 +++++++++++++ Source/cmGlobalVisualStudio10Generator.h | 3 +- Source/cmGlobalVisualStudioVersionedGenerator.cxx | 37 +++++++++++++++++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 29eeb5a..7886fc7 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -389,6 +389,27 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( 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 = {}; + } break; } } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 4977a84..a33c94e 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -200,7 +200,8 @@ protected: None, Default, PropsExist, - PropsMissing + PropsMissing, + PropsIndeterminate }; virtual AuxToolset FindAuxToolset(std::string& version, std::string& props) const; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 7e36881..c3ba2c2 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -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")) { -- cgit v0.12