/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmGlobalVisualStudioVersionedGenerator.h"

#include <cstring>
#include <set>
#include <sstream>
#include <utility>
#include <vector>

#include <cmext/string_view>

#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVSSetupHelper.h"
#include "cmake.h"

#ifndef IMAGE_FILE_MACHINE_ARM64
#  define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
#endif

static bool VSIsWow64()
{
  BOOL isWow64 = false;
  return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
}

static bool VSIsArm64Host()
{
  typedef BOOL(WINAPI * CM_ISWOW64PROCESS2)(
    HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine);

#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#  define CM_VS_GCC_DIAGNOSTIC_PUSHED
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
  static const CM_ISWOW64PROCESS2 s_IsWow64Process2Impl =
    (CM_ISWOW64PROCESS2)GetProcAddress(
      GetModuleHandleW(L"api-ms-win-core-wow64-l1-1-1.dll"),
      "IsWow64Process2");
#ifdef CM_VS_GCC_DIAGNOSTIC_PUSHED
#  pragma GCC diagnostic pop
#  undef CM_VS_GCC_DIAGNOSTIC_PUSHED
#endif

  USHORT processMachine;
  USHORT nativeMachine;

  return s_IsWow64Process2Impl &&
    s_IsWow64Process2Impl(GetCurrentProcess(), &processMachine,
                          &nativeMachine) &&
    nativeMachine == IMAGE_FILE_MACHINE_ARM64;
}

static bool VSHasDotNETFrameworkArm64()
{
  std::string dotNetArm64;
  return cmSystemTools::ReadRegistryValue(
    R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework;InstallRootArm64)",
    dotNetArm64, cmSystemTools::KeyWOW64_64);
}

static bool VSIsWindows11OrGreater()
{
  cmSystemTools::WindowsVersion const windowsVersion =
    cmSystemTools::GetWindowsVersion();
  return (windowsVersion.dwMajorVersion > 10 ||
          (windowsVersion.dwMajorVersion == 10 &&
           windowsVersion.dwMinorVersion > 0) ||
          (windowsVersion.dwMajorVersion == 10 &&
           windowsVersion.dwMinorVersion == 0 &&
           windowsVersion.dwBuildNumber >= 22000));
}

static std::string VSHostPlatformName()
{
  if (VSIsArm64Host()) {
    return "ARM64";
  }
  if (VSIsWow64()) {
    return "x64";
  }
#if defined(_M_ARM)
  return "ARM";
#elif defined(_M_IA64)
  return "Itanium";
#elif defined(_WIN64)
  return "x64";
#else
  return "Win32";
#endif
}

static std::string VSHostArchitecture(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  if (VSIsArm64Host()) {
    return v >= cmGlobalVisualStudioGenerator::VSVersion::VS17 ? "ARM64" : "";
  }
  if (VSIsWow64()) {
    return "x64";
  }
#if defined(_M_ARM)
  return "";
#elif defined(_M_IA64)
  return "";
#elif defined(_WIN64)
  return "x64";
#else
  return "x86";
#endif
}

static unsigned int VSVersionToMajor(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return 14;
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
      return 15;
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
      return 16;
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return 17;
  }
  return 0;
}

static char const* VSVersionToToolset(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return "v140";
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
      return "v141";
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
      return "v142";
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return "v143";
  }
  return "";
}

static std::string VSVersionToMajorString(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return "14";
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
      return "15";
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
      return "16";
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return "17";
  }
  return "";
}

static char const* VSVersionToAndroidToolset(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return "Clang_3_8";
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return "Clang_5_0";
  }
  return "";
}

static char const vs15generatorName[] = "Visual Studio 15 2017";

// Map generator name without year to name with year.
static char const* cmVS15GenName(std::string const& name, std::string& genName)
{
  if (strncmp(name.c_str(), vs15generatorName,
              sizeof(vs15generatorName) - 6) != 0) {
    return nullptr;
  }
  char const* p = name.c_str() + sizeof(vs15generatorName) - 6;
  if (cmHasLiteralPrefix(p, " 2017")) {
    p += 5;
  }
  genName = cmStrCat(vs15generatorName, p);
  return p;
}

class cmGlobalVisualStudioVersionedGenerator::Factory15
  : public cmGlobalGeneratorFactory
{
public:
  std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
    std::string const& name, cmake* cm) const override
  {
    std::string genName;
    char const* p = cmVS15GenName(name, genName);
    if (!p) {
      return std::unique_ptr<cmGlobalGenerator>();
    }
    if (!*p) {
      return std::unique_ptr<cmGlobalGenerator>(
        new cmGlobalVisualStudioVersionedGenerator(
          cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName));
    }
    return std::unique_ptr<cmGlobalGenerator>();
  }

  cmDocumentationEntry GetDocumentation() const override
  {
    return { std::string(vs15generatorName),
             "Generates Visual Studio 2017 project files.  "
             "Use -A option to specify architecture." };
  }

  std::vector<std::string> GetGeneratorNames() const override
  {
    std::vector<std::string> names;
    names.push_back(vs15generatorName);
    return names;
  }

  bool SupportsToolset() const override { return true; }
  bool SupportsPlatform() const override { return true; }

  std::vector<std::string> GetKnownPlatforms() const override
  {
    std::vector<std::string> platforms;
    platforms.emplace_back("x64");
    platforms.emplace_back("Win32");
    platforms.emplace_back("ARM");
    platforms.emplace_back("ARM64");
    return platforms;
  }

  std::string GetDefaultPlatformName() const override { return "Win32"; }
};

std::unique_ptr<cmGlobalGeneratorFactory>
cmGlobalVisualStudioVersionedGenerator::NewFactory15()
{
  return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory15);
}

static char const vs16generatorName[] = "Visual Studio 16 2019";
static char const vs17generatorName[] = "Visual Studio 17 2022";

// Map generator name without year to name with year.
static char const* cmVS16GenName(std::string const& name, std::string& genName)
{
  if (strncmp(name.c_str(), vs16generatorName,
              sizeof(vs16generatorName) - 6) != 0) {
    return nullptr;
  }
  char const* p = name.c_str() + sizeof(vs16generatorName) - 6;
  if (cmHasLiteralPrefix(p, " 2019")) {
    p += 5;
  }
  genName = cmStrCat(vs16generatorName, p);
  return p;
}

static char const* cmVS17GenName(std::string const& name, std::string& genName)
{
  if (strncmp(name.c_str(), vs17generatorName,
              sizeof(vs17generatorName) - 6) != 0) {
    return nullptr;
  }
  char const* p = name.c_str() + sizeof(vs17generatorName) - 6;
  if (cmHasLiteralPrefix(p, " 2022")) {
    p += 5;
  }
  genName = cmStrCat(vs17generatorName, p);
  return p;
}

class cmGlobalVisualStudioVersionedGenerator::Factory16
  : public cmGlobalGeneratorFactory
{
public:
  std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
    std::string const& name, cmake* cm) const override
  {
    std::string genName;
    char const* p = cmVS16GenName(name, genName);
    if (!p) {
      return std::unique_ptr<cmGlobalGenerator>();
    }
    if (!*p) {
      return std::unique_ptr<cmGlobalGenerator>(
        new cmGlobalVisualStudioVersionedGenerator(
          cmGlobalVisualStudioGenerator::VSVersion::VS16, cm, genName));
    }
    return std::unique_ptr<cmGlobalGenerator>();
  }

  cmDocumentationEntry GetDocumentation() const override
  {
    return { std::string(vs16generatorName),
             "Generates Visual Studio 2019 project files.  "
             "Use -A option to specify architecture." };
  }

  std::vector<std::string> GetGeneratorNames() const override
  {
    std::vector<std::string> names;
    names.push_back(vs16generatorName);
    return names;
  }

  bool SupportsToolset() const override { return true; }
  bool SupportsPlatform() const override { return true; }

  std::vector<std::string> GetKnownPlatforms() const override
  {
    std::vector<std::string> platforms;
    platforms.emplace_back("x64");
    platforms.emplace_back("Win32");
    platforms.emplace_back("ARM");
    platforms.emplace_back("ARM64");
    platforms.emplace_back("ARM64EC");
    return platforms;
  }

  std::string GetDefaultPlatformName() const override
  {
    return VSHostPlatformName();
  }
};

std::unique_ptr<cmGlobalGeneratorFactory>
cmGlobalVisualStudioVersionedGenerator::NewFactory16()
{
  return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory16);
}

class cmGlobalVisualStudioVersionedGenerator::Factory17
  : public cmGlobalGeneratorFactory
{
public:
  std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
    std::string const& name, cmake* cm) const override
  {
    std::string genName;
    char const* p = cmVS17GenName(name, genName);
    if (!p) {
      return std::unique_ptr<cmGlobalGenerator>();
    }
    if (!*p) {
      return std::unique_ptr<cmGlobalGenerator>(
        new cmGlobalVisualStudioVersionedGenerator(
          cmGlobalVisualStudioGenerator::VSVersion::VS17, cm, genName));
    }
    return std::unique_ptr<cmGlobalGenerator>();
  }

  cmDocumentationEntry GetDocumentation() const override
  {
    return { std::string(vs17generatorName),
             "Generates Visual Studio 2022 project files.  "
             "Use -A option to specify architecture." };
  }

  std::vector<std::string> GetGeneratorNames() const override
  {
    std::vector<std::string> names;
    names.push_back(vs17generatorName);
    return names;
  }

  bool SupportsToolset() const override { return true; }
  bool SupportsPlatform() const override { return true; }

  std::vector<std::string> GetKnownPlatforms() const override
  {
    std::vector<std::string> platforms;
    platforms.emplace_back("x64");
    platforms.emplace_back("Win32");
    platforms.emplace_back("ARM");
    platforms.emplace_back("ARM64");
    platforms.emplace_back("ARM64EC");
    return platforms;
  }

  std::string GetDefaultPlatformName() const override
  {
    return VSHostPlatformName();
  }
};

std::unique_ptr<cmGlobalGeneratorFactory>
cmGlobalVisualStudioVersionedGenerator::NewFactory17()
{
  return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory17);
}

cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
  VSVersion version, cmake* cm, std::string const& name)
  : cmGlobalVisualStudio14Generator(cm, name)
  , vsSetupAPIHelper(VSVersionToMajor(version))
{
  this->Version = version;
  this->ExpressEdition = false;
  this->DefaultPlatformToolset = VSVersionToToolset(this->Version);
  this->DefaultAndroidToolset = VSVersionToAndroidToolset(this->Version);
  this->DefaultCLFlagTableName = VSVersionToToolset(this->Version);
  this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version);
  this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version);
  if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    this->DefaultPlatformName = VSHostPlatformName();
    this->DefaultPlatformToolsetHostArchitecture =
      VSHostArchitecture(this->Version);
  }
  if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {
    // FIXME: Search for an existing framework?  Under '%ProgramFiles(x86)%',
    // see 'Reference Assemblies\Microsoft\Framework\.NETFramework'.
    // Use a version installed by VS 2022 without a separate component.
    this->DefaultTargetFrameworkVersion = "v4.7.2";
  }
}

bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
  std::string const& name) const
{
  std::string genName;
  switch (this->Version) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      break;
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
      if (cmVS15GenName(name, genName)) {
        return genName == this->GetName();
      }
      break;
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
      if (cmVS16GenName(name, genName)) {
        return genName == this->GetName();
      }
      break;
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      if (cmVS17GenName(name, genName)) {
        return genName == this->GetName();
      }
      break;
  }
  return false;
}

bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
  std::string const& i, cmMakefile* mf)
{
  if (this->LastGeneratorInstanceString &&
      i == *(this->LastGeneratorInstanceString)) {
    this->SetVSVersionVar(mf);
    return true;
  }

  if (!this->ParseGeneratorInstance(i, mf)) {
    return false;
  }

  if (!this->GeneratorInstanceVersion.empty()) {
    std::string const majorStr = VSVersionToMajorString(this->Version);
    cmsys::RegularExpression versionRegex(
      cmStrCat('^', majorStr, R"(\.[0-9]+\.[0-9]+\.[0-9]+$)"));
    if (!versionRegex.find(this->GeneratorInstanceVersion)) {
      mf->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Generator\n"
                 "  ",
                 this->GetName(),
                 "\n"
                 "given instance specification\n"
                 "  ",
                 i,
                 "\n"
                 "but the version field is not 4 integer components"
                 " starting in ",
                 majorStr, '.'));
      return false;
    }
  }

  std::string vsInstance;
  if (!i.empty()) {
    vsInstance = i;
    if (!this->vsSetupAPIHelper.SetVSInstance(
          this->GeneratorInstance, this->GeneratorInstanceVersion)) {
      std::ostringstream e;
      /* clang-format off */
      e <<
        "Generator\n"
        "  " << this->GetName() << "\n"
        "could not find specified instance of Visual Studio:\n"
        "  " << i;
      /* clang-format on */
      if (!this->GeneratorInstance.empty() &&
          this->GeneratorInstanceVersion.empty() &&
          cmSystemTools::FileIsDirectory(this->GeneratorInstance)) {
        e << "\n"
             "The directory exists, but the instance is not known to the "
             "Visual Studio Installer, and no 'version=' field was given.";
      }
      mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return false;
    }
  } else if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
    mf->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("Generator\n"
               "  ",
               this->GetName(),
               "\n"
               "could not find any instance of Visual Studio.\n"));
    return false;
  }

  // Save the selected instance persistently.
  std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
  if (vsInstance != genInstance) {
    this->CMakeInstance->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", vsInstance,
                                       "Generator instance identifier.",
                                       cmStateEnums::INTERNAL);
  }

  this->SetVSVersionVar(mf);

  // The selected instance may have a different MSBuild than previously found.
  this->MSBuildCommandInitialized = false;

  this->LastGeneratorInstanceString = i;

  return true;
}

bool cmGlobalVisualStudioVersionedGenerator::ParseGeneratorInstance(
  std::string const& is, cmMakefile* mf)
{
  this->GeneratorInstance.clear();
  this->GeneratorInstanceVersion.clear();

  std::vector<std::string> const fields =
    cmTokenize(is, ',', cmTokenizerMode::New);
  if (fields.empty()) {
    return true;
  }

  auto fi = fields.begin();
  // The first field may be the VS instance.
  if (fi->find('=') == fi->npos) {
    this->GeneratorInstance = *fi;
    ++fi;
  }

  std::set<std::string> handled;

  // The rest of the fields must be key=value pairs.
  for (; fi != fields.end(); ++fi) {
    std::string::size_type pos = fi->find('=');
    if (pos == fi->npos) {
      mf->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Generator\n"
                 "  ",
                 this->GetName(),
                 "\n"
                 "given instance specification\n"
                 "  ",
                 is,
                 "\n"
                 "that contains a field after the first ',' with no '='."));
      return false;
    }
    std::string const key = fi->substr(0, pos);
    std::string const value = fi->substr(pos + 1);
    if (!handled.insert(key).second) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("Generator\n"
                                "  ",
                                this->GetName(),
                                "\n"
                                "given instance specification\n"
                                "  ",
                                is,
                                "\n"
                                "that contains duplicate field key '",
                                key, "'."));
      return false;
    }
    if (!this->ProcessGeneratorInstanceField(key, value)) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("Generator\n"
                                "  ",
                                this->GetName(),
                                "\n"
                                "given instance specification\n"
                                "  ",
                                is,
                                "\n"
                                "that contains invalid field '",
                                *fi, "'."));
      return false;
    }
  }

  return true;
}

void cmGlobalVisualStudioVersionedGenerator::SetVSVersionVar(cmMakefile* mf)
{
  if (cm::optional<std::string> vsVer = this->GetVSInstanceVersion()) {
    mf->AddDefinition("CMAKE_VS_VERSION_BUILD_NUMBER", *vsVer);
  }
}

bool cmGlobalVisualStudioVersionedGenerator::ProcessGeneratorInstanceField(
  std::string const& key, std::string const& value)
{
  if (key == "version"_s) {
    this->GeneratorInstanceVersion = value;
    return true;
  }
  return false;
}

bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance(
  std::string& dir) const
{
  return vsSetupAPIHelper.GetVSInstanceInfo(dir);
}

cm::optional<std::string>
cmGlobalVisualStudioVersionedGenerator::GetVSInstanceVersion() const
{
  cm::optional<std::string> result;
  std::string vsInstanceVersion;
  if (vsSetupAPIHelper.GetVSInstanceVersion(vsInstanceVersion)) {
    result = vsInstanceVersion;
  }
  return result;
}

bool cmGlobalVisualStudioVersionedGenerator::IsStdOutEncodingSupported() const
{
  // Supported from Visual Studio 16.7 Preview 3.
  if (this->Version > cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    return true;
  }
  if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    return false;
  }
  static std::string const vsVer16_7_P2 = "16.7.30128.36";
  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  return (vsVer &&
          cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_7_P2));
}

bool cmGlobalVisualStudioVersionedGenerator::IsUtf8EncodingSupported() const
{
  // Supported from Visual Studio 16.10 Preview 2.
  if (this->Version > cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    return true;
  }
  if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    return false;
  }
  static std::string const vsVer16_10_P2 = "16.10.31213.239";
  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  return (vsVer &&
          cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer16_10_P2));
}

bool cmGlobalVisualStudioVersionedGenerator::IsScanDependenciesSupported()
  const
{
  // Supported from Visual Studio 17.6 Preview 7.
  if (this->Version > cmGlobalVisualStudioGenerator::VSVersion::VS17) {
    return true;
  }
  if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS17) {
    return false;
  }
  static std::string const vsVer17_6_P7 = "17.6.33706.43";
  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  return (vsVer &&
          cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer17_6_P7));
}

char const*
cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
  const
{
  switch (this->Version) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return "2.0";
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return "3.0";
  }
  return "";
}

cmGlobalVisualStudioVersionedGenerator::AuxToolset
cmGlobalVisualStudioVersionedGenerator::FindAuxToolset(
  std::string& version, std::string& props) const
{
  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 threeComponentRegex(
    "^([0-9]+\\.[0-9]+)\\.[0-9][0-9][0-9][0-9][0-9]$");
  // 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 = threeComponentRegex.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;
            }
          }
        }
      }
    }
  } 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);
    if (glob.FindFiles(pattern) && !glob.GetFiles().empty()) {
      // Since we are only using the first two components of the
      // toolset version, we require a single match.
      if (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")) {
    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"_s && vcToolsetVersion == "14.28.29910"_s) {
      return AuxToolset::Default;
    }
    if (version == "14.29.16.10"_s && vcToolsetVersion == "14.29.30037"_s) {
      return AuxToolset::Default;
    }
    if (version == "14.29.16.11"_s && vcToolsetVersion == "14.29.30133"_s) {
      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::SelectWindowsStoreToolset(
  std::string& toolset) const
{
  if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
    if (this->IsWindowsStoreToolsetInstalled() &&
        this->IsWindowsDesktopToolsetInstalled()) {
      toolset = VSVersionToToolset(this->Version);
      return true;
    }
    return false;
  }
  return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
    toolset);
}

bool cmGlobalVisualStudioVersionedGenerator::IsWindowsDesktopToolsetInstalled()
  const
{
  return vsSetupAPIHelper.IsVSInstalled();
}

bool cmGlobalVisualStudioVersionedGenerator::IsWindowsStoreToolsetInstalled()
  const
{
  return vsSetupAPIHelper.IsWin10SDKInstalled();
}

bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const
{
  // Does the VS installer tool know about one?
  if (vsSetupAPIHelper.IsWin81SDKInstalled()) {
    return true;
  }

  // Does the registry know about one (e.g. from VS 2015)?
  std::string win81Root;
  if (cmSystemTools::ReadRegistryValue(
        "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
        "Windows Kits\\Installed Roots;KitsRoot81",
        win81Root, cmSystemTools::KeyWOW64_32) ||
      cmSystemTools::ReadRegistryValue(
        "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
        "Windows Kits\\Installed Roots;KitsRoot81",
        win81Root, cmSystemTools::KeyWOW64_32)) {
    return cmSystemTools::FileExists(
      cmStrCat(win81Root, "/include/um/windows.h"), true);
  }
  return false;
}

std::string
cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersionDefault(
  cmMakefile*) const
{
  return std::string();
}

cm::optional<std::string>
cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommandEarly(cmMakefile* mf)
{
  std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
  if (!this->SetGeneratorInstance(instance, mf)) {
    cmSystemTools::SetFatalErrorOccurred();
    return {};
  }
  return this->cmGlobalVisualStudio14Generator::FindMSBuildCommandEarly(mf);
}

std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
{
  std::string msbuild;

  // Ask Visual Studio Installer tool.
  std::string vs;
  if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
    if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {
      if (VSIsArm64Host()) {
        if (VSHasDotNETFrameworkArm64()) {
          msbuild = cmStrCat(vs, "/MSBuild/Current/Bin/arm64/MSBuild.exe");
          if (cmSystemTools::FileExists(msbuild)) {
            return msbuild;
          }
        }
        if (VSIsWindows11OrGreater()) {
          msbuild = cmStrCat(vs, "/MSBuild/Current/Bin/amd64/MSBuild.exe");
          if (cmSystemTools::FileExists(msbuild)) {
            return msbuild;
          }
        }
      } else {
        msbuild = cmStrCat(vs, "/MSBuild/Current/Bin/amd64/MSBuild.exe");
        if (cmSystemTools::FileExists(msbuild)) {
          return msbuild;
        }
      }
    }
    msbuild = cmStrCat(vs, "/MSBuild/Current/Bin/MSBuild.exe");
    if (cmSystemTools::FileExists(msbuild)) {
      return msbuild;
    }
    msbuild = cmStrCat(vs, "/MSBuild/15.0/Bin/MSBuild.exe");
    if (cmSystemTools::FileExists(msbuild)) {
      return msbuild;
    }
  }

  msbuild = "MSBuild.exe";
  return msbuild;
}

std::string cmGlobalVisualStudioVersionedGenerator::FindDevEnvCommand()
{
  std::string devenv;

  // Ask Visual Studio Installer tool.
  std::string vs;
  if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
    devenv = cmStrCat(vs, "/Common7/IDE/devenv.com");
    if (cmSystemTools::FileExists(devenv)) {
      return devenv;
    }
  }

  devenv = "devenv.com";
  return devenv;
}
