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

#include <algorithm>
#include <cstring>
#include <map>
#include <sstream>
#include <utility>

#include <cm/memory>
#include <cmext/string_view>

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>

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

#include "cmCryptoHash.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio7Generator.h"
#include "cmGlobalVisualStudioGenerator.h"
#include "cmIDEFlagTable.h"
#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmVisualStudioSlnData.h"
#include "cmVisualStudioSlnParser.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
#include "cmake.h"

class cmSlnxParser : public cmXMLParser
{
public:
  std::map<std::string, std::string> ProjectToPath;
  void StartElement(std::string const& name, char const** atts) override
  {
    if (name == "Project"_s) {
      if (char const* rawPath = this->FindAttribute(atts, "Path")) {
        std::string path = rawPath;
        cmSystemTools::ConvertToUnixSlashes(path);
        std::string nameOnly =
          cmsys::SystemTools::GetFilenameWithoutLastExtension(path);
        this->ProjectToPath[cmSystemTools::LowerCase(nameOnly)] = path;
      }
    }
  }
  void EndElement(std::string const&) override {}
};

static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;

static void ConvertToWindowsSlashes(std::string& s)
{
  // first convert all of the slashes
  for (auto& ch : s) {
    if (ch == '/') {
      ch = '\\';
    }
  }
}

cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
  cmake* cm, std::string const& name)
  : cmGlobalVisualStudio8Generator(cm, name)
{
  this->DefaultCudaFlagTableName = "v10";
  this->DefaultCudaHostFlagTableName = "v10";
  this->DefaultMarmasmFlagTableName = "v10";
  this->DefaultNasmFlagTableName = "v10";
}

bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s,
                                                    cmMakefile* mf)
{
  this->SystemName = s;
  this->SystemVersion = mf->GetSafeDefinition("CMAKE_SYSTEM_VERSION");
  if (!this->InitializeSystem(mf)) {
    return false;
  }
  return this->cmGlobalVisualStudio8Generator::SetSystemName(s, mf);
}

static void cmCudaToolVersion(std::string& s)
{
  // "CUDA x.y.props" => "x.y"
  s = s.substr(5);
  s = s.substr(0, s.size() - 6);
}

bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
  std::string const& ts, bool build, cmMakefile* mf)
{
  if (this->SystemIsWindowsCE && ts.empty() &&
      this->DefaultPlatformToolset.empty()) {
    mf->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat(this->GetName(), " Windows CE version '", this->SystemVersion,
               "' requires CMAKE_GENERATOR_TOOLSET to be set."));
    return false;
  }

  if (!this->ParseGeneratorToolset(ts, mf)) {
    return false;
  }

  if (build) {
    return true;
  }

  if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) {
    return false;
  }

  if (!this->CustomFlagTableDir.empty() &&
      !(cmSystemTools::FileIsFullPath(this->CustomFlagTableDir) &&
        cmSystemTools::FileIsDirectory(this->CustomFlagTableDir))) {
    mf->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("Generator\n"
               "  ",
               this->GetName(),
               "\n"
               "given toolset\n"
               "  customFlagTableDir=",
               this->CustomFlagTableDir,
               "\n"
               "that is not an absolute path to an existing directory."));
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }

  if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) {
    // The GenerateDebugInformation link setting for the v140 toolset
    // in VS 2015 was originally an enum with "No" and "Debug" values,
    // differing from the "false" and "true" values used in older toolsets.
    // A VS 2015 update changed it back.  Parse the "link.xml" file to
    // discover which one we need.
    std::string const link_xml =
      cmStrCat(this->VCTargetsPath, "/1033/link.xml");
    cmsys::ifstream fin(link_xml.c_str());
    std::string line;
    while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
      if (line.find(" Switch=\"DEBUG\" ") != std::string::npos) {
        this->PlatformToolsetNeedsDebugEnum =
          line.find(" Name=\"Debug\" ") != std::string::npos;
        break;
      }
    }
  }

  this->SupportsUnityBuilds =
    this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 ||
    (this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS15 &&
     cmSystemTools::PathExists(
       cmStrCat(this->VCTargetsPath, "/Microsoft.Cpp.Unity.targets")));

  if (this->GeneratorToolsetCuda.empty()) {
    // Find the highest available version of the CUDA tools.
    std::vector<std::string> cudaTools;
    std::string bcDir;
    if (this->GeneratorToolsetCudaCustomDir.empty()) {
      bcDir = cmStrCat(this->VCTargetsPath, "/BuildCustomizations");
    } else {
      bcDir = cmStrCat(this->GetPlatformToolsetCudaCustomDirString(),
                       this->GetPlatformToolsetCudaVSIntegrationSubdirString(),
                       "extras\\visual_studio_integration\\MSBuildExtensions");
      cmSystemTools::ConvertToUnixSlashes(bcDir);
    }
    cmsys::Glob gl;
    gl.SetRelative(bcDir.c_str());
    if (gl.FindFiles(cmStrCat(bcDir, "/CUDA *.props"))) {
      cudaTools = gl.GetFiles();
    }
    if (!cudaTools.empty()) {
      std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion);
      std::sort(cudaTools.begin(), cudaTools.end(),
                cmSystemTools::VersionCompareGreater);
      this->GeneratorToolsetCuda = cudaTools.at(0);
    } else if (!this->GeneratorToolsetCudaCustomDir.empty()) {
      // Generate an error if Visual Studio integration files are not found
      // inside of custom cuda toolset.
      mf->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Generator\n"
                 "  ",
                 this->GetName(),
                 "\n"
                 "given toolset\n"
                 "  cuda=",
                 this->GeneratorToolsetCudaCustomDir,
                 "\n"
                 "cannot detect Visual Studio integration files in path\n"
                 "  ",
                 bcDir));

      // Clear the configured tool-set
      this->GeneratorToolsetCuda.clear();
    }
  }

  if (this->GeneratorToolsetFortran) {
    if (*this->GeneratorToolsetFortran != "ifx" &&
        *this->GeneratorToolsetFortran != "ifort") {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("Generator\n"
                                "  ",
                                this->GetName(),
                                "\n"
                                "given toolset\n"
                                "  fortran=",
                                *this->GeneratorToolsetFortran,
                                "\n"
                                "but the value is not \"ifx\" or \"ifort\"."));
      this->GeneratorToolsetFortran = cm::nullopt;
    }
  }

  if (!this->GeneratorToolsetVersion.empty() &&
      this->GeneratorToolsetVersion != "Test Toolset Version"_s) {
    // If a specific minor version of the MSVC toolset is requested, verify
    // that it is compatible with the PlatformToolset version. The ability to
    // choose a minor version of MSVC has been available since v141.
    std::string const& platformToolset = this->GetPlatformToolsetString();
    cmsys::RegularExpression vcPlatformToolsetRegex("^v[0-9][0-9][0-9]$");
    if (vcPlatformToolsetRegex.find(platformToolset) ||
        platformToolset == "Test Toolset"_s) {
      std::string versionToolset = this->GeneratorToolsetVersion;
      cmsys::RegularExpression versionToolsetRegex(
        "^([0-9][0-9])\\.([0-9])[0-9](\\.|$)");
      if (versionToolsetRegex.find(versionToolset)) {
        versionToolset = cmStrCat('v', versionToolsetRegex.match(1),
                                  versionToolsetRegex.match(2));
        // Hard-code special cases for toolset versions whose first
        // three digits do not match their toolset name.
        // The v143 toolset reserves versions 14.30 through 14.49.
        if (platformToolset == "v143"_s && versionToolset == "v144"_s) {
          versionToolset = "v143";
        }
      } else {
        // Version not recognized. Clear it.
        versionToolset.clear();
      }

      if (versionToolset != platformToolset) {
        mf->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("Generator\n"
                   "  ",
                   this->GetName(),
                   "\n"
                   "given toolset and version specification\n"
                   "  ",
                   this->GetPlatformToolsetString(),
                   ",version=", this->GeneratorToolsetVersion,
                   "\n"
                   "contains an invalid version specification."));

        // Clear the configured tool-set
        this->GeneratorToolsetVersion.clear();
      }
    }

    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: {
        mf->IssueMessage(MessageType::FATAL_ERROR,
                         cmStrCat("Generator\n"
                                  "  ",
                                  this->GetName(),
                                  "\n"
                                  "given toolset and version specification\n"
                                  "  ",
                                  this->GetPlatformToolsetString(),
                                  ",version=", this->GeneratorToolsetVersion,
                                  "\n"
                                  "does not seem to be installed at\n"
                                  "  ",
                                  auxProps));

        // Clear the configured tool-set
        this->GeneratorToolsetVersion.clear();
        this->GeneratorToolsetVersionProps = {};
      } break;
      case AuxToolset::PropsIndeterminate: {
        mf->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("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"));

        // Clear the configured tool-set
        this->GeneratorToolsetVersion.clear();
        this->GeneratorToolsetVersionProps = {};
      } break;
    }
  }

  if (char const* toolset = this->GetPlatformToolset()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
  }
  if (!this->GeneratorToolsetVersion.empty()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION",
                      this->GeneratorToolsetVersion);
  }
  if (char const* hostArch = this->GetPlatformToolsetHostArchitecture()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
  }
  if (char const* cuda = this->GetPlatformToolsetCuda()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda);
  }
  if (char const* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
  }
  if (cm::optional<std::string> fortran = this->GetPlatformToolsetFortran()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_FORTRAN", *fortran);
  }
  if (char const* vcTargetsDir = this->GetCustomVCTargetsPath()) {
    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR",
                      vcTargetsDir);
  }

  return true;
}

bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
  std::string const& ts, cmMakefile* mf)
{
  std::vector<std::string> const fields =
    cmTokenize(ts, ',', cmTokenizerMode::New);
  if (fields.empty()) {
    return true;
  }

  auto fi = fields.begin();
  // The first field may be the VS platform toolset.
  if (fi->find('=') == fi->npos) {
    this->GeneratorToolset = *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 toolset specification\n"
                 "  ",
                 ts,
                 "\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 toolset specification\n"
                                "  ",
                                ts,
                                "\n"
                                "that contains duplicate field key '",
                                key, "'."));
      return false;
    }
    if (!this->ProcessGeneratorToolsetField(key, value)) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("Generator\n"
                                "  ",
                                this->GetName(),
                                "\n"
                                "given toolset specification\n"
                                "  ",
                                ts,
                                "\n"
                                "that contains invalid field '",
                                *fi, "'."));
      return false;
    }
  }

  return true;
}

bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
  std::string const& key, std::string const& value)
{
  if (key == "cuda"_s) {
    /* test if cuda toolset is path to custom dir or cuda version */
    auto pos = value.find_first_not_of("0123456789.");
    if (pos != std::string::npos) {
      this->GeneratorToolsetCudaCustomDir = value;
      /* ensure trailing backslash for easy path joining */
      if (this->GeneratorToolsetCudaCustomDir.back() != '\\') {
        this->GeneratorToolsetCudaCustomDir.push_back('\\');
      }
      /* check for legacy toolkit folder structure */
      if (cmsys::SystemTools::FileIsDirectory(
            cmStrCat(this->GeneratorToolsetCudaCustomDir, "nvcc"))) {
        this->GeneratorToolsetCudaNvccSubdir = "nvcc\\";
      }
      if (cmsys::SystemTools::FileIsDirectory(
            cmStrCat(this->GeneratorToolsetCudaCustomDir,
                     "CUDAVisualStudioIntegration"))) {
        this->GeneratorToolsetCudaVSIntegrationSubdir =
          "CUDAVisualStudioIntegration\\";
      }
    } else {
      this->GeneratorToolsetCuda = value;
    }
    return true;
  }
  if (key == "customFlagTableDir"_s) {
    this->CustomFlagTableDir = value;
    cmSystemTools::ConvertToUnixSlashes(this->CustomFlagTableDir);
    return true;
  }
  if (key == "fortran"_s) {
    this->GeneratorToolsetFortran = value;
    return true;
  }
  if (key == "version"_s) {
    this->GeneratorToolsetVersion = value;
    return true;
  }
  if (key == "VCTargetsPath"_s) {
    this->CustomVCTargetsPath = value;
    ConvertToWindowsSlashes(this->CustomVCTargetsPath);
    return true;
  }
  return false;
}

bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
{
  if (this->SystemName == "Windows"_s) {
    if (!this->InitializeWindows(mf)) {
      return false;
    }
  } else if (this->SystemName == "WindowsCE"_s) {
    this->SystemIsWindowsCE = true;
    if (!this->InitializeWindowsCE(mf)) {
      return false;
    }
  } else if (this->SystemName == "WindowsPhone"_s) {
    this->SystemIsWindowsPhone = true;
    if (!this->InitializeWindowsPhone(mf)) {
      return false;
    }
  } else if (this->SystemName == "WindowsStore"_s) {
    this->SystemIsWindowsStore = true;
    if (!this->InitializeWindowsStore(mf)) {
      return false;
    }
  } else if (this->SystemName == "WindowsKernelModeDriver"_s) {
    this->SystemIsWindowsKernelModeDriver = true;
    if (!this->InitializeWindowsKernelModeDriver(mf)) {
      return false;
    }
  } else if (this->SystemName == "Android"_s) {
    if (mf->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM") ==
        "Tegra-Android"_s) {
      if (!this->InitializeTegraAndroid(mf)) {
        return false;
      }
    } else {
      this->SystemIsAndroid = true;
      if (!this->InitializeAndroid(mf)) {
        return false;
      }
    }
  }

  return true;
}

bool cmGlobalVisualStudio10Generator::InitializeWindows(cmMakefile*)
{
  return true;
}

bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile*)
{
  this->DefaultPlatformToolset = this->SelectWindowsCEToolset();

  return true;
}

bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf)
{
  mf->IssueMessage(
    MessageType::FATAL_ERROR,
    cmStrCat(this->GetName(), " does not support Windows Phone."));
  return false;
}

bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf)
{
  mf->IssueMessage(
    MessageType::FATAL_ERROR,
    cmStrCat(this->GetName(), " does not support Windows Store."));
  return false;
}

bool cmGlobalVisualStudio10Generator::InitializeWindowsKernelModeDriver(
  cmMakefile*)
{
  this->DefaultPlatformToolset = "WindowsKernelModeDriver10.0";
  return true;
}

bool cmGlobalVisualStudio10Generator::InitializeTegraAndroid(cmMakefile* mf)
{
  std::string v =
    cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion();
  if (v.empty()) {
    mf->IssueMessage(MessageType::FATAL_ERROR,
                     "CMAKE_SYSTEM_NAME is 'Android' but "
                     "'NVIDIA Nsight Tegra Visual Studio Edition' "
                     "is not installed.");
    return false;
  }
  this->DefaultPlatformName = "Tegra-Android";
  this->DefaultPlatformToolset = "Default";
  this->NsightTegraVersion = v;
  mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v);
  return true;
}

bool cmGlobalVisualStudio10Generator::InitializeAndroid(cmMakefile* mf)
{
  mf->IssueMessage(MessageType::FATAL_ERROR,
                   cmStrCat(this->GetName(), " does not support Android."));
  return false;
}

bool cmGlobalVisualStudio10Generator::InitializePlatform(cmMakefile* mf)
{
  if (this->SystemName == "Windows"_s ||
      this->SystemName == "WindowsStore"_s) {
    if (!this->InitializePlatformWindows(mf)) {
      return false;
    }
  } else if (!this->SystemName.empty() &&
             !this->VerifyNoGeneratorPlatformVersion(mf)) {
    return false;
  }
  return this->cmGlobalVisualStudio8Generator::InitializePlatform(mf);
}

bool cmGlobalVisualStudio10Generator::InitializePlatformWindows(cmMakefile*)
{
  return true;
}

bool cmGlobalVisualStudio10Generator::VerifyNoGeneratorPlatformVersion(
  cmMakefile*) const
{
  return true;
}

bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
  std::string& toolset) const
{
  toolset.clear();
  return false;
}

bool cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(
  std::string& toolset) const
{
  toolset.clear();
  return false;
}

std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const
{
  if (this->SystemVersion == "8.0"_s) {
    return "CE800";
  }
  return "";
}

//! Create a local generator appropriate to this Global Generator
std::unique_ptr<cmLocalGenerator>
cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmMakefile* mf)
{
  return std::unique_ptr<cmLocalGenerator>(
    cm::make_unique<cmLocalVisualStudio10Generator>(this, mf));
}

void cmGlobalVisualStudio10Generator::Generate()
{
  this->LongestSource = LongestSourcePath();
  this->cmGlobalVisualStudio8Generator::Generate();
  if (!this->AndroidExecutableWarnings.empty() &&
      !this->CMakeInstance->GetIsInTryCompile()) {
    std::ostringstream e;
    /* clang-format off */
    e <<
      "You are using Visual Studio tools for Android, which does not support "
      "standalone executables. However, the following executable targets do "
      "not have the ANDROID_GUI property set, and thus will not be built as "
      "expected. They will be built as shared libraries with executable "
      "filenames:\n"
      "  ";
    /* clang-format on */
    bool first = true;
    for (auto const& name : this->AndroidExecutableWarnings) {
      if (!first) {
        e << ", ";
      }
      first = false;
      e << name;
    }
    this->CMakeInstance->IssueMessage(MessageType::WARNING, e.str());
  }
  if (this->LongestSource.Length > 0) {
    cmLocalGenerator* lg = this->LongestSource.Target->GetLocalGenerator();
    lg->IssueMessage(
      MessageType::WARNING,
      cmStrCat(
        "The binary and/or source directory paths may be too long to generate "
        "Visual Studio 10 files for this project.  "
        "Consider choosing shorter directory names to build this project with "
        "Visual Studio 10.  "
        "A more detailed explanation follows."
        "\n"
        "There is a bug in the VS 10 IDE that renders property dialog fields "
        "blank for files referenced by full path in the project file.  "
        "However, CMake must reference at least one file by full path:\n"
        "  ",
        this->LongestSource.SourceFile->GetFullPath(),
        "\n"
        "This is because some Visual Studio tools would append the relative "
        "path to the end of the referencing directory path, as in:\n"
        "  ",
        lg->GetCurrentBinaryDirectory(), '/', this->LongestSource.SourceRel,
        "\n"
        "and then incorrectly complain that the file does not exist because "
        "the path length is too long for some internal buffer or API.  "
        "To avoid this problem CMake must use a full path for this file "
        "which then triggers the VS 10 property dialog bug."));
  }
  if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
        "CMAKE_VS_NUGET_PACKAGE_RESTORE")) {
    this->CMakeInstance->MarkCliAsUsed("CMAKE_VS_NUGET_PACKAGE_RESTORE");
  }
}

void cmGlobalVisualStudio10Generator::EnableLanguage(
  std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
  for (std::string const& it : lang) {
    if (it == "ASM_NASM"_s) {
      this->NasmEnabled = true;
    }
    if (it == "CUDA"_s) {
      this->CudaEnabled = true;
    }
  }
  this->AddPlatformDefinitions(mf);
  cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}

char const* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const
{
  if (this->CustomVCTargetsPath.empty()) {
    return nullptr;
  }
  return this->CustomVCTargetsPath.c_str();
}

char const* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  if (toolset.empty()) {
    return nullptr;
  }
  return toolset.c_str();
}

std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString()
  const
{
  if (!this->GeneratorToolset.empty()) {
    return this->GeneratorToolset;
  }
  if (this->SystemIsAndroid) {
    if (!this->DefaultAndroidToolset.empty()) {
      return this->DefaultAndroidToolset;
    }
  } else {
    if (!this->DefaultPlatformToolset.empty()) {
      return this->DefaultPlatformToolset;
    }
  }
  static std::string const empty;
  return empty;
}

std::string const&
cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionProps() const
{
  return this->GeneratorToolsetVersionProps;
}

char const*
cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
{
  std::string const& hostArch =
    this->GetPlatformToolsetHostArchitectureString();
  if (hostArch.empty()) {
    return nullptr;
  }
  return hostArch.c_str();
}

std::string const&
cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitectureString()
  const
{
  if (!this->GeneratorToolsetHostArchitecture.empty()) {
    return this->GeneratorToolsetHostArchitecture;
  }
  if (!this->DefaultPlatformToolsetHostArchitecture.empty()) {
    return this->DefaultPlatformToolsetHostArchitecture;
  }
  static std::string const empty;
  return empty;
}

char const* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
{
  if (!this->GeneratorToolsetCuda.empty()) {
    return this->GeneratorToolsetCuda.c_str();
  }
  return nullptr;
}

std::string const&
cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
{
  return this->GeneratorToolsetCuda;
}

char const* cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDir()
  const
{
  if (!this->GeneratorToolsetCudaCustomDir.empty()) {
    return this->GeneratorToolsetCudaCustomDir.c_str();
  }
  return nullptr;
}

std::string const&
cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
{
  return this->GeneratorToolsetCudaCustomDir;
}

std::string const&
cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaNvccSubdirString() const
{
  return this->GeneratorToolsetCudaNvccSubdir;
}

std::string const& cmGlobalVisualStudio10Generator::
  GetPlatformToolsetCudaVSIntegrationSubdirString() const
{
  return this->GeneratorToolsetCudaVSIntegrationSubdir;
}

cm::optional<std::string>
cmGlobalVisualStudio10Generator::GetPlatformToolsetFortran() const
{
  if (this->GeneratorToolsetFortran) {
    return this->GeneratorToolsetFortran;
  }
  return this->DefaultToolsetFortran;
}

cmGlobalVisualStudio10Generator::AuxToolset
cmGlobalVisualStudio10Generator::FindAuxToolset(std::string&,
                                                std::string&) const
{
  return AuxToolset::None;
}

bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
{
  if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
    return false;
  }
  mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND", this->GetMSBuildCommand());
  return true;
}

std::string const& cmGlobalVisualStudio10Generator::GetMSBuildCommand()
{
  if (!this->MSBuildCommandInitialized) {
    this->MSBuildCommandInitialized = true;
    this->MSBuildCommand = this->FindMSBuildCommand();
  }
  return this->MSBuildCommand;
}

cm::optional<std::string>
cmGlobalVisualStudio10Generator::FindMSBuildCommandEarly(cmMakefile*)
{
  return this->GetMSBuildCommand();
}

std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
{
  std::string msbuild;
  std::string mskey;

  // Search in standard location.
  mskey =
    cmStrCat(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\)",
             this->GetToolsVersion(), ";MSBuildToolsPath");
  if (cmSystemTools::ReadRegistryValue(mskey, msbuild,
                                       cmSystemTools::KeyWOW64_32)) {
    cmSystemTools::ConvertToUnixSlashes(msbuild);
    msbuild += "/MSBuild.exe";
    if (cmSystemTools::FileExists(msbuild, true)) {
      return msbuild;
    }
  }

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

std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand()
{
  if (this->ExpressEdition) {
    // Visual Studio Express >= 10 do not have "devenv.com" or
    // "VCExpress.exe" that we can use to build reliably.
    // Tell the caller it needs to use MSBuild instead.
    return "";
  }
  // Skip over the cmGlobalVisualStudio8Generator implementation because
  // we expect a real devenv and do not want to look for VCExpress.
  // NOLINTNEXTLINE(bugprone-parent-virtual-call)
  return this->cmGlobalVisualStudio7Generator::FindDevEnvCommand();
}

bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
{
  // Skip this in special cases within our own test suite.
  if (this->GetPlatformName() == "Test Platform"_s ||
      this->GetPlatformToolsetString() == "Test Toolset"_s) {
    return true;
  }

  std::string wd;
  if (!this->ConfiguredFilesPath.empty()) {
    // In a try-compile we are given the outer CMakeFiles directory.
    wd = this->ConfiguredFilesPath;
  } else {
    wd = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
                  "/CMakeFiles");
  }
  wd += '/';
  wd += cmVersion::GetCMakeVersion();

  // We record the result persistently in a file.
  std::string const txt = cmStrCat(wd, "/VCTargetsPath.txt");

  // If we have a recorded result, use it.
  {
    cmsys::ifstream fin(txt.c_str());
    if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) &&
        cmSystemTools::FileIsDirectory(this->VCTargetsPath)) {
      cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
      return true;
    }
  }

  // Prepare the work directory.
  if (!cmSystemTools::MakeDirectory(wd)) {
    mf->IssueMessage(MessageType::FATAL_ERROR,
                     cmStrCat("Failed to make directory:\n  ", wd));
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }

  // Generate a project file for MSBuild to tell us the VCTargetsPath value.
  std::string const vcxproj = "VCTargetsPath.vcxproj";
  {
    std::string const vcxprojAbs = cmStrCat(wd, '/', vcxproj);
    cmsys::ofstream fout(vcxprojAbs.c_str());
    cmXMLWriter xw(fout);

    cmXMLDocument doc(xw);
    cmXMLElement eprj(doc, "Project");
    eprj.Attribute("DefaultTargets", "Build");
    eprj.Attribute("ToolsVersion", "4.0");
    eprj.Attribute("xmlns",
                   "http://schemas.microsoft.com/developer/msbuild/2003");
    if (this->IsNsightTegra()) {
      cmXMLElement epg(eprj, "PropertyGroup");
      epg.Attribute("Label", "NsightTegraProject");
      cmXMLElement(epg, "NsightTegraProjectRevisionNumber").Content("6");
    }
    {
      cmXMLElement eig(eprj, "ItemGroup");
      eig.Attribute("Label", "ProjectConfigurations");
      cmXMLElement epc(eig, "ProjectConfiguration");
      epc.Attribute("Include", cmStrCat("Debug|", this->GetPlatformName()));
      cmXMLElement(epc, "Configuration").Content("Debug");
      cmXMLElement(epc, "Platform").Content(this->GetPlatformName());
    }
    {
      cmXMLElement epg(eprj, "PropertyGroup");
      epg.Attribute("Label", "Globals");
      cmXMLElement(epg, "ProjectGuid")
        .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
      cmXMLElement(epg, "Keyword")
        .Content(mf->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android"_s
                   ? "Android"
                   : "Win32Proj");
      cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
      if (this->GetSystemName() == "WindowsPhone"_s) {
        cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
        cmXMLElement(epg, "ApplicationTypeRevision")
          .Content(this->GetApplicationTypeRevision());
      } else if (this->GetSystemName() == "WindowsStore"_s) {
        cmXMLElement(epg, "ApplicationType").Content("Windows Store");
        cmXMLElement(epg, "ApplicationTypeRevision")
          .Content(this->GetApplicationTypeRevision());
      } else if (this->GetSystemName() == "Android"_s) {
        cmXMLElement(epg, "ApplicationType").Content("Android");
        cmXMLElement(epg, "ApplicationTypeRevision")
          .Content(this->GetApplicationTypeRevision());
      }
      if (!this->WindowsTargetPlatformVersion.empty()) {
        cmXMLElement(epg, "WindowsTargetPlatformVersion")
          .Content(this->WindowsTargetPlatformVersion);
      }
      if (this->GetSystemName() != "Android"_s) {
        if (this->GetPlatformName() == "ARM64"_s) {
          cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
        } else if (this->GetPlatformName() == "ARM"_s) {
          cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
        }
      }
    }
    cmXMLElement(eprj, "Import")
      .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
    if (char const* hostArch = this->GetPlatformToolsetHostArchitecture()) {
      cmXMLElement epg(eprj, "PropertyGroup");
      cmXMLElement(epg, "PreferredToolArchitecture").Content(hostArch);
    }
    {
      cmXMLElement epg(eprj, "PropertyGroup");
      epg.Attribute("Label", "Configuration");
      {
        // noqa: spellcheck off
        cmXMLElement ect(epg, "ConfigurationType");
        if (this->IsNsightTegra()) {
          // Tegra-Android platform does not understand "Utility".
          ect.Content("StaticLibrary");
        } else {
          ect.Content("Utility");
        }
        // noqa: spellcheck on
      }
      cmXMLElement(epg, "CharacterSet").Content("MultiByte");
      if (this->IsNsightTegra()) {
        cmXMLElement(epg, "NdkToolchainVersion")
          .Content(this->GetPlatformToolsetString());
      } else {
        cmXMLElement(epg, "PlatformToolset")
          .Content(this->GetPlatformToolsetString());
      }
    }
    cmXMLElement(eprj, "Import")
      .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
    {
      cmXMLElement eidg(eprj, "ItemDefinitionGroup");
      cmXMLElement epbe(eidg, "PostBuildEvent");
      cmXMLElement(epbe, "Command")
        .Content("echo VCTargetsPath=$(VCTargetsPath)");
    }
    cmXMLElement(eprj, "Import")
      .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
  }

  std::vector<std::string> cmd;
  cmd.push_back(this->GetMSBuildCommand());
  cmd.push_back(vcxproj);
  cmd.emplace_back("/p:Configuration=Debug");
  cmd.emplace_back(cmStrCat("/p:Platform=", this->GetPlatformName()));
  cmd.emplace_back(cmStrCat("/p:VisualStudioVersion=", this->GetIDEVersion()));
  std::string out;
  int ret = 0;
  cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]");
  if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(),
                                       cmSystemTools::OUTPUT_NONE) ||
      ret != 0 || !regex.find(out)) {
    cmSystemTools::ReplaceString(out, "\n", "\n  ");
    std::ostringstream e;
    /* clang-format off */
    e <<
      "Failed to run MSBuild command:\n"
      "  " << cmd[0] << "\n"
      "to get the value of VCTargetsPath:\n"
      "  " << out << '\n'
      ;
    /* clang-format on */
    if (ret != 0) {
      e << "Exit code: " << ret << '\n';
    }
    mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }
  this->VCTargetsPath = regex.match(1);
  cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);

  {
    cmsys::ofstream fout(txt.c_str());
    fout << this->VCTargetsPath << '\n';
  }
  return true;
}

std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalVisualStudio10Generator::GenerateBuildCommand(
  std::string const& makeProgram, std::string const& projectName,
  std::string const& projectDir, std::vector<std::string> const& targetNames,
  std::string const& config, int jobs, bool verbose,
  cmBuildOptions buildOptions, std::vector<std::string> const& makeOptions,
  BuildTryCompile /*isInTryCompile*/)
{
  std::vector<GeneratedMakeCommand> makeCommands;
  // Select the caller- or user-preferred make program, else MSBuild.
  std::string makeProgramSelected =
    this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand());

  std::string const slnFile = this->GetSLNFile(projectDir, projectName);

  // Check if the caller explicitly requested a devenv tool.
  std::string makeProgramLower = makeProgramSelected;
  cmSystemTools::LowerCase(makeProgramLower);
  bool useDevEnv = (makeProgramLower.find("devenv") != std::string::npos ||
                    makeProgramLower.find("vcexpress") != std::string::npos);

  // Workaround to convince VCExpress.exe to produce output.
  bool const requiresOutputForward =
    (makeProgramLower.find("vcexpress") != std::string::npos);

  // MSBuild is preferred (and required for VS Express), but if the .sln has
  // an Intel Fortran .vfproj then we have to use devenv. Parse it to find out.
  cmSlnxParser slnxParser;
  cmSlnData slnData;
  if (this->Version >= VSVersion::VS18) {
    if (slnxParser.ParseFile(slnFile.c_str())) {
      for (auto const& i : slnxParser.ProjectToPath) {
        if (cmHasLiteralSuffix(i.second, ".vfproj")) {
          useDevEnv = true;
          break;
        }
      }
    }
  } else {
    cmVisualStudioSlnParser parser;
    if (parser.ParseFile(slnFile, slnData,
                         cmVisualStudioSlnParser::DataGroupAll)) {
      std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
      for (cmSlnProjectEntry const& project : slnProjects) {
        std::string proj = project.GetRelativePath();
        if (cmHasLiteralSuffix(proj, ".vfproj")) {
          useDevEnv = true;
          break;
        }
      }
    }
  }
  if (useDevEnv) {
    // Use devenv to build solutions containing Intel Fortran projects.
    return cmGlobalVisualStudio7Generator::GenerateBuildCommand(
      makeProgram, projectName, projectDir, targetNames, config, jobs, verbose,
      buildOptions, makeOptions);
  }

  std::vector<std::string> realTargetNames = targetNames;
  if (targetNames.empty() ||
      ((targetNames.size() == 1) && targetNames.front().empty())) {
    realTargetNames = { "ALL_BUILD" };
  }
  for (auto const& tname : realTargetNames) {
    // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug
    // /target:ALL_BUILD
    //                         /m
    if (tname.empty()) {
      continue;
    }

    GeneratedMakeCommand makeCommand;
    makeCommand.RequiresOutputForward = requiresOutputForward;
    makeCommand.Add(makeProgramSelected);

    if (tname == "clean"_s) {
      makeCommand.Add(slnFile);
      makeCommand.Add("/t:Clean");
    } else {
      std::string targetProject = cmStrCat(tname, ".vcxproj");
      if (targetProject.find('/') == std::string::npos) {
        // it might be in a subdir
        if (this->Version >= VSVersion::VS18) {
          auto i =
            slnxParser.ProjectToPath.find(cmSystemTools::LowerCase(tname));
          if (i != slnxParser.ProjectToPath.end()) {
            targetProject = i->second;
          }
        } else {
          if (cmSlnProjectEntry const* proj =
                slnData.GetProjectByName(tname)) {
            targetProject = proj->GetRelativePath();
            cmSystemTools::ConvertToUnixSlashes(targetProject);
          }
        }
      }
      makeCommand.Add(targetProject);

      // Check if we do need a restore at all (i.e. if there are package
      // references and restore has not been disabled by a command line option.
      PackageResolveMode restoreMode = buildOptions.ResolveMode;
      bool requiresRestore = true;

      if (restoreMode == PackageResolveMode::Disable) {
        requiresRestore = false;
      } else if (cmValue cached =
                   this->CMakeInstance->GetState()->GetCacheEntryValue(
                     cmStrCat(tname, "_REQUIRES_VS_PACKAGE_RESTORE"))) {
        requiresRestore = cached.IsOn();
      } else {
        // There are no package references defined.
        requiresRestore = false;
      }

      // If a restore is required, evaluate the restore mode.
      if (requiresRestore) {
        if (restoreMode == PackageResolveMode::OnlyResolve) {
          // Only invoke the restore target on the project.
          makeCommand.Add("/t:Restore");
        } else {
          // Invoke restore target, unless it has been explicitly disabled.
          bool restorePackages = true;

          if (this->Version < VSVersion::VS15) {
            // Package restore is only supported starting from Visual Studio
            // 2017. Package restore must be executed manually using NuGet
            // shell for older versions.
            this->CMakeInstance->IssueMessage(
              MessageType::WARNING,
              "Restoring package references is only supported for Visual "
              "Studio 2017 and later. You have to manually restore the "
              "packages using NuGet before building the project.");
            restorePackages = false;
          } else if (restoreMode == PackageResolveMode::Default) {
            // Decide if a restore is performed, based on a cache variable.
            if (cmValue cached =
                  this->CMakeInstance->GetState()->GetCacheEntryValue(
                    "CMAKE_VS_NUGET_PACKAGE_RESTORE")) {
              restorePackages = cached.IsOn();
            }
          }

          if (restorePackages) {
            if (this->IsMsBuildRestoreSupported()) {
              makeCommand.Add("/restore");
            } else {
              GeneratedMakeCommand restoreCommand;
              restoreCommand.Add(makeProgramSelected);
              restoreCommand.Add(targetProject);
              restoreCommand.Add("/t:Restore");
              makeCommands.emplace_back(restoreCommand);
            }
          }
        }
      }
    }

    makeCommand.Add(
      cmStrCat("/p:Configuration=", config.empty() ? "Debug" : config));
    makeCommand.Add(cmStrCat("/p:Platform=", this->GetPlatformName()));
    makeCommand.Add(
      cmStrCat("/p:VisualStudioVersion=", this->GetIDEVersion()));

    if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
      if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
        makeCommand.Add("/m");
      } else {
        makeCommand.Add(cmStrCat("/m:", jobs));
      }
    }

    // Respect the verbosity: 'n' normal will show build commands
    //                        'm' minimal only the build step's title
    makeCommand.Add(cmStrCat("/v:", ((verbose) ? 'n' : 'm')));
    makeCommand.Add(makeOptions.begin(), makeOptions.end());
    makeCommands.emplace_back(std::move(makeCommand));
  }
  return makeCommands;
}

std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
  std::string const& output) const
{
  // The VS 10 generator needs to create the .rule files on disk.
  // Hide them away under the CMakeFiles directory.
  cmCryptoHash hasher(cmCryptoHash::AlgoMD5);
  std::string ruleDir = cmStrCat(
    this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/",
    hasher.HashString(cmSystemTools::GetFilenamePath(output)));
  std::string ruleFile = cmStrCat(
    ruleDir, '/', cmSystemTools::GetFilenameNameView(output), ".rule");
  return ruleFile;
}

void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target,
                                                  cmSourceFile const* sf,
                                                  std::string const& sfRel)
{
  size_t len =
    (target->GetLocalGenerator()->GetCurrentBinaryDirectory().length() + 1 +
     sfRel.length());
  if (len > this->LongestSource.Length) {
    this->LongestSource.Length = len;
    this->LongestSource.Target = target;
    this->LongestSource.SourceFile = sf;
    this->LongestSource.SourceRel = sfRel;
  }
}

std::string cmGlobalVisualStudio10Generator::Encoding()
{
  return "utf-8";
}

char const* cmGlobalVisualStudio10Generator::GetToolsVersion() const
{
  switch (this->Version) {
    case cmGlobalVisualStudioGenerator::VSVersion::VS14:
      return "14.0";
    case cmGlobalVisualStudioGenerator::VSVersion::VS15:
      return "15.0";
    case cmGlobalVisualStudioGenerator::VSVersion::VS16:
      return "16.0";
    case cmGlobalVisualStudioGenerator::VSVersion::VS17:
      return "17.0";
    case cmGlobalVisualStudioGenerator::VSVersion::VS18:
      return "18.0";
  }
  return "";
}

bool cmGlobalVisualStudio10Generator::IsNsightTegra() const
{
  return !this->NsightTegraVersion.empty();
}

std::string cmGlobalVisualStudio10Generator::GetNsightTegraVersion() const
{
  return this->NsightTegraVersion;
}

std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion()
{
  std::string version;
  cmSystemTools::ReadRegistryValue(
    "HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;"
    "Version",
    version, cmSystemTools::KeyWOW64_32);
  return version;
}

std::string cmGlobalVisualStudio10Generator::GetApplicationTypeRevision() const
{
  if (this->GetSystemName() == "Android"_s) {
    return this->GetAndroidApplicationTypeRevision();
  }

  // Return the first two '.'-separated components of the Windows version.
  std::string::size_type end1 = this->SystemVersion.find('.');
  std::string::size_type end2 =
    end1 == std::string::npos ? end1 : this->SystemVersion.find('.', end1 + 1);
  return this->SystemVersion.substr(0, end2);
}

static std::string cmLoadFlagTableString(Json::Value entry, char const* field)
{
  if (entry.isMember(field)) {
    auto string = entry[field];
    if (string.isConvertibleTo(Json::ValueType::stringValue)) {
      return string.asString();
    }
  }
  return "";
}

static unsigned int cmLoadFlagTableSpecial(Json::Value entry,
                                           char const* field)
{
  unsigned int value = 0;
  if (entry.isMember(field)) {
    auto specials = entry[field];
    if (specials.isArray()) {
      for (auto const& special : specials) {
        std::string s = special.asString();
        if (s == "UserValue"_s) {
          value |= cmIDEFlagTable::UserValue;
        } else if (s == "UserIgnored"_s) {
          value |= cmIDEFlagTable::UserIgnored;
        } else if (s == "UserRequired"_s) {
          value |= cmIDEFlagTable::UserRequired;
        } else if (s == "Continue"_s) {
          value |= cmIDEFlagTable::Continue;
        } else if (s == "SemicolonAppendable"_s) {
          value |= cmIDEFlagTable::SemicolonAppendable;
        } else if (s == "UserFollowing"_s) {
          value |= cmIDEFlagTable::UserFollowing;
        } else if (s == "CaseInsensitive"_s) {
          value |= cmIDEFlagTable::CaseInsensitive;
        } else if (s == "SpaceAppendable"_s) {
          value |= cmIDEFlagTable::SpaceAppendable;
        } else if (s == "CommaAppendable"_s) {
          value |= cmIDEFlagTable::CommaAppendable;
        }
      }
    }
  }
  return value;
}

namespace {

cmIDEFlagTable const* cmLoadFlagTableJson(std::string const& flagJsonPath,
                                          cm::optional<std::string> vsVer)
{
  cmIDEFlagTable* ret = nullptr;
  auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath);
  if (savedFlagIterator != loadedFlagJsonFiles.end()) {
    ret = savedFlagIterator->second.data();
  } else {
    Json::Reader reader;
    cmsys::ifstream stream;

    stream.open(flagJsonPath.c_str(), std::ios_base::in);
    if (stream) {
      Json::Value flags;
      if (reader.parse(stream, flags, false) && flags.isArray()) {
        std::vector<cmIDEFlagTable> flagTable;
        for (auto const& flag : flags) {
          Json::Value const& vsminJson = flag["vsmin"];
          if (vsminJson.isString()) {
            std::string const& vsmin = vsminJson.asString();
            if (!vsmin.empty()) {
              if (!vsVer ||
                  cmSystemTools::VersionCompareGreater(vsmin, *vsVer)) {
                continue;
              }
            }
          }
          cmIDEFlagTable flagEntry;
          flagEntry.IDEName = cmLoadFlagTableString(flag, "name");
          flagEntry.commandFlag = cmLoadFlagTableString(flag, "switch");
          flagEntry.comment = cmLoadFlagTableString(flag, "comment");
          flagEntry.value = cmLoadFlagTableString(flag, "value");
          flagEntry.special = cmLoadFlagTableSpecial(flag, "flags");
          flagTable.push_back(flagEntry);
        }
        cmIDEFlagTable endFlag{ "", "", "", "", 0 };
        flagTable.push_back(endFlag);

        loadedFlagJsonFiles[flagJsonPath] = flagTable;
        ret = loadedFlagJsonFiles[flagJsonPath].data();
      }
    }
  }
  return ret;
}
}

cm::optional<std::string> cmGlobalVisualStudio10Generator::FindFlagTable(
  cm::string_view toolsetName, cm::string_view table) const
{
  if (!this->CustomFlagTableDir.empty()) {
    std::string customFlagTableFile =
      cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
               toolsetName, '_', table, ".json");
    if (cmSystemTools::FileExists(customFlagTableFile)) {
      return customFlagTableFile;
    }
    customFlagTableFile =
      cmStrCat(this->CustomFlagTableDir, '/', this->GetPlatformName(), '_',
               table, ".json");
    if (cmSystemTools::FileExists(customFlagTableFile)) {
      return customFlagTableFile;
    }
  }
  std::string fullPath =
    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/MSBuild/FlagTables/",
             toolsetName, '_', table, ".json");
  if (cmSystemTools::FileExists(fullPath)) {
    return fullPath;
  }
  return {};
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable(
  std::string const& toolSpecificName, std::string const& defaultName,
  std::string const& table) const
{
  cmMakefile* mf = this->GetCurrentMakefile();

  std::string filename;
  if (!toolSpecificName.empty()) {
    if (cm::optional<std::string> found =
          this->FindFlagTable(toolSpecificName, table)) {
      filename = std::move(*found);
    } else {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("JSON flag table for ", table,
                                " not found for toolset ", toolSpecificName));
      return nullptr;
    }
  } else {
    std::string const& genericName =
      this->CanonicalToolsetName(this->GetPlatformToolsetString());
    cm::optional<std::string> found = this->FindFlagTable(genericName, table);
    if (!found) {
      found = this->FindFlagTable(defaultName, table);
    }
    if (found) {
      filename = std::move(*found);
    } else {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("JSON flag table for ", table,
                                " not found for toolset ", genericName, ' ',
                                defaultName));
      return nullptr;
    }
  }

  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  if (cmIDEFlagTable const* ret = cmLoadFlagTableJson(filename, vsVer)) {
    return ret;
  }

  mf->IssueMessage(
    MessageType::FATAL_ERROR,
    cmStrCat("JSON flag table could not be loaded:\n  ", filename));
  return nullptr;
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const
{
  return LoadFlagTable(this->GetClFlagTableName(),
                       this->DefaultCLFlagTableName, "CL");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable()
  const
{
  return LoadFlagTable(this->GetCSharpFlagTableName(),
                       this->DefaultCSharpFlagTableName, "CSharp");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const
{
  return LoadFlagTable(this->GetRcFlagTableName(),
                       this->DefaultRCFlagTableName, "RC");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const
{
  return LoadFlagTable(this->GetLibFlagTableName(),
                       this->DefaultLibFlagTableName, "LIB");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
{
  return LoadFlagTable(this->GetLinkFlagTableName(),
                       this->DefaultLinkFlagTableName, "Link");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
{
  return LoadFlagTable(std::string(), this->DefaultCudaFlagTableName, "Cuda");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
  const
{
  return LoadFlagTable(std::string(), this->DefaultCudaHostFlagTableName,
                       "CudaHost");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMarmasmFlagTable()
  const
{
  return LoadFlagTable(std::string(), this->DefaultMarmasmFlagTableName,
                       "MARMASM");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
{
  return LoadFlagTable(this->GetMasmFlagTableName(),
                       this->DefaultMasmFlagTableName, "MASM");
}

cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
{
  return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM");
}

bool cmGlobalVisualStudio10Generator::IsMsBuildRestoreSupported() const
{
  if (this->Version >= VSVersion::VS16) {
    return true;
  }

  static std::string const vsVer15_7_5 = "15.7.27703.2042";
  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  return (vsVer &&
          cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer15_7_5));
}

bool cmGlobalVisualStudio10Generator::IsBuildInParallelSupported() const
{
  if (this->Version >= VSVersion::VS16) {
    return true;
  }

  static std::string const vsVer15_8_0 = "15.8.27705.0";
  cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
  return (vsVer &&
          cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer15_8_0));
}

bool cmGlobalVisualStudio10Generator::SupportsShortObjectNames() const
{
  return true;
}

std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if (toolset == "v142"_s) {
    return "v142";
  }
  if (toolset == "v141"_s) {
    return "v141";
  }
  if (useToolset == "v140"_s) {
    return "v140";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::GetCSharpFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if (useToolset == "v142"_s) {
    return "v142";
  }
  if (useToolset == "v141"_s) {
    return "v141";
  }
  if (useToolset == "v140"_s) {
    return "v140";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::GetRcFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if ((useToolset == "v140"_s) || (useToolset == "v141"_s) ||
      (useToolset == "v142"_s)) {
    return "v14";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::GetLibFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if ((useToolset == "v140"_s) || (useToolset == "v141"_s) ||
      (useToolset == "v142"_s)) {
    return "v14";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::GetLinkFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if (useToolset == "v142"_s) {
    return "v142";
  }
  if (useToolset == "v141"_s) {
    return "v141";
  }
  if (useToolset == "v140"_s) {
    return "v140";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::GetMasmFlagTableName() const
{
  std::string const& toolset = this->GetPlatformToolsetString();
  std::string const useToolset = this->CanonicalToolsetName(toolset);

  if ((useToolset == "v140"_s) || (useToolset == "v141"_s) ||
      (useToolset == "v142"_s)) {
    return "v14";
  }
  if (useToolset == "v120"_s) {
    return "v12";
  }
  if (useToolset == "v110"_s) {
    return "v11";
  }
  if (useToolset == "v100"_s) {
    return "v10";
  }
  return "";
}

std::string cmGlobalVisualStudio10Generator::CanonicalToolsetName(
  std::string const& toolset) const
{
  std::size_t length = toolset.length();

  if (cmHasLiteralSuffix(toolset, "_xp")) {
    length -= 3;
  }

  return toolset.substr(0, length);
}
