/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt 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 != nullptr &&
    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::VS12:
      return 12;
    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 const char* VSVersionToToolset(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS12:
      return "v120";
    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::VS12:
      return "12";
    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 const char* VSVersionToAndroidToolset(
  cmGlobalVisualStudioGenerator::VSVersion v)
{
  switch (v) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS12:
      return "";
    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 const char vs15generatorName[] = "Visual Studio 15 2017";

// Map generator name without year to name with year.
static const char* cmVS15GenName(const std::string& name, std::string& genName)
{
  if (strncmp(name.c_str(), vs15generatorName,
              sizeof(vs15generatorName) - 6) != 0) {
    return nullptr;
  }
  const char* 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(
    const std::string& name, bool allowArch, cmake* cm) const override
  {
    std::string genName;
    const char* 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, ""));
    }
    if (!allowArch || *p++ != ' ') {
      return std::unique_ptr<cmGlobalGenerator>();
    }
    if (strcmp(p, "Win64") == 0) {
      return std::unique_ptr<cmGlobalGenerator>(
        new cmGlobalVisualStudioVersionedGenerator(
          cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName, "x64"));
    }
    if (strcmp(p, "ARM") == 0) {
      return std::unique_ptr<cmGlobalGenerator>(
        new cmGlobalVisualStudioVersionedGenerator(
          cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName, "ARM"));
    }
    return std::unique_ptr<cmGlobalGenerator>();
  }

  cmDocumentationEntry GetDocumentation() const override
  {
    return { cmStrCat(vs15generatorName, " [arch]"),
             "Generates Visual Studio 2017 project files.  "
             "Optional [arch] can be \"Win64\" or \"ARM\"." };
  }

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

  std::vector<std::string> GetGeneratorNamesWithPlatform() const override
  {
    std::vector<std::string> names;
    names.emplace_back(cmStrCat(vs15generatorName, " ARM"));
    names.emplace_back(cmStrCat(vs15generatorName, " Win64"));
    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 const char vs16generatorName[] = "Visual Studio 16 2019";
static const char vs17generatorName[] = "Visual Studio 17 2022";

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

static const char* cmVS17GenName(const std::string& name, std::string& genName)
{
  if (strncmp(name.c_str(), vs17generatorName,
              sizeof(vs17generatorName) - 6) != 0) {
    return nullptr;
  }
  const char* 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(
    const std::string& name, bool /*allowArch*/, cmake* cm) const override
  {
    std::string genName;
    const char* 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;
  }

  std::vector<std::string> GetGeneratorNamesWithPlatform() const override
  {
    return std::vector<std::string>();
  }

  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(
    const std::string& name, bool /*allowArch*/, cmake* cm) const override
  {
    std::string genName;
    const char* 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;
  }

  std::vector<std::string> GetGeneratorNamesWithPlatform() const override
  {
    return std::vector<std::string>();
  }

  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, const std::string& name,
  std::string const& platformInGeneratorName)
  : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName)
  , 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(
  const std::string& name) const
{
  std::string genName;
  switch (this->Version) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS12:
    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, ",");
  auto fi = fields.begin();
  if (fi == fields.end()) {
    return true;
  }

  // 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));
}

const char*
cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
  const
{
  switch (this->Version) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS12:
      return "";
    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;
}
