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

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iterator>
#include <set>
#include <sstream>

#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
#include <cmext/string_view>

#include "windows.h"
// include wincrypt.h after windows.h
#include <wincrypt.h>

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

#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio10Generator.h"
#include "cmGlobalVisualStudio7Generator.h"
#include "cmGlobalVisualStudioGenerator.h"
#include "cmLinkLineDeviceComputer.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmLocalVisualStudioGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPropertyMap.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
#include "cmSourceGroup.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmVisualStudioGeneratorOptions.h"

struct cmIDEFlagTable;

static void ConvertToWindowsSlash(std::string& s);

static std::string cmVS10EscapeXML(std::string arg)
{
  cmSystemTools::ReplaceString(arg, "&", "&amp;");
  cmSystemTools::ReplaceString(arg, "<", "&lt;");
  cmSystemTools::ReplaceString(arg, ">", "&gt;");
  return arg;
}

static std::string cmVS10EscapeAttr(std::string arg)
{
  cmSystemTools::ReplaceString(arg, "&", "&amp;");
  cmSystemTools::ReplaceString(arg, "<", "&lt;");
  cmSystemTools::ReplaceString(arg, ">", "&gt;");
  cmSystemTools::ReplaceString(arg, "\"", "&quot;");
  cmSystemTools::ReplaceString(arg, "\n", "&#10;");
  return arg;
}

struct cmVisualStudio10TargetGenerator::Elem
{
  std::ostream& S;
  int const Indent;
  bool HasElements = false;
  bool HasContent = false;
  std::string Tag;

  Elem(std::ostream& s, std::string tag)
    : S(s)
    , Indent(0)
    , Tag(std::move(tag))
  {
    this->StartElement();
  }
  Elem(Elem const&) = delete;
  Elem(Elem& par, cm::string_view tag)
    : S(par.S)
    , Indent(par.Indent + 1)
    , Tag(std::string(tag))
  {
    par.SetHasElements();
    this->StartElement();
  }
  void SetHasElements()
  {
    if (!HasElements) {
      this->S << '>';
      HasElements = true;
    }
  }
  std::ostream& WriteString(char const* line);
  void StartElement() { this->WriteString("<") << this->Tag; }
  void Element(cm::string_view tag, std::string val)
  {
    Elem(*this, tag).Content(std::move(val));
  }
  Elem& Attribute(char const* an, std::string av)
  {
    this->S << ' ' << an << "=\"" << cmVS10EscapeAttr(std::move(av)) << '"';
    return *this;
  }
  void Content(std::string val)
  {
    if (!this->HasContent) {
      this->S << '>';
      this->HasContent = true;
    }
    this->S << cmVS10EscapeXML(std::move(val));
  }
  ~Elem()
  {
    // Do not emit element which has not been started
    if (Tag.empty()) {
      return;
    }

    if (HasElements) {
      this->WriteString("</") << this->Tag << '>';
    } else if (HasContent) {
      this->S << "</" << this->Tag << '>';
    } else {
      this->S << " />";
    }
  }

  void WritePlatformConfigTag(std::string const& tag, std::string const& cond,
                              std::string const& content);
};

class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
{
public:
  using Elem = cmVisualStudio10TargetGenerator::Elem;
  cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
                         cmVS7FlagTable const* table,
                         cmVisualStudio10TargetGenerator* g = nullptr)
    : cmVisualStudioGeneratorOptions(lg, tool, table)
    , TargetGenerator(g)
  {
  }

  void OutputFlag(std::ostream& /*fout*/, int /*indent*/,
                  std::string const& tag, std::string const& content) override
  {
    if (!this->GetConfiguration().empty()) {
      // if there are configuration specific flags, then
      // use the configuration specific tag for PreprocessorDefinitions
      std::string const cond =
        this->TargetGenerator->CalcCondition(this->GetConfiguration());
      this->Parent->WritePlatformConfigTag(tag, cond, content);
    } else {
      this->Parent->Element(tag, content);
    }
  }

private:
  cmVisualStudio10TargetGenerator* const TargetGenerator;
  Elem* Parent = nullptr;
  friend cmVisualStudio10TargetGenerator::OptionsHelper;
};

struct cmVisualStudio10TargetGenerator::OptionsHelper
{
  cmVS10GeneratorOptions& O;
  OptionsHelper(cmVS10GeneratorOptions& o, Elem& e)
    : O(o)
  {
    O.Parent = &e;
  }
  ~OptionsHelper() { O.Parent = nullptr; }

  void OutputPreprocessorDefinitions(std::string const& lang)
  {
    O.OutputPreprocessorDefinitions(O.Parent->S, O.Parent->Indent + 1, lang);
  }
  void OutputAdditionalIncludeDirectories(std::string const& lang)
  {
    O.OutputAdditionalIncludeDirectories(O.Parent->S, O.Parent->Indent + 1,
                                         lang);
  }
  void OutputFlagMap() { O.OutputFlagMap(O.Parent->S, O.Parent->Indent + 1); }
  void PrependInheritedString(std::string const& key)
  {
    O.PrependInheritedString(key);
  }
};

static std::string cmVS10EscapeComment(std::string const& comment)
{
  // MSBuild takes the CDATA of a <Message></Message> element and just
  // does "echo $CDATA" with no escapes.  We must encode the string.
  // http://technet.microsoft.com/en-us/library/cc772462%28WS.10%29.aspx
  std::string echoable;
  for (char c : comment) {
    switch (c) {
      case '\r':
        break;
      case '\n':
        echoable += '\t';
        break;
      case '"': /* no break */
      case '|': /* no break */
      case '&': /* no break */
      case '<': /* no break */
      case '>': /* no break */
      case '^':
        echoable += '^'; /* no break */
        CM_FALLTHROUGH;
      default:
        echoable += c;
        break;
    }
  }
  return echoable;
}

static bool cmVS10IsTargetsFile(std::string const& path)
{
  std::string const ext = cmSystemTools::GetFilenameLastExtension(path);
  return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0;
}

static VsProjectType computeProjectType(cmGeneratorTarget const* t)
{
  if (t->IsCSharpOnly()) {
    return VsProjectType::csproj;
  }
  return VsProjectType::vcxproj;
}

static std::string computeProjectFileExtension(VsProjectType projectType)
{
  switch (projectType) {
    case VsProjectType::csproj:
      return ".csproj";
    case VsProjectType::proj:
      return ".proj";
    default:
      return ".vcxproj";
  }
}

static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
{
  return computeProjectFileExtension(computeProjectType(t));
}

cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
  cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
  : GeneratorTarget(target)
  , Makefile(target->Target->GetMakefile())
  , Platform(gg->GetPlatformName())
  , Name(target->GetName())
  , GUID(gg->GetGUID(this->Name))
  , GlobalGenerator(gg)
  , LocalGenerator(
      (cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
{
  this->Configurations =
    this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
  this->NsightTegra = gg->IsNsightTegra();
  this->Android = gg->TargetsAndroid();
  this->WindowsKernelMode = gg->TargetsWindowsKernelModeDriver();
  auto scanProp = target->GetProperty("CXX_SCAN_FOR_MODULES");
  for (auto const& config : this->Configurations) {
    if (scanProp.IsSet()) {
      this->ScanSourceForModuleDependencies[config] = scanProp.IsOn();
    } else {
      this->ScanSourceForModuleDependencies[config] =
        target->NeedCxxDyndep(config) ==
        cmGeneratorTarget::CxxModuleSupport::Enabled;
    }
  }
  for (unsigned int& version : this->NsightTegraVersion) {
    version = 0;
  }
  sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u",
         &this->NsightTegraVersion[0], &this->NsightTegraVersion[1],
         &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]);
  this->MSTools = !this->NsightTegra && !this->Android;
  this->DefaultArtifactDir = this->GeneratorTarget->GetSupportDirectory();
  this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
                         this->Makefile->GetCurrentBinaryDirectory());
  this->ClassifyAllConfigSources();
}

cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() = default;

std::string cmVisualStudio10TargetGenerator::CalcCondition(
  std::string const& config) const
{
  std::ostringstream oss;
  oss << "'$(Configuration)|$(Platform)'=='" << config << '|' << this->Platform
      << '\'';
  // handle special case for 32 bit C# targets
  if (this->ProjectType == VsProjectType::csproj &&
      this->Platform == "Win32"_s) {
    oss << " Or "
           "'$(Configuration)|$(Platform)'=='"
        << config
        << "|x86"
           "'";
  }
  return oss.str();
}

void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag(
  std::string const& tag, std::string const& cond, std::string const& content)
{
  Elem(*this, tag).Attribute("Condition", cond).Content(content);
}

std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
  char const* line)
{
  this->S << '\n';
  this->S.fill(' ');
  this->S.width(this->Indent * 2);
  // write an empty string to get the fill level indent to print
  this->S << "";
  this->S << line;
  return this->S;
}

#define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
#define VS10_CXX_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.props"
#define VS10_CXX_USER_PROPS                                                   \
  "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
#define VS10_CXX_TARGETS "$(VCTargetsPath)\\Microsoft.Cpp.targets"

#define VS10_CSharp_DEFAULT_PROPS                                             \
  "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props"
// This does not seem to exist by default, it's just provided for consistency
// in case users want to have default custom props for C# targets
#define VS10_CSharp_USER_PROPS                                                \
  "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props"
#define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"

#define VS10_CSharp_NETCF_TARGETS                                             \
  "$(MSBuildExtensionsPath)\\Microsoft\\$(TargetFrameworkIdentifier)\\"       \
  "$(TargetFrameworkTargetsVersion)\\Microsoft.$(TargetFrameworkIdentifier)"  \
  ".CSharp.targets"

void cmVisualStudio10TargetGenerator::Generate()
{
  if (this->GeneratorTarget->IsSynthetic()) {
    this->GeneratorTarget->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("Target \"", this->GeneratorTarget->GetName(),
               "\" contains C++ modules intended for BMI-only compilation. "
               "This is not yet supported by the Visual Studio generator."));
    return;
  }

  for (std::string const& config : this->Configurations) {
    this->GeneratorTarget->CheckCxxModuleStatus(config);
  }

  this->ProjectType = computeProjectType(this->GeneratorTarget);
  this->Managed = this->ProjectType == VsProjectType::csproj;
  std::string const ProjectFileExtension =
    computeProjectFileExtension(this->ProjectType);

  if (this->ProjectType == VsProjectType::csproj &&
      this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
    std::string message =
      cmStrCat("The C# target \"", this->GeneratorTarget->GetName(),
               "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
               "disabled in future). Make it a SHARED library instead.");
    this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
  }

  if (this->Android &&
      this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
      !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
    this->GlobalGenerator->AddAndroidExecutableWarning(this->Name);
  }

  // Tell the global generator the name of the project file
  this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
                                             this->Name);
  this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
                                             ProjectFileExtension);
  this->DotNetHintReferences.clear();
  this->AdditionalUsingDirectories.clear();
  if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
    if (!this->ComputeClOptions()) {
      return;
    }
    if (!this->ComputeRcOptions()) {
      return;
    }
    if (!this->ComputeCudaOptions()) {
      return;
    }
    if (!this->ComputeCudaLinkOptions()) {
      return;
    }
    if (!this->ComputeMarmasmOptions()) {
      return;
    }
    if (!this->ComputeMasmOptions()) {
      return;
    }
    if (!this->ComputeNasmOptions()) {
      return;
    }
    if (!this->ComputeLinkOptions()) {
      return;
    }
    if (!this->ComputeLibOptions()) {
      return;
    }
    for (std::string const& config : this->Configurations) {
      // Default character set if not populated above.
      this->CharSet.emplace(
        config,
        (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
         this->GlobalGenerator->TargetsWindowsPhone() ||
         this->GlobalGenerator->TargetsWindowsStore() ||
         this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
          ? MsvcCharSet::Unicode
          : MsvcCharSet::MultiByte);
    }
  }
  std::string path =
    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
             this->Name, ProjectFileExtension);
  cmGeneratedFileStream BuildFileStream(path);
  std::string const& PathToProjectFile = path;
  BuildFileStream.SetCopyIfDifferent(true);

  // Write the encoding header into the file
  char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
  BuildFileStream.write(magic, 3);

  if (this->ProjectType == VsProjectType::csproj &&
      this->GeneratorTarget->IsDotNetSdkTarget() &&
      this->GlobalGenerator->GetVersion() >=
        cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    this->WriteSdkStyleProjectFile(BuildFileStream);
  } else {
    this->WriteClassicMsBuildProjectFile(BuildFileStream);
  }

  if (BuildFileStream.Close()) {
    this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
  }

  // The groups are stored in a separate file for VS 10
  this->WriteGroups();

  // Update cache with project-specific entries.
  this->UpdateCache();
}

void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
  cmGeneratedFileStream& BuildFileStream)
{
  BuildFileStream << R"(<?xml version="1.0" encoding=")"
                  << this->GlobalGenerator->Encoding() << "\"?>";
  {
    Elem e0(BuildFileStream, "Project");
    e0.Attribute("DefaultTargets", "Build");
    char const* toolsVersion = this->GlobalGenerator->GetToolsVersion();
    e0.Attribute("ToolsVersion", toolsVersion);
    e0.Attribute("xmlns",
                 "http://schemas.microsoft.com/developer/msbuild/2003");

    if (this->NsightTegra) {
      Elem e1(e0, "PropertyGroup");
      e1.Attribute("Label", "NsightTegraProject");
      unsigned int const nsightTegraMajorVersion = this->NsightTegraVersion[0];
      unsigned int const nsightTegraMinorVersion = this->NsightTegraVersion[1];
      if (nsightTegraMajorVersion >= 2) {
        if (nsightTegraMajorVersion > 3 ||
            (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
          e1.Element("NsightTegraProjectRevisionNumber", "11");
        } else {
          // Nsight Tegra 2.0 uses project revision 9.
          e1.Element("NsightTegraProjectRevisionNumber", "9");
        }
        // Tell newer versions to upgrade silently when loading.
        e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
      } else {
        // Require Nsight Tegra 1.6 for JCompile support.
        e1.Element("NsightTegraProjectRevisionNumber", "7");
      }
    }

    if (char const* hostArch =
          this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
      Elem e1(e0, "PropertyGroup");
      e1.Element("PreferredToolArchitecture", hostArch);
    }

    // The ALL_BUILD, PACKAGE, and ZERO_CHECK projects transitively include
    // Microsoft.Common.CurrentVersion.targets which triggers Target
    // ResolveNugetPackageAssets when SDK-style targets are in the project.
    // However, these projects have no nuget packages to reference and the
    // build fails.
    // Setting ResolveNugetPackages to false skips this target and the build
    // succeeds.
    cm::string_view targetName{ this->GeneratorTarget->GetName() };
    if (targetName == "ALL_BUILD"_s || targetName == "PACKAGE"_s ||
        targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
      Elem e1(e0, "PropertyGroup");
      e1.Element("ResolveNugetPackages", "false");
    }

    if (this->ProjectType != VsProjectType::csproj) {
      this->WriteProjectConfigurations(e0);
    }

    {
      Elem e1(e0, "PropertyGroup");
      this->WriteCommonPropertyGroupGlobals(e1);

      if ((this->MSTools || this->Android) &&
          this->GeneratorTarget->IsInBuildSystem()) {
        this->WriteApplicationTypeSettings(e1);
        this->VerifyNecessaryFiles();
      }

      cmValue vsProjectName =
        this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
      cmValue vsLocalPath =
        this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
      cmValue vsProvider =
        this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");

      if (vsProjectName && vsLocalPath && vsProvider) {
        e1.Element("SccProjectName", *vsProjectName);
        e1.Element("SccLocalPath", *vsLocalPath);
        e1.Element("SccProvider", *vsProvider);

        cmValue vsAuxPath =
          this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
        if (vsAuxPath) {
          e1.Element("SccAuxPath", *vsAuxPath);
        }
      }

      if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
        e1.Element("WinMDAssembly", "true");
      }

      e1.Element("Platform", this->Platform);
      cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
      e1.Element("ProjectName", projLabel ? *projLabel : this->Name);
      {
        cm::optional<std::string> targetFramework;
        cm::optional<std::string> targetFrameworkVersion;
        cm::optional<std::string> targetFrameworkIdentifier;
        cm::optional<std::string> targetFrameworkTargetsVersion;
        if (cmValue tf =
              this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) {
          targetFramework = *tf;
        } else if (cmValue vstfVer = this->GeneratorTarget->GetProperty(
                     "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
          // FIXME: Someday, add a deprecation warning for VS_* property.
          targetFrameworkVersion = *vstfVer;
        } else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
                     "DOTNET_TARGET_FRAMEWORK_VERSION")) {
          targetFrameworkVersion = *tfVer;
        } else if (this->ProjectType == VsProjectType::csproj) {
          targetFrameworkVersion =
            this->GlobalGenerator->GetTargetFrameworkVersion();
        }
        if (this->ProjectType == VsProjectType::vcxproj &&
            this->GlobalGenerator->TargetsWindowsCE()) {
          e1.Element("EnableRedirectPlatform", "true");
          e1.Element("RedirectPlatformValue", this->Platform);
        }
        if (this->ProjectType == VsProjectType::csproj) {
          if (this->GlobalGenerator->TargetsWindowsCE()) {
            // FIXME: These target VS_TARGET_FRAMEWORK* target properties
            // are undocumented settings only ever supported for WinCE.
            // We need a better way to control these in general.
            if (cmValue tfId = this->GeneratorTarget->GetProperty(
                  "VS_TARGET_FRAMEWORK_IDENTIFIER")) {
              targetFrameworkIdentifier = *tfId;
            }
            if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty(
                  "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) {
              targetFrameworkTargetsVersion = *tfTargetsVer;
            }
          }
          if (!targetFrameworkIdentifier) {
            targetFrameworkIdentifier =
              this->GlobalGenerator->GetTargetFrameworkIdentifier();
          }
          if (!targetFrameworkTargetsVersion) {
            targetFrameworkTargetsVersion =
              this->GlobalGenerator->GetTargetFrameworkTargetsVersion();
          }
        }
        if (targetFramework) {
          if (targetFramework->find(';') != std::string::npos) {
            e1.Element("TargetFrameworks", *targetFramework);
          } else {
            e1.Element("TargetFramework", *targetFramework);
          }
        }
        if (targetFrameworkVersion) {
          e1.Element("TargetFrameworkVersion", *targetFrameworkVersion);
        }
        if (targetFrameworkIdentifier) {
          e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier);
        }
        if (targetFrameworkTargetsVersion) {
          e1.Element("TargetFrameworkTargetsVersion",
                     *targetFrameworkTargetsVersion);
        }
        if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
               .empty()) {
          e1.Element(
            "CudaToolkitCustomDir",
            cmStrCat(
              this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString(),
              this->GlobalGenerator
                ->GetPlatformToolsetCudaNvccSubdirString()));
        }
      }

      // Disable the project upgrade prompt that is displayed the first time a
      // project using an older toolset version is opened in a newer version of
      // the IDE.
      e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");

      if (char const* vcTargetsPath =
            this->GlobalGenerator->GetCustomVCTargetsPath()) {
        e1.Element("VCTargetsPath", vcTargetsPath);
      }

      if (this->Managed) {
        if (this->LocalGenerator->GetVersion() >=
            cmGlobalVisualStudioGenerator::VSVersion::VS17) {
          e1.Element("ManagedAssembly", "true");
        }
        std::string outputType;
        switch (this->GeneratorTarget->GetType()) {
          case cmStateEnums::OBJECT_LIBRARY:
          case cmStateEnums::STATIC_LIBRARY:
          case cmStateEnums::SHARED_LIBRARY:
            outputType = "Library";
            break;
          case cmStateEnums::MODULE_LIBRARY:
            outputType = "Module";
            break;
          case cmStateEnums::EXECUTABLE: {
            auto const win32 =
              this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
            if (win32.find("$<") != std::string::npos) {
              this->Makefile->IssueMessage(
                MessageType::FATAL_ERROR,
                cmStrCat(
                  "Target \"", this->GeneratorTarget->GetName(),
                  "\" has a generator expression in its WIN32_EXECUTABLE "
                  "property. This is not supported on managed executables."));
              return;
            }
            if (cmIsOn(win32)) {
              outputType = "WinExe";
            } else {
              outputType = "Exe";
            }
          } break;
          case cmStateEnums::UTILITY:
          case cmStateEnums::INTERFACE_LIBRARY:
          case cmStateEnums::GLOBAL_TARGET:
            outputType = "Utility";
            break;
          case cmStateEnums::UNKNOWN_LIBRARY:
            break;
        }
        e1.Element("OutputType", outputType);
        e1.Element("AppDesignerFolder", "Properties");
      }
    }

    cmValue startupObject =
      this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");

    if (startupObject && this->Managed) {
      Elem e1(e0, "PropertyGroup");
      e1.Element("StartupObject", *startupObject);
    }

    switch (this->ProjectType) {
      case VsProjectType::vcxproj: {
        Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
        std::string const& props =
          this->GlobalGenerator->GetPlatformToolsetVersionProps();
        if (!props.empty()) {
          Elem(e0, "Import").Attribute("Project", props);
        }
      } break;
      case VsProjectType::csproj:
        Elem(e0, "Import")
          .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
          .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
        break;
      default:
        break;
    }

    this->WriteProjectConfigurationValues(e0);

    if (this->ProjectType == VsProjectType::vcxproj) {
      Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
    }
    {
      Elem e1(e0, "ImportGroup");
      e1.Attribute("Label", "ExtensionSettings");
      e1.SetHasElements();

      if (this->GlobalGenerator->IsCudaEnabled()) {
        auto customDir =
          this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
        std::string cudaPath = customDir.empty()
          ? "$(VCTargetsPath)\\BuildCustomizations\\"
          : cmStrCat(customDir,
                     this->GlobalGenerator
                       ->GetPlatformToolsetCudaVSIntegrationSubdirString(),
                     R"(extras\visual_studio_integration\MSBuildExtensions\)");
        Elem(e1, "Import")
          .Attribute("Project",
                     cmStrCat(std::move(cudaPath), "CUDA ",
                              this->GlobalGenerator->GetPlatformToolsetCuda(),
                              ".props"));
      }
      if (this->GlobalGenerator->IsMarmasmEnabled()) {
        Elem(e1, "Import")
          .Attribute("Project",
                     "$(VCTargetsPath)\\BuildCustomizations\\marmasm.props");
      }
      if (this->GlobalGenerator->IsMasmEnabled()) {
        Elem(e1, "Import")
          .Attribute("Project",
                     "$(VCTargetsPath)\\BuildCustomizations\\masm.props");
      }
      if (this->GlobalGenerator->IsNasmEnabled()) {
        // Always search in the standard modules location.
        std::string propsTemplate =
          GetCMakeFilePath("Templates/MSBuild/nasm.props.in");

        std::string propsLocal =
          cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
        ConvertToWindowsSlash(propsLocal);
        this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
                                      true);
        Elem(e1, "Import").Attribute("Project", propsLocal);
      }
    }
    {
      Elem e1(e0, "ImportGroup");
      e1.Attribute("Label", "PropertySheets");
      std::string props;
      switch (this->ProjectType) {
        case VsProjectType::vcxproj:
          props = VS10_CXX_USER_PROPS;
          break;
        case VsProjectType::csproj:
          props = VS10_CSharp_USER_PROPS;
          break;
        default:
          break;
      }
      if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
        props = *p;
      }
      if (!props.empty()) {
        ConvertToWindowsSlash(props);
        Elem(e1, "Import")
          .Attribute("Project", props)
          .Attribute("Condition", cmStrCat("exists('", props, "')"))
          .Attribute("Label", "LocalAppDataPlatform");
      }

      this->WritePlatformExtensions(e1);
    }

    this->WriteDotNetDocumentationFile(e0);
    Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
    this->WriteWinRTPackageCertificateKeyFile(e0);
    this->WritePathAndIncrementalLinkOptions(e0);
    this->WritePublicProjectContentOptions(e0);
    this->WriteCEDebugProjectConfigurationValues(e0);
    this->WriteItemDefinitionGroups(e0);
    this->WriteCustomCommands(e0);
    this->WriteAllSources(e0);
    this->WriteDotNetReferences(e0);
    this->WriteFrameworkReferences(e0);
    this->WritePackageReferences(e0);
    this->WriteImports(e0);
    this->WriteEmbeddedResourceGroup(e0);
    this->WriteXamlFilesGroup(e0);
    this->WriteWinRTReferences(e0);
    this->WriteProjectReferences(e0);
    this->WriteSDKReferences(e0);
    switch (this->ProjectType) {
      case VsProjectType::vcxproj:
        Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
        break;
      case VsProjectType::csproj:
        if (this->GlobalGenerator->TargetsWindowsCE()) {
          Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS);
        } else {
          Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
        }
        break;
      default:
        break;
    }

    this->WriteTargetSpecificReferences(e0);
    {
      Elem e1(e0, "ImportGroup");
      e1.Attribute("Label", "ExtensionTargets");
      e1.SetHasElements();
      this->WriteTargetsFileReferences(e1);
      if (this->GlobalGenerator->IsCudaEnabled()) {
        auto customDir =
          this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
        std::string cudaPath = customDir.empty()
          ? "$(VCTargetsPath)\\BuildCustomizations\\"
          : cmStrCat(customDir,
                     this->GlobalGenerator
                       ->GetPlatformToolsetCudaVSIntegrationSubdirString(),
                     R"(extras\visual_studio_integration\MSBuildExtensions\)");
        Elem(e1, "Import")
          .Attribute("Project",
                     cmStrCat(std::move(cudaPath), "CUDA ",
                              this->GlobalGenerator->GetPlatformToolsetCuda(),
                              ".targets"));
      }
      if (this->GlobalGenerator->IsMarmasmEnabled()) {
        Elem(e1, "Import")
          .Attribute("Project",
                     "$(VCTargetsPath)\\BuildCustomizations\\marmasm.targets");
      }
      if (this->GlobalGenerator->IsMasmEnabled()) {
        Elem(e1, "Import")
          .Attribute("Project",
                     "$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
      }
      if (this->GlobalGenerator->IsNasmEnabled()) {
        std::string nasmTargets =
          GetCMakeFilePath("Templates/MSBuild/nasm.targets");
        Elem(e1, "Import").Attribute("Project", nasmTargets);
      }
    }
    if (this->ProjectType == VsProjectType::vcxproj &&
        this->HaveCustomCommandDepfile) {
      std::string depfileTargets =
        GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
      Elem(e0, "Import").Attribute("Project", depfileTargets);
    }
    if (this->ProjectType == VsProjectType::csproj) {
      for (std::string const& c : this->Configurations) {
        Elem e1(e0, "PropertyGroup");
        e1.Attribute("Condition",
                     cmStrCat("'$(Configuration)' == '", c, '\''));
        e1.SetHasElements();
        this->WriteEvents(e1, c);
      }
      // make sure custom commands are executed before build (if necessary)
      {
        Elem e1(e0, "PropertyGroup");
        std::ostringstream oss;
        oss << "\n";
        for (std::string const& i : this->CSharpCustomCommandNames) {
          oss << "      " << i << ";\n";
        }
        oss << "      "
               "$(BuildDependsOn)\n";
        e1.Element("BuildDependsOn", oss.str());
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
  cmGeneratedFileStream& BuildFileStream)
{
  if (this->ProjectType != VsProjectType::csproj ||
      !this->GeneratorTarget->IsDotNetSdkTarget()) {
    std::string message =
      cmStrCat("The target \"", this->GeneratorTarget->GetName(),
               "\" is not eligible for .Net SDK style project.");
    this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message);
    return;
  }

  Elem e0(BuildFileStream, "Project");
  e0.Attribute("Sdk", *this->GeneratorTarget->GetProperty("DOTNET_SDK"));

  {
    Elem e1(e0, "PropertyGroup");
    this->WriteCommonPropertyGroupGlobals(e1);

    e1.Element("Configurations", cmJoinStrings(this->Configurations, ";", ""));

    e1.Element("EnableDefaultItems", "false");
    // Disable the project upgrade prompt that is displayed the first time a
    // project using an older toolset version is opened in a newer version
    // of the IDE.
    e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
    e1.Element("ManagedAssembly", "true");

    cmValue targetFramework =
      this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
    if (targetFramework) {
      if (targetFramework->find(';') != std::string::npos) {
        e1.Element("TargetFrameworks", *targetFramework);
      } else {
        e1.Element("TargetFramework", *targetFramework);
        e1.Element("AppendTargetFrameworkToOutputPath", "false");
      }
    } else {
      e1.Element("TargetFramework", "net5.0");
      e1.Element("AppendTargetFrameworkToOutputPath", "false");
    }

    std::string outputType;
    switch (this->GeneratorTarget->GetType()) {
      case cmStateEnums::OBJECT_LIBRARY:
      case cmStateEnums::STATIC_LIBRARY:
      case cmStateEnums::MODULE_LIBRARY:
        this->Makefile->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("Target \"", this->GeneratorTarget->GetName(),
                   "\" is of a type not supported for managed binaries."));
        return;
      case cmStateEnums::SHARED_LIBRARY:
        outputType = "Library";
        break;
      case cmStateEnums::EXECUTABLE: {
        auto const win32 =
          this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
        if (win32.find("$<") != std::string::npos) {
          this->Makefile->IssueMessage(
            MessageType::FATAL_ERROR,
            cmStrCat("Target \"", this->GeneratorTarget->GetName(),
                     "\" has a generator expression in its WIN32_EXECUTABLE "
                     "property. This is not supported on managed "
                     "executables."));
          return;
        }
        if (cmIsOn(win32)) {
          outputType = "WinExe";
        } else {
          outputType = "Exe";
        }
      } break;
      case cmStateEnums::UTILITY:
      case cmStateEnums::INTERFACE_LIBRARY:
      case cmStateEnums::GLOBAL_TARGET:
        outputType = "Utility";
        break;
      case cmStateEnums::UNKNOWN_LIBRARY:
        break;
    }
    e1.Element("OutputType", outputType);

    cmValue startupObject =
      this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");
    if (startupObject) {
      e1.Element("StartupObject", *startupObject);
    }
  }

  for (std::string const& config : this->Configurations) {
    Elem e1(e0, "PropertyGroup");
    e1.Attribute("Condition",
                 cmStrCat("'$(Configuration)' == '", config, '\''));
    e1.SetHasElements();

    std::string outDir =
      cmStrCat(this->GeneratorTarget->GetDirectory(config), '/');
    ConvertToWindowsSlash(outDir);
    e1.Element("OutputPath", outDir);

    e1.Element("AssemblyName", GetAssemblyName(config));

    Options& o = *(this->ClOptions[config]);
    OptionsHelper oh(o, e1);
    oh.OutputFlagMap();
  }

  for (std::string const& config : this->Configurations) {
    this->WriteSdkStyleEvents(e0, config);
  }

  this->WriteDotNetDocumentationFile(e0);
  this->WriteCustomCommands(e0);
  this->WriteAllSources(e0);
  this->WriteEmbeddedResourceGroup(e0);
  this->WriteXamlFilesGroup(e0);
  this->WriteDotNetReferences(e0);
  this->WritePackageReferences(e0);
  this->WriteImports(e0);
  this->WriteProjectReferences(e0);
}

void cmVisualStudio10TargetGenerator::WriteCommonPropertyGroupGlobals(Elem& e1)
{
  e1.Attribute("Label", "Globals");
  e1.Element("ProjectGuid", cmStrCat('{', this->GUID, '}'));

  cmValue vsProjectTypes =
    this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
  if (vsProjectTypes) {
    char const* tagName = "ProjectTypes";
    if (this->ProjectType == VsProjectType::csproj) {
      tagName = "ProjectTypeGuids";
    }
    e1.Element(tagName, *vsProjectTypes);
  }

  cmValue vsGlobalKeyword =
    this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
  if (!vsGlobalKeyword) {
    if (this->GlobalGenerator->TargetsAndroid()) {
      e1.Element("Keyword", "Android");
    } else {
      e1.Element("Keyword", "Win32Proj");
    }
  } else {
    e1.Element("Keyword", *vsGlobalKeyword);
  }

  cmValue vsGlobalRootNamespace =
    this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
  if (vsGlobalRootNamespace) {
    e1.Element("RootNamespace", *vsGlobalRootNamespace);
  }

  std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
  for (std::string const& keyIt : keys) {
    static cm::string_view const prefix = "VS_GLOBAL_";
    if (!cmHasPrefix(keyIt, prefix)) {
      continue;
    }
    cm::string_view globalKey = cm::string_view(keyIt).substr(prefix.length());
    // Skip invalid or separately-handled properties.
    if (globalKey.empty() || globalKey == "PROJECT_TYPES"_s ||
        globalKey == "ROOTNAMESPACE"_s || globalKey == "KEYWORD"_s) {
      continue;
    }
    cmValue value = this->GeneratorTarget->GetProperty(keyIt);
    if (!value) {
      continue;
    }
    e1.Element(globalKey, *value);
  }
}

void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
{
  std::vector<std::string> packageReferences =
    this->GeneratorTarget->GetPackageReferences();

  if (!packageReferences.empty()) {
    Elem e1(e0, "ItemGroup");
    for (std::string const& ri : packageReferences) {
      size_t versionIndex = ri.find_last_of('_');
      if (versionIndex != std::string::npos) {
        Elem e2(e1, "PackageReference");
        e2.Attribute("Include", ri.substr(0, versionIndex));
        e2.Attribute("Version", ri.substr(versionIndex + 1));
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
{
  cmList references;
  if (cmValue vsDotNetReferences =
        this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
    references.assign(*vsDotNetReferences);
  }
  cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
  for (auto const& i : props.GetList()) {
    static cm::string_view const vsDnRef = "VS_DOTNET_REFERENCE_";
    if (cmHasPrefix(i.first, vsDnRef)) {
      std::string path = i.second;
      if (!cmsys::SystemTools::FileIsFullPath(path)) {
        path =
          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', path);
      }
      ConvertToWindowsSlash(path);
      this->DotNetHintReferences[""].emplace_back(
        DotNetHintReference(i.first.substr(vsDnRef.length()), path));
    }
  }
  if (!references.empty() || !this->DotNetHintReferences.empty()) {
    Elem e1(e0, "ItemGroup");
    for (auto const& ri : references) {
      // if the entry from VS_DOTNET_REFERENCES is an existing file, generate
      // a new hint-reference and name it from the filename
      if (cmsys::SystemTools::FileExists(ri, true)) {
        std::string name =
          cmsys::SystemTools::GetFilenameWithoutLastExtension(ri);
        std::string path = ri;
        ConvertToWindowsSlash(path);
        this->DotNetHintReferences[""].emplace_back(
          DotNetHintReference(name, path));
      } else {
        this->WriteDotNetReference(e1, ri, "", "");
      }
    }
    for (auto const& h : this->DotNetHintReferences) {
      // DotNetHintReferences is also populated from AddLibraries().
      // The configuration specific hint references are added there.
      for (auto const& i : h.second) {
        this->WriteDotNetReference(e1, i.first, i.second, h.first);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteDotNetReference(
  Elem& e1, std::string const& ref, std::string const& hint,
  std::string const& config)
{
  Elem e2(e1, "Reference");
  // If 'config' is not empty, the reference is only added for the given
  // configuration. This is used when referencing imported managed assemblies.
  // See also cmVisualStudio10TargetGenerator::AddLibraries().
  if (!config.empty()) {
    e2.Attribute("Condition", this->CalcCondition(config));
  }
  e2.Attribute("Include", ref);
  e2.Element("CopyLocalSatelliteAssemblies", "true");
  e2.Element("ReferenceOutputAssembly", "true");
  if (!hint.empty()) {
    char const* privateReference = "True";
    if (cmValue value = this->GeneratorTarget->GetProperty(
          "VS_DOTNET_REFERENCES_COPY_LOCAL")) {
      if (value.IsOff()) {
        privateReference = "False";
      }
    }
    e2.Element("Private", privateReference);
    e2.Element("HintPath", hint);
  }
  this->WriteDotNetReferenceCustomTags(e2, ref);
}

void cmVisualStudio10TargetGenerator::WriteFrameworkReferences(Elem& e0)
{
  cmList references;
  if (cmValue vsFrameworkReferences =
        this->GeneratorTarget->GetProperty("VS_FRAMEWORK_REFERENCES")) {
    references.assign(*vsFrameworkReferences);
  }

  Elem e1(e0, "ItemGroup");
  for (auto const& ref : references) {
    Elem e2(e1, "FrameworkReference");
    e2.Attribute("Include", ref);
  }
}

void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0)
{
  cmValue imports =
    this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT");
  if (imports) {
    cmList argsSplit{ *imports };
    for (auto& path : argsSplit) {
      if (!cmsys::SystemTools::FileIsFullPath(path)) {
        path =
          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', path);
      }
      ConvertToWindowsSlash(path);
      Elem e1(e0, "Import");
      e1.Attribute("Project", path);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
  Elem& e2, std::string const& ref)
{

  static std::string const refpropPrefix = "VS_DOTNET_REFERENCEPROP_";
  static std::string const refpropInfix = "_TAG_";
  std::string const refPropFullPrefix =
    cmStrCat(refpropPrefix, ref, refpropInfix);
  using CustomTags = std::map<std::string, std::string>;
  CustomTags tags;
  cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
  for (auto const& i : props.GetList()) {
    if (cmHasPrefix(i.first, refPropFullPrefix) && !i.second.empty()) {
      tags[i.first.substr(refPropFullPrefix.length())] = i.second;
    }
  }
  for (auto const& tag : tags) {
    e2.Element(tag.first, tag.second);
  }
}

void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0)
{
  std::string const& documentationFile =
    this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE");

  if (this->ProjectType == VsProjectType::csproj &&
      !documentationFile.empty()) {
    Elem e1(e0, "PropertyGroup");
    Elem e2(e1, "DocumentationFile");
    e2.Content(documentationFile);
  }
}

void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
{
  if (!this->ResxObjs.empty()) {
    Elem e1(e0, "ItemGroup");
    std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
    ConvertToWindowsSlash(srcDir);
    for (cmSourceFile const* oi : this->ResxObjs) {
      std::string obj = oi->GetFullPath();
      ConvertToWindowsSlash(obj);
      bool useRelativePath = false;
      if (this->ProjectType == VsProjectType::csproj && this->InSourceBuild) {
        // If we do an in-source build and the resource file is in a
        // subdirectory
        // of the .csproj file, we have to use relative pathnames, otherwise
        // visual studio does not show the file in the IDE. Sorry.
        if (cmHasPrefix(obj, srcDir)) {
          obj = this->ConvertPath(obj, true);
          ConvertToWindowsSlash(obj);
          useRelativePath = true;
        }
      }
      Elem e2(e1, "EmbeddedResource");
      e2.Attribute("Include", obj);

      if (this->ProjectType != VsProjectType::csproj) {
        std::string hFileName =
          cmStrCat(obj.substr(0, obj.find_last_of('.')), ".h");
        e2.Element("DependentUpon", hFileName);

        for (std::string const& c : this->Configurations) {
          std::string s;
          if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
              // Handle variant of VS_GLOBAL_<variable> for RootNamespace.
              this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
            s = "$(RootNamespace).";
          }
          s += "%(Filename).resources";
          e2.WritePlatformConfigTag("LogicalName", this->CalcCondition(c), s);
        }
      } else {
        std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
        ConvertToWindowsSlash(binDir);
        // If the resource was NOT added using a relative path (which should
        // be the default), we have to provide a link here
        if (!useRelativePath) {
          std::string link = this->GetCSharpSourceLink(oi);
          if (link.empty()) {
            link = cmsys::SystemTools::GetFilenameName(obj);
          }
          e2.Element("Link", link);
        }
        // Determine if this is a generated resource from a .Designer.cs file
        std::string designerResource = cmStrCat(
          cmSystemTools::GetFilenamePath(oi->GetFullPath()), '/',
          cmSystemTools::GetFilenameWithoutLastExtension(oi->GetFullPath()),
          ".Designer.cs");
        if (cmsys::SystemTools::FileExists(designerResource)) {
          std::string generator = "PublicResXFileCodeGenerator";
          if (cmValue g = oi->GetProperty("VS_RESOURCE_GENERATOR")) {
            generator = *g;
          }
          if (!generator.empty()) {
            e2.Element("Generator", generator);
            if (cmHasPrefix(designerResource, srcDir)) {
              designerResource.erase(0, srcDir.length());
            } else if (cmHasPrefix(designerResource, binDir)) {
              designerResource.erase(0, binDir.length());
            } else {
              designerResource =
                cmsys::SystemTools::GetFilenameName(designerResource);
            }
            ConvertToWindowsSlash(designerResource);
            e2.Element("LastGenOutput", designerResource);
          }
        }
        cmPropertyMap const& props = oi->GetProperties();
        for (std::string const& p : props.GetKeys()) {
          static cm::string_view const propNamePrefix = "VS_CSHARP_";
          if (cmHasPrefix(p, propNamePrefix)) {
            cm::string_view tagName =
              cm::string_view(p).substr(propNamePrefix.length());
            if (!tagName.empty()) {
              cmValue value = props.GetPropertyValue(p);
              if (cmNonempty(value)) {
                e2.Element(tagName, *value);
              }
            }
          }
        }
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
{
  if (!this->XamlObjs.empty()) {
    Elem e1(e0, "ItemGroup");
    for (cmSourceFile const* oi : this->XamlObjs) {
      std::string obj = oi->GetFullPath();
      std::string xamlType;
      cmValue xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
      if (xamlTypeProperty) {
        xamlType = *xamlTypeProperty;
      } else {
        xamlType = "Page";
      }

      Elem e2(e1, xamlType);
      this->WriteSource(e2, oi);
      e2.SetHasElements();
      e2.Element("SubType", "Designer");
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences(Elem& e0)
{
  if (this->MSTools) {
    if (this->GlobalGenerator->TargetsWindowsPhone() &&
        this->GlobalGenerator->GetSystemVersion() == "8.0"_s) {
      Elem(e0, "Import")
        .Attribute("Project",
                   "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
                   "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
                   "$(TargetPlatformVersion).targets");
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
{
  for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
    std::ostringstream oss;
    oss << "Exists('" << tac.File << "')";
    if (!tac.Configs.empty()) {
      oss << " And (";
      for (size_t j = 0; j < tac.Configs.size(); ++j) {
        if (j > 0) {
          oss << " Or ";
        }
        oss << "'$(Configuration)'=='" << tac.Configs[j] << '\'';
      }
      oss << ')';
    }

    Elem(e1, "Import")
      .Attribute("Project", tac.File)
      .Attribute("Condition", oss.str());
  }
}

void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
{
  cmList references;
  if (cmValue vsWinRTReferences =
        this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) {
    references.assign(*vsWinRTReferences);
  }

  if (this->GlobalGenerator->TargetsWindowsPhone() &&
      this->GlobalGenerator->GetSystemVersion() == "8.0"_s &&
      references.empty()) {
    references.push_back(std::string{ "platform.winmd" });
  }
  if (!references.empty()) {
    Elem e1(e0, "ItemGroup");
    for (auto const& ri : references) {
      Elem e2(e1, "Reference");
      e2.Attribute("Include", ri);
      e2.Element("IsWinMDFile", "true");
    }
  }
}

// ConfigurationType Application, Utility StaticLibrary DynamicLibrary

void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0)
{
  Elem e1(e0, "ItemGroup");
  e1.Attribute("Label", "ProjectConfigurations");
  for (std::string const& c : this->Configurations) {
    Elem e2(e1, "ProjectConfiguration");
    e2.Attribute("Include", cmStrCat(c, '|', this->Platform));
    e2.Element("Configuration", c);
    e2.Element("Platform", this->Platform);
  }
}

void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
{
  for (std::string const& c : this->Configurations) {
    Elem e1(e0, "PropertyGroup");
    e1.Attribute("Condition", this->CalcCondition(c));
    e1.Attribute("Label", "Configuration");

    if (this->ProjectType != VsProjectType::csproj) {
      std::string configType;
      if (cmValue vsConfigurationType =
            this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
        configType = cmGeneratorExpression::Evaluate(*vsConfigurationType,
                                                     this->LocalGenerator, c);
      } else {
        switch (this->GeneratorTarget->GetType()) {
          case cmStateEnums::SHARED_LIBRARY:
          case cmStateEnums::MODULE_LIBRARY:
            if (this->WindowsKernelMode) {
              configType = "Driver";
            } else {
              configType = "DynamicLibrary";
            }
            break;
          case cmStateEnums::OBJECT_LIBRARY:
          case cmStateEnums::STATIC_LIBRARY:
            configType = "StaticLibrary";
            break;
          case cmStateEnums::EXECUTABLE:
            if (this->NsightTegra &&
                !this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
              // Android executables are .so too.
              configType = "DynamicLibrary";
            } else if (this->Android) {
              configType = "DynamicLibrary";
            } else {
              configType = "Application";
            }
            break;
          case cmStateEnums::UTILITY:
          case cmStateEnums::INTERFACE_LIBRARY:
          case cmStateEnums::GLOBAL_TARGET:
            if (this->NsightTegra) {
              // Tegra-Android platform does not understand "Utility".
              configType = "StaticLibrary";
            } else {
              configType = "Utility";
            }
            break;
          case cmStateEnums::UNKNOWN_LIBRARY:
            break;
        }
      }
      e1.Element("ConfigurationType", configType);
    }

    if (this->MSTools) {
      if (!this->Managed) {
        this->WriteMSToolConfigurationValues(e1, c);
      } else {
        this->WriteMSToolConfigurationValuesManaged(e1, c);
      }
    } else if (this->NsightTegra) {
      this->WriteNsightTegraConfigurationValues(e1, c);
    } else if (this->Android) {
      this->WriteAndroidConfigurationValues(e1, c);
    }

    if (this->WindowsKernelMode) {
      this->WriteMSDriverConfigurationValues(e1, c);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues(
  Elem& e0)
{
  if (!this->GlobalGenerator->TargetsWindowsCE()) {
    return;
  }
  cmValue additionalFiles =
    this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
  cmValue remoteDirectory =
    this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
  if (!(additionalFiles || remoteDirectory)) {
    return;
  }
  for (std::string const& c : this->Configurations) {
    Elem e1(e0, "PropertyGroup");
    e1.Attribute("Condition", this->CalcCondition(c));

    if (remoteDirectory) {
      e1.Element("RemoteDirectory", *remoteDirectory);
    }
    if (additionalFiles) {
      e1.Element("CEAdditionalFiles", *additionalFiles);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
  Elem& e1, std::string const& config)
{
  cmValue mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
  if (mfcFlag) {
    std::string const mfcFlagValue =
      cmGeneratorExpression::Evaluate(*mfcFlag, this->LocalGenerator, config);

    std::string useOfMfcValue = "false";
    if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
      if (mfcFlagValue == "1"_s) {
        useOfMfcValue = "Static";
      } else if (mfcFlagValue == "2"_s) {
        useOfMfcValue = "Dynamic";
      }
    }
    e1.Element("UseOfMfc", useOfMfcValue);
  }

  if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
       this->CharSet[config] == MsvcCharSet::Unicode)) {
    e1.Element("CharacterSet", "Unicode");
  } else if (this->GeneratorTarget->GetType() <=
               cmStateEnums::OBJECT_LIBRARY &&
             this->CharSet[config] == MsvcCharSet::SingleByte) {
    e1.Element("CharacterSet", "NotSet");
  } else {
    e1.Element("CharacterSet", "MultiByte");
  }

  this->WriteMSToolConfigurationValuesCommon(e1, config);

  if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
      this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
    e1.Element("WindowsAppContainer", "true");
  }
  if (this->IPOEnabledConfigurations.count(config) > 0) {
    e1.Element("WholeProgramOptimization", "true");
  }
  if (this->ASanEnabledConfigurations.find(config) !=
      this->ASanEnabledConfigurations.end()) {
    e1.Element("EnableAsan", "true");
  }
  if (this->FuzzerEnabledConfigurations.find(config) !=
      this->FuzzerEnabledConfigurations.end()) {
    e1.Element("EnableFuzzer", "true");
  }
  {
    auto s = this->SpectreMitigation.find(config);
    if (s != this->SpectreMitigation.end()) {
      e1.Element("SpectreMitigation", s->second);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
  Elem& e1, std::string const& config)
{
  if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
    return;
  }

  Options& o = *(this->ClOptions[config]);

  if (o.UsingDebugInfo()) {
    e1.Element("DebugSymbols", "true");
    e1.Element("DefineDebug", "true");
  }

  std::string outDir =
    cmStrCat(this->GeneratorTarget->GetDirectory(config), '/');
  ConvertToWindowsSlash(outDir);
  e1.Element("OutputPath", outDir);

  if (o.HasFlag("Platform")) {
    e1.Element("PlatformTarget", o.GetFlag("Platform"));
    o.RemoveFlag("Platform");
  }

  this->WriteMSToolConfigurationValuesCommon(e1, config);

  std::string assemblyName = GetAssemblyName(config);
  e1.Element("AssemblyName", assemblyName);

  if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
    e1.Element("StartAction", "Program");
    e1.Element("StartProgram", cmStrCat(outDir, assemblyName, ".exe"));
  }

  OptionsHelper oh(o, e1);
  oh.OutputFlagMap();
}

void cmVisualStudio10TargetGenerator::WriteMSDriverConfigurationValues(
  Elem& e1, std::string const&)
{
  // FIXME: Introduce a way for project code to control these.
  e1.Element("DriverType", "KMDF");
  e1.Element("DriverTargetPlatform", "Universal");
}

void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesCommon(
  Elem& e1, std::string const& config)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  if (cmValue projectToolsetOverride =
        this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
    e1.Element("PlatformToolset", *projectToolsetOverride);
  } else if (char const* toolset = gg->GetPlatformToolset()) {
    e1.Element("PlatformToolset", toolset);
  }

  cm::optional<bool> maybeUseDebugLibraries;
  if (cmValue useDebugLibrariesProp =
        this->GeneratorTarget->GetProperty("VS_USE_DEBUG_LIBRARIES")) {
    // The project explicitly specified a value for this target.
    // An empty string suppresses generation of the setting altogether.
    std::string const useDebugLibraries = cmGeneratorExpression::Evaluate(
      *useDebugLibrariesProp, this->LocalGenerator, config);
    if (!useDebugLibraries.empty()) {
      maybeUseDebugLibraries = cmIsOn(useDebugLibraries);
    }
  } else if (this->GeneratorTarget->GetPolicyStatusCMP0162() ==
             cmPolicies::NEW) {
    // The project did not explicitly specify a value for this target.
    // If the target compiles sources for a known MSVC runtime library,
    // base our default value on that.
    if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
      maybeUseDebugLibraries = this->ClOptions[config]->UsingDebugRuntime();
    }
    // For other targets, such as UTILITY targets, base our default
    // on the configuration name.
    if (!maybeUseDebugLibraries) {
      maybeUseDebugLibraries = cmSystemTools::UpperCase(config) == "DEBUG"_s;
    }
  }
  if (maybeUseDebugLibraries) {
    if (*maybeUseDebugLibraries) {
      e1.Element("UseDebugLibraries", "true");
    } else {
      e1.Element("UseDebugLibraries", "false");
    }
  }
}

//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
  Elem& e1, std::string const&)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  char const* toolset = gg->GetPlatformToolset();
  e1.Element("NdkToolchainVersion", toolset ? toolset : "Default");
  if (cmValue minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
    e1.Element("AndroidMinAPI", cmStrCat("android-", *minApi));
  }
  if (cmValue api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
    e1.Element("AndroidTargetAPI", cmStrCat("android-", *api));
  }

  if (cmValue cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
    e1.Element("AndroidArch", *cpuArch);
  }

  if (cmValue stlType =
        this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
    e1.Element("AndroidStlType", *stlType);
  }
}

void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues(
  Elem& e1, std::string const&)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  if (cmValue projectToolsetOverride =
        this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
    e1.Element("PlatformToolset", *projectToolsetOverride);
  } else if (char const* toolset = gg->GetPlatformToolset()) {
    e1.Element("PlatformToolset", toolset);
  }
  if (cmValue stlType =
        this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
    if (*stlType != "none"_s) {
      e1.Element("UseOfStl", *stlType);
    }
  }
  std::string const& apiLevel = gg->GetSystemVersion();
  if (!apiLevel.empty()) {
    e1.Element("AndroidAPILevel", cmStrCat("android-", apiLevel));
  }
}

void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
{
  this->CSharpCustomCommandNames.clear();

  cmSourceFile const* srcCMakeLists =
    this->LocalGenerator->CreateVCProjBuildRule();

  for (cmGeneratorTarget::AllConfigSource const& si :
       this->GeneratorTarget->GetAllConfigSources()) {
    if (si.Source == srcCMakeLists) {
      // Skip explicit reference to CMakeLists.txt source.
      continue;
    }
    this->WriteCustomCommand(e0, si.Source);
  }

  // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
  if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET &&
      this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
    if (srcCMakeLists) {
      // Write directly rather than through WriteCustomCommand because
      // we do not want the de-duplication and it has no dependencies.
      if (cmCustomCommand const* command = srcCMakeLists->GetCustomCommand()) {
        this->WriteCustomRule(e0, srcCMakeLists, *command);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteCustomCommand(
  Elem& e0, cmSourceFile const* sf)
{
  if (this->LocalGenerator->GetSourcesVisited(this->GeneratorTarget)
        .insert(sf)
        .second) {
    if (std::vector<cmSourceFile*> const* depends =
          this->GeneratorTarget->GetSourceDepends(sf)) {
      for (cmSourceFile const* di : *depends) {
        this->WriteCustomCommand(e0, di);
      }
    }
    if (cmCustomCommand const* command = sf->GetCustomCommand()) {
      // C# projects write their <Target> within WriteCustomRule()
      this->WriteCustomRule(e0, sf, *command);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteCustomRule(
  Elem& e0, cmSourceFile const* source, cmCustomCommand const& command)
{
  std::string sourcePath = source->GetFullPath();
  // VS 10 will always rebuild a custom command attached to a .rule
  // file that doesn't exist so create the file explicitly.
  if (source->GetPropertyAsBool("__CMAKE_RULE")) {
    if (!cmSystemTools::FileExists(sourcePath)) {
      // Make sure the path exists for the file
      std::string path = cmSystemTools::GetFilenamePath(sourcePath);
      cmSystemTools::MakeDirectory(path);
      cmsys::ofstream fout(sourcePath.c_str());
      if (fout) {
        fout << "# generated from CMake\n";
        fout.flush();
        fout.close();
        // Force given file to have a very old timestamp, thus
        // preventing dependent rebuilds.
        this->ForceOld(sourcePath);
      } else {
        cmSystemTools::Error(cmStrCat("Could not create file: [", sourcePath,
                                      "]  ",
                                      cmSystemTools::GetLastSystemError()));
      }
    }
  }
  cmLocalVisualStudio7Generator* lg = this->LocalGenerator;

  std::unique_ptr<Elem> spe1;
  std::unique_ptr<Elem> spe2;
  if (this->ProjectType != VsProjectType::csproj) {
    spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
    spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
    this->WriteSource(*spe2, source);
    spe2->SetHasElements();
    if (command.GetStdPipesUTF8()) {
      this->WriteStdOutEncodingUtf8(*spe2);
    }
  } else {
    Elem e1(e0, "ItemGroup");
    Elem e2(e1, "None");
    this->WriteSource(e2, source);
    e2.SetHasElements();
  }
  for (std::string const& c : this->Configurations) {
    cmCustomCommandGenerator ccg(command, c, lg, true);
    std::string comment = lg->ConstructComment(ccg);
    comment = cmVS10EscapeComment(comment);
    std::string script = lg->ConstructScript(ccg);
    bool symbolic = false;
    // input files for custom command
    std::stringstream additional_inputs;
    {
      char const* sep = "";
      if (this->ProjectType == VsProjectType::csproj) {
        // csproj files do not attach the command to a specific file
        // so the primary input must be listed explicitly.
        additional_inputs << source->GetFullPath();
        sep = ";";
      }

      // Avoid listing an input more than once.
      std::set<std::string> unique_inputs;
      // The source is either implicit an input or has been added above.
      unique_inputs.insert(source->GetFullPath());

      for (std::string const& d : ccg.GetDepends()) {
        std::string dep;
        if (lg->GetRealDependency(d, c, dep)) {
          if (!unique_inputs.insert(dep).second) {
            // already listed
            continue;
          }
          ConvertToWindowsSlash(dep);
          additional_inputs << sep << dep;
          sep = ";";
          if (!symbolic) {
            if (cmSourceFile* sf = this->Makefile->GetSource(
                  dep, cmSourceFileLocationKind::Known)) {
              symbolic = sf->GetPropertyAsBool("SYMBOLIC");
            }
          }

          // Without UpToDateCheckInput VS will ignore the dependency files
          // when doing it's fast up-to-date check and the command will not run
          if (this->ProjectType == VsProjectType::csproj &&
              this->GeneratorTarget->IsDotNetSdkTarget()) {
            Elem e1(e0, "ItemGroup");
            Elem e2(e1, "UpToDateCheckInput");
            e2.Attribute("Include", dep);
          }
        }
      }
      if (this->ProjectType != VsProjectType::csproj) {
        additional_inputs << sep << "%(AdditionalInputs)";
      }
    }
    // output files for custom command
    std::stringstream outputs;
    {
      char const* sep = "";
      for (std::string const& o : ccg.GetOutputs()) {
        std::string out = o;
        ConvertToWindowsSlash(out);
        outputs << sep << out;
        sep = ";";
        if (!symbolic) {
          if (cmSourceFile* sf = this->Makefile->GetSource(
                o, cmSourceFileLocationKind::Known)) {
            symbolic = sf->GetPropertyAsBool("SYMBOLIC");
          }
        }
      }
    }
    script += lg->FinishConstructScript(this->ProjectType);
    if (this->ProjectType == VsProjectType::csproj) {
      cmCryptoHash hasher(cmCryptoHash::AlgoMD5);
      std::string name =
        cmStrCat("CustomCommand_", c, '_', hasher.HashString(sourcePath));
      this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
                                  outputs.str(), comment, ccg);
    } else {
      BuildInParallel buildInParallel = BuildInParallel::No;
      if (command.GetCMP0147Status() == cmPolicies::NEW &&
          !command.GetUsesTerminal() &&
          !(command.HasMainDependency() && source->GetIsGenerated()) &&
          !source->GetPropertyAsBool(
            "VS_CUSTOM_COMMAND_DISABLE_PARALLEL_BUILD")) {
        buildInParallel = BuildInParallel::Yes;
      }
      this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
                               outputs.str(), comment, ccg, symbolic,
                               buildInParallel);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
  Elem& e2, std::string const& config, std::string const& script,
  std::string const& additional_inputs, std::string const& outputs,
  std::string const& comment, cmCustomCommandGenerator const& ccg,
  bool symbolic, BuildInParallel buildInParallel)
{
  std::string const cond = this->CalcCondition(config);
  if (buildInParallel == BuildInParallel::Yes &&
      this->GlobalGenerator->IsBuildInParallelSupported()) {
    e2.WritePlatformConfigTag("BuildInParallel", cond, "true");
  }
  e2.WritePlatformConfigTag("Message", cond, comment);
  e2.WritePlatformConfigTag("Command", cond, script);
  e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
  e2.WritePlatformConfigTag("Outputs", cond, outputs);
  // Turn off linking of custom command outputs.
  e2.WritePlatformConfigTag("LinkObjects", cond, "false");
  if (symbolic &&
      this->LocalGenerator->GetVersion() >=
        cmGlobalVisualStudioGenerator::VSVersion::VS16) {
    // VS >= 16.4 warn if outputs are not created, but one of our
    // outputs is marked SYMBOLIC and not expected to be created.
    e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
  }

  std::string depfile = ccg.GetFullDepfile();
  if (!depfile.empty()) {
    this->HaveCustomCommandDepfile = true;
    std::string internal_depfile = ccg.GetInternalDepfile();
    ConvertToWindowsSlash(internal_depfile);
    e2.WritePlatformConfigTag("DepFileAdditionalInputsFile", cond,
                              internal_depfile);
  }
}

void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
  Elem& e0, std::string const& config, std::string const& name,
  std::string const& script, std::string const& inputs,
  std::string const& outputs, std::string const& comment,
  cmCustomCommandGenerator const& ccg)
{
  if (!ccg.GetFullDepfile().empty()) {
    this->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("CSharp target \"", this->GeneratorTarget->GetName(),
               "\" does not support add_custom_command DEPFILE."));
  }
  this->CSharpCustomCommandNames.insert(name);
  Elem e1(e0, "Target");
  e1.Attribute("Condition", cmStrCat("'$(Configuration)' == '", config, '\''));
  e1.S << "\n    Name=\"" << name << "\"";
  e1.S << "\n    Inputs=\"" << cmVS10EscapeAttr(inputs) << "\"";
  e1.S << "\n    Outputs=\"" << cmVS10EscapeAttr(outputs) << "\"";

  // Run before sources are compiled...
  e1.S << "\n    BeforeTargets=\"CoreCompile\""; // BeforeBuild
  // ...but after output directory has been created
  e1.S << "\n    DependsOnTargets=\"PrepareForBuild\"";

  if (!comment.empty()) {
    Elem(e1, "Exec").Attribute("Command", cmStrCat("echo ", comment));
  }
  Elem(e1, "Exec").Attribute("Command", script);
}

std::string cmVisualStudio10TargetGenerator::ConvertPath(
  std::string const& path, bool forceRelative)
{
  return forceRelative
    ? cmSystemTools::RelativePath(
        this->LocalGenerator->GetCurrentBinaryDirectory(), path)
    : path;
}

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

void cmVisualStudio10TargetGenerator::WriteGroups()
{
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }

  // collect up group information
  std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();

  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
    this->GeneratorTarget->GetAllConfigSources();

  std::set<cmSourceGroup const*> groupsUsed;
  for (cmGeneratorTarget::AllConfigSource const& si : sources) {
    std::string const& source = si.Source->GetFullPath();
    cmSourceGroup* sourceGroup =
      this->Makefile->FindSourceGroup(source, sourceGroups);
    groupsUsed.insert(sourceGroup);
  }

  if (cmSourceFile const* srcCMakeLists =
        this->LocalGenerator->CreateVCProjBuildRule()) {
    std::string const& source = srcCMakeLists->GetFullPath();
    cmSourceGroup* sourceGroup =
      this->Makefile->FindSourceGroup(source, sourceGroups);
    groupsUsed.insert(sourceGroup);
  }

  this->AddMissingSourceGroups(groupsUsed, sourceGroups);

  // Write out group file
  std::string path = cmStrCat(
    this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name,
    computeProjectFileExtension(this->GeneratorTarget), ".filters");
  cmGeneratedFileStream fout(path);
  fout.SetCopyIfDifferent(true);
  char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
  fout.write(magic, 3);

  fout << R"(<?xml version="1.0" encoding=")"
       << this->GlobalGenerator->Encoding() << "\"?>";
  {
    Elem e0(fout, "Project");
    e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
    e0.Attribute("xmlns",
                 "http://schemas.microsoft.com/developer/msbuild/2003");

    for (auto const& ti : this->Tools) {
      this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
    }

    // Added files are images and the manifest.
    if (!this->AddedFiles.empty()) {
      Elem e1(e0, "ItemGroup");
      e1.SetHasElements();
      for (std::string const& oi : this->AddedFiles) {
        std::string fileName =
          cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
        if (fileName == "wmappmanifest.xml"_s) {
          Elem e2(e1, "XML");
          e2.Attribute("Include", oi);
          e2.Element("Filter", "Resource Files");
        } else if (cmSystemTools::GetFilenameExtension(fileName) ==
                   ".appxmanifest") {
          Elem e2(e1, "AppxManifest");
          e2.Attribute("Include", oi);
          e2.Element("Filter", "Resource Files");
        } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx"_s) {
          Elem e2(e1, "None");
          e2.Attribute("Include", oi);
          e2.Element("Filter", "Resource Files");
        } else {
          Elem e2(e1, "Image");
          e2.Attribute("Include", oi);
          e2.Element("Filter", "Resource Files");
        }
      }
    }

    if (!this->ResxObjs.empty()) {
      Elem e1(e0, "ItemGroup");
      for (cmSourceFile const* oi : this->ResxObjs) {
        std::string obj = oi->GetFullPath();
        ConvertToWindowsSlash(obj);
        Elem e2(e1, "EmbeddedResource");
        e2.Attribute("Include", obj);
        e2.Element("Filter", "Resource Files");
      }
    }
    {
      Elem e1(e0, "ItemGroup");
      e1.SetHasElements();
      std::vector<cmSourceGroup const*> groupsVec(groupsUsed.begin(),
                                                  groupsUsed.end());
      std::sort(groupsVec.begin(), groupsVec.end(),
                [](cmSourceGroup const* l, cmSourceGroup const* r) {
                  return l->GetFullName() < r->GetFullName();
                });
      for (cmSourceGroup const* sg : groupsVec) {
        std::string const& name = sg->GetFullName();
        if (!name.empty()) {
          std::string guidName = cmStrCat("SG_Filter_", name);
          std::string guid = this->GlobalGenerator->GetGUID(guidName);
          Elem e2(e1, "Filter");
          e2.Attribute("Include", name);
          e2.Element("UniqueIdentifier", cmStrCat('{', guid, '}'));
        }
      }

      if (!this->ResxObjs.empty() || !this->AddedFiles.empty()) {
        std::string guidName = "SG_Filter_Resource Files";
        std::string guid = this->GlobalGenerator->GetGUID(guidName);
        Elem e2(e1, "Filter");
        e2.Attribute("Include", "Resource Files");
        e2.Element("UniqueIdentifier", cmStrCat('{', guid, '}'));
        e2.Element("Extensions",
                   "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
                   "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
      }
    }
    {
      if (cmValue p = this->GeneratorTarget->GetProperty("VS_FILTER_PROPS")) {
        auto props = *p;
        if (!props.empty()) {
          ConvertToWindowsSlash(props);
          Elem(e0, "Import")
            .Attribute("Project", props)
            .Attribute("Condition", cmStrCat("exists('", props, "')"))
            .Attribute("Label", "LocalAppDataPlatform");
        }
      }
    }
  }
  fout << '\n';

  if (fout.Close()) {
    this->GlobalGenerator->FileReplacedDuringGenerate(path);
  }
}

// Add to groupsUsed empty source groups that have non-empty children.
void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
  std::set<cmSourceGroup const*>& groupsUsed,
  std::vector<cmSourceGroup> const& allGroups)
{
  for (cmSourceGroup const& current : allGroups) {
    std::vector<cmSourceGroup> const& children = current.GetGroupChildren();
    if (children.empty()) {
      continue; // the group is really empty
    }

    this->AddMissingSourceGroups(groupsUsed, children);

    if (groupsUsed.count(&current) > 0) {
      continue; // group has already been added to set
    }

    // check if it least one of the group's descendants is not empty
    // (at least one child must already have been added)
    auto child_it = children.begin();
    while (child_it != children.end()) {
      if (groupsUsed.count(&(*child_it)) > 0) {
        break; // found a child that was already added => add current group too
      }
      child_it++;
    }

    if (child_it == children.end()) {
      continue; // no descendants have source files => ignore this group
    }

    groupsUsed.insert(&current);
  }
}

void cmVisualStudio10TargetGenerator::WriteGroupSources(
  Elem& e0, std::string const& name, ToolSources const& sources,
  std::vector<cmSourceGroup>& sourceGroups)
{
  Elem e1(e0, "ItemGroup");
  e1.SetHasElements();
  for (ToolSource const& s : sources) {
    cmSourceFile const* sf = s.SourceFile;
    std::string const& source = sf->GetFullPath();
    cmSourceGroup* sourceGroup =
      this->Makefile->FindSourceGroup(source, sourceGroups);
    std::string const& filter = sourceGroup->GetFullName();
    std::string path = this->ConvertPath(source, s.RelativePath);
    ConvertToWindowsSlash(path);
    Elem e2(e1, name);
    e2.Attribute("Include", path);
    if (!filter.empty()) {
      e2.Element("Filter", filter);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteHeaderSource(
  Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings)
{
  std::string const& fileName = sf->GetFullPath();
  Elem e2(e1, "ClInclude");
  this->WriteSource(e2, sf);
  if (this->IsResxHeader(fileName)) {
    e2.Element("FileType", "CppForm");
  } else if (this->IsXamlHeader(fileName)) {
    e2.Element("DependentUpon",
               fileName.substr(0, fileName.find_last_of('.')));
  }
  this->FinishWritingSource(e2, toolSettings);
}

void cmVisualStudio10TargetGenerator::ParseSettingsProperty(
  std::string const& settingsPropertyValue, ConfigToSettings& toolSettings)
{
  if (!settingsPropertyValue.empty()) {
    cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());

    std::unique_ptr<cmCompiledGeneratorExpression> cge =
      ge.Parse(settingsPropertyValue);

    for (std::string const& config : this->Configurations) {
      std::string evaluated = cge->Evaluate(this->LocalGenerator, config);

      cmList settings{ evaluated };
      for (auto const& setting : settings) {
        std::string::size_type const assignment = setting.find('=');
        if (assignment != std::string::npos) {
          std::string const propName = setting.substr(0, assignment);
          std::string const propValue = setting.substr(assignment + 1);

          if (!propValue.empty()) {
            toolSettings[config][propName] = propValue;
          }
        }
      }
    }
  }
}

bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs(
  ConfigToSettings const& toolSettings, std::string const& propName)
{
  std::string firstPropValue;
  for (auto const& configToSettings : toolSettings) {
    std::unordered_map<std::string, std::string> const& settings =
      configToSettings.second;

    if (firstPropValue.empty()) {
      if (settings.find(propName) != settings.end()) {
        firstPropValue = settings.find(propName)->second;
      }
    }

    if (settings.find(propName) == settings.end()) {
      return false;
    }

    if (settings.find(propName)->second != firstPropValue) {
      return false;
    }
  }

  return true;
}

void cmVisualStudio10TargetGenerator::WriteExtraSource(
  Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings)
{
  bool toolHasSettings = false;
  char const* tool = "None";
  std::string settingsGenerator;
  std::string settingsLastGenOutput;
  std::string sourceLink;
  std::string subType;
  std::string copyToOutDir;
  std::string includeInVsix;
  std::string ext = cmSystemTools::LowerCase(sf->GetExtension());

  if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
    toolHasSettings = true;
  }
  if (ext == "hlsl"_s) {
    tool = "FXCompile";
    // Figure out the type of shader compiler to use.
    if (cmValue st = sf->GetProperty("VS_SHADER_TYPE")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["ShaderType"] = *st;
      }
    }
    // Figure out which entry point to use if any
    if (cmValue se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["EntryPointName"] = *se;
      }
    }
    // Figure out which shader model to use if any
    if (cmValue sm = sf->GetProperty("VS_SHADER_MODEL")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["ShaderModel"] = *sm;
      }
    }
    // Figure out which output header file to use if any
    if (cmValue ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["HeaderFileOutput"] = *ohf;
      }
    }
    // Figure out which variable name to use if any
    if (cmValue vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["VariableName"] = *vn;
      }
    }
    // Figure out if there's any additional flags to use
    if (cmValue saf = sf->GetProperty("VS_SHADER_FLAGS")) {
      cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());
      std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf);

      for (std::string const& config : this->Configurations) {
        std::string evaluated = cge->Evaluate(this->LocalGenerator, config);

        if (!evaluated.empty()) {
          toolSettings[config]["AdditionalOptions"] = evaluated;
        }
      }
    }
    // Figure out if debug information should be generated
    if (cmValue sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
      cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());
      std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sed);

      for (std::string const& config : this->Configurations) {
        std::string evaluated = cge->Evaluate(this->LocalGenerator, config);

        if (!evaluated.empty()) {
          toolSettings[config]["EnableDebuggingInformation"] =
            cmIsOn(evaluated) ? "true" : "false";
        }
      }
    }
    // Figure out if optimizations should be disabled
    if (cmValue sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
      cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());
      std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sdo);

      for (std::string const& config : this->Configurations) {
        std::string evaluated = cge->Evaluate(this->LocalGenerator, config);

        if (!evaluated.empty()) {
          toolSettings[config]["DisableOptimizations"] =
            cmIsOn(evaluated) ? "true" : "false";
        }
      }
    }
    if (cmValue sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
      for (std::string const& config : this->Configurations) {
        toolSettings[config]["ObjectFileOutput"] = *sofn;
      }
    }
  } else if (ext == "jpg"_s || ext == "png"_s) {
    tool = "Image";
  } else if (ext == "resw"_s) {
    tool = "PRIResource";
  } else if (ext == "xml"_s) {
    tool = "XML";
  } else if (ext == "natvis"_s) {
    tool = "Natvis";
  } else if (ext == "settings"_s) {
    settingsLastGenOutput =
      cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
    std::size_t pos = settingsLastGenOutput.find(".settings");
    settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
    settingsGenerator = "SettingsSingleFileGenerator";
    toolHasSettings = true;
  } else if (ext == "vsixmanifest"_s) {
    subType = "Designer";
  }
  if (cmValue c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
    tool = "Content";
    copyToOutDir = *c;
    toolHasSettings = true;
  }
  if (sf->GetPropertyAsBool("VS_INCLUDE_IN_VSIX")) {
    includeInVsix = "True";
    tool = "Content";
    toolHasSettings = true;
  }

  // Collect VS_CSHARP_* property values (if some are set)
  std::map<std::string, std::string> sourceFileTags;
  this->GetCSharpSourceProperties(sf, sourceFileTags);

  if (this->NsightTegra) {
    // Nsight Tegra needs specific file types to check up-to-dateness.
    std::string name = cmSystemTools::LowerCase(sf->GetLocation().GetName());
    if (name == "androidmanifest.xml"_s || name == "build.xml"_s ||
        name == "proguard.cfg"_s || name == "proguard-project.txt"_s ||
        ext == "properties"_s) {
      tool = "AndroidBuild";
    } else if (ext == "java"_s) {
      tool = "JCompile";
    } else if (ext == "asm"_s || ext == "s"_s) {
      tool = "ClCompile";
    }
  }

  cmValue toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
  if (cmNonempty(toolOverride)) {
    tool = toolOverride->c_str();
  }

  std::string deployContent;
  std::string deployLocation;
  if (this->GlobalGenerator->TargetsWindowsPhone() ||
      this->GlobalGenerator->TargetsWindowsStore()) {
    cmValue content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
    if (cmNonempty(content)) {
      toolHasSettings = true;
      deployContent = *content;

      cmValue location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
      if (cmNonempty(location)) {
        deployLocation = *location;
      }
    }
  }

  if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) {
    cmValue toolTargetProperty = this->GeneratorTarget->Target->GetProperty(
      cmStrCat("VS_SOURCE_SETTINGS_", tool));
    ConfigToSettings toolTargetSettings;
    if (toolTargetProperty) {
      ParseSettingsProperty(*toolTargetProperty, toolTargetSettings);
    }

    ParsedToolTargetSettings[tool] = toolTargetSettings;
  }

  for (auto const& configToSetting : ParsedToolTargetSettings[tool]) {
    for (auto const& setting : configToSetting.second) {
      toolSettings[configToSetting.first][setting.first] = setting.second;
    }
  }

  if (!toolSettings.empty()) {
    toolHasSettings = true;
  }

  Elem e2(e1, tool);
  this->WriteSource(e2, sf);
  if (toolHasSettings) {
    e2.SetHasElements();

    this->FinishWritingSource(e2, toolSettings);

    if (!deployContent.empty()) {
      cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance());
      std::unique_ptr<cmCompiledGeneratorExpression> cge =
        ge.Parse(deployContent);
      // Deployment location cannot be set on a configuration basis
      if (!deployLocation.empty()) {
        e2.Element("Link",
                   cmStrCat(deployLocation, "\\%(FileName)%(Extension)"));
      }
      for (auto& config : this->Configurations) {
        if (cge->Evaluate(this->LocalGenerator, config) == "1"_s) {
          e2.WritePlatformConfigTag(
            "DeploymentContent",
            cmStrCat("'$(Configuration)|$(Platform)'=='", config, '|',
                     this->Platform, '\''),
            "true");
        } else {
          e2.WritePlatformConfigTag(
            "ExcludedFromBuild",
            cmStrCat("'$(Configuration)|$(Platform)'=='", config, '|',
                     this->Platform, '\''),
            "true");
        }
      }
    }

    if (!settingsGenerator.empty()) {
      e2.Element("Generator", settingsGenerator);
    }
    if (!settingsLastGenOutput.empty()) {
      e2.Element("LastGenOutput", settingsLastGenOutput);
    }
    if (!subType.empty()) {
      e2.Element("SubType", subType);
    }
    if (!copyToOutDir.empty()) {
      e2.Element("CopyToOutputDirectory", copyToOutDir);
    }
    if (!includeInVsix.empty()) {
      e2.Element("IncludeInVSIX", includeInVsix);
    }
    // write source file specific tags
    this->WriteCSharpSourceProperties(e2, sourceFileTags);
  }
}

void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
                                                  cmSourceFile const* sf)
{
  // Visual Studio tools append relative paths to the current dir, as in:
  //
  //  c:\path\to\current\dir\..\..\..\relative\path\to\source.c
  //
  // and fail if this exceeds the maximum allowed path length.  Our path
  // conversion uses full paths when possible to allow deeper trees.
  // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
  // we must use relative paths.
  bool forceRelative = sf->GetLanguage() == "CUDA"_s;
  std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
  ConvertToWindowsSlash(sourceFile);
  e2.Attribute("Include", sourceFile);

  if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
    // For out of source projects we have to provide a link (if not specified
    // via property) for every source file (besides .cs files) otherwise they
    // will not be visible in VS at all.
    // First we check if the file is in a source group, then we check if the
    // file path is relative to current source- or binary-dir, otherwise it is
    // added with the plain filename without any path. This means the file will
    // show up at root-level of the csproj (where CMakeLists.txt etc. are).
    std::string link = this->GetCSharpSourceLink(sf);
    if (link.empty()) {
      link = cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
    }
    e2.Element("Link", link);
  }

  ToolSource toolSource = { sf, forceRelative };
  this->Tools[e2.Tag].push_back(toolSource);
}

void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
{
  if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
    return;
  }

  bool const haveUnityBuild =
    this->GeneratorTarget->GetPropertyAsBool("UNITY_BUILD");

  if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
    Elem e1(e0, "PropertyGroup");
    e1.Element("EnableUnitySupport", "true");
  }

  Elem e1(e0, "ItemGroup");
  e1.SetHasElements();

  std::vector<size_t> all_configs;
  for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
    all_configs.push_back(ci);
  }

  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
    this->GeneratorTarget->GetAllConfigSources();

  cmSourceFile const* srcCMakeLists =
    this->LocalGenerator->CreateVCProjBuildRule();

  for (cmGeneratorTarget::AllConfigSource const& si : sources) {
    if (si.Source == srcCMakeLists) {
      // Skip explicit reference to CMakeLists.txt source.
      continue;
    }

    ConfigToSettings toolSettings;
    for (auto const& config : this->Configurations) {
      toolSettings[config];
    }
    if (cmValue p = si.Source->GetProperty("VS_SETTINGS")) {
      ParseSettingsProperty(*p, toolSettings);
    }

    char const* tool = nullptr;
    cmValue const toolOverride = si.Source->GetProperty("VS_TOOL_OVERRIDE");

    if (cmNonempty(toolOverride)) {
      // Custom tool specified: the file will be built in a user-defined way
      this->WriteExtraSource(e1, si.Source, toolSettings);
    } else {
      switch (si.Kind) {
        case cmGeneratorTarget::SourceKindAppManifest:
          tool = "AppxManifest";
          break;
        case cmGeneratorTarget::SourceKindCertificate:
          tool = "None";
          break;
        case cmGeneratorTarget::SourceKindCustomCommand:
          // Handled elsewhere.
          break;
        case cmGeneratorTarget::SourceKindExternalObject:
          tool = "Object";
          break;
        case cmGeneratorTarget::SourceKindExtra:
          this->WriteExtraSource(e1, si.Source, toolSettings);
          break;
        case cmGeneratorTarget::SourceKindHeader:
          this->WriteHeaderSource(e1, si.Source, toolSettings);
          break;
        case cmGeneratorTarget::SourceKindIDL:
          tool = "Midl";
          break;
        case cmGeneratorTarget::SourceKindManifest:
          // Handled elsewhere.
          break;
        case cmGeneratorTarget::SourceKindModuleDefinition:
          tool = "None";
          break;
        case cmGeneratorTarget::SourceKindCxxModuleSource:
        case cmGeneratorTarget::SourceKindUnityBatched:
        case cmGeneratorTarget::SourceKindObjectSource: {
          std::string const& lang = si.Source->GetLanguage();
          if (lang == "C"_s || lang == "CXX"_s) {
            tool = "ClCompile";
          } else if (lang == "ASM_MARMASM"_s &&
                     this->GlobalGenerator->IsMarmasmEnabled()) {
            tool = "MARMASM";
          } else if (lang == "ASM_MASM"_s &&
                     this->GlobalGenerator->IsMasmEnabled()) {
            tool = "MASM";
          } else if (lang == "ASM_NASM"_s &&
                     this->GlobalGenerator->IsNasmEnabled()) {
            tool = "NASM";
          } else if (lang == "RC"_s) {
            tool = "ResourceCompile";
          } else if (lang == "CSharp"_s) {
            tool = "Compile";
          } else if (lang == "CUDA"_s &&
                     this->GlobalGenerator->IsCudaEnabled()) {
            tool = "CudaCompile";
          } else {
            tool = "None";
          }
        } break;
        case cmGeneratorTarget::SourceKindResx:
          this->ResxObjs.push_back(si.Source);
          break;
        case cmGeneratorTarget::SourceKindXaml:
          this->XamlObjs.push_back(si.Source);
          break;
      }
    }

    std::string config;
    if (!this->Configurations.empty()) {
      config = this->Configurations[si.Configs[0]];
    }
    auto const* fs =
      this->GeneratorTarget->GetFileSetForSource(config, si.Source);
    if (tool) {
      // Compute set of configurations to exclude, if any.
      std::vector<size_t> const& include_configs = si.Configs;
      std::vector<size_t> exclude_configs;
      std::set_difference(all_configs.begin(), all_configs.end(),
                          include_configs.begin(), include_configs.end(),
                          std::back_inserter(exclude_configs));

      Elem e2(e1, tool);
      bool isCSharp = (si.Source->GetLanguage() == "CSharp"_s);
      if (isCSharp && !exclude_configs.empty()) {
        std::stringstream conditions;
        bool firstConditionSet{ false };
        for (auto const& ci : include_configs) {
          if (firstConditionSet) {
            conditions << " Or ";
          }
          conditions << "('$(Configuration)|$(Platform)'=='"
                     << this->Configurations[ci] << '|' << this->Platform
                     << "')";
          firstConditionSet = true;
        }
        e2.Attribute("Condition", conditions.str());
      }
      this->WriteSource(e2, si.Source);

      bool useNativeUnityBuild = false;
      if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
        // Magic value taken from cmGlobalVisualStudioVersionedGenerator.cxx
        static std::string const vs15 = "141";
        std::string toolset =
          this->GlobalGenerator->GetPlatformToolsetString();
        cmSystemTools::ReplaceString(toolset, "v", "");

        if (toolset.empty() ||
            cmSystemTools::VersionCompareGreaterEq(toolset, vs15)) {
          useNativeUnityBuild = true;
        }
      }

      if (haveUnityBuild && strcmp(tool, "ClCompile") == 0 &&
          si.Source->GetProperty("UNITY_SOURCE_FILE")) {
        if (useNativeUnityBuild) {
          e2.Attribute(
            "IncludeInUnityFile",
            si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")
              ? "false"
              : "true");
          e2.Attribute("CustomUnityFile", "true");

          std::string unityDir = cmSystemTools::GetFilenamePath(
            *si.Source->GetProperty("UNITY_SOURCE_FILE"));
          e2.Attribute("UnityFilesDirectory", unityDir);
        } else {
          // Visual Studio versions prior to 2017 15.8 do not know about unity
          // builds, thus we exclude the files already part of unity sources.
          if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
            exclude_configs = all_configs;
          }
        }
      }
      if (haveUnityBuild && strcmp(tool, "CudaCompile") == 0 &&
          si.Source->GetProperty("UNITY_SOURCE_FILE")) {
        if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
          exclude_configs = all_configs;
        }
      }

      if (si.Kind == cmGeneratorTarget::SourceKindObjectSource ||
          si.Kind == cmGeneratorTarget::SourceKindUnityBatched) {
        this->OutputSourceSpecificFlags(e2, si.Source);
      } else if (fs && fs->GetType() == "CXX_MODULES"_s) {
        this->GeneratorTarget->Makefile->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("Target \"", this->GeneratorTarget->GetName(),
                   "\" has source file\n  ", si.Source->GetFullPath(),
                   "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
                   "scheduled for compilation."));
      }
      if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
        e2.Element("PrecompiledHeader", "NotUsing");
      }
      if (!isCSharp && !exclude_configs.empty()) {
        this->WriteExcludeFromBuild(e2, exclude_configs);
      }

      std::string customObjectName;
      if (this->GlobalGenerator->UseShortObjectNames()) {
        customObjectName =
          this->LocalGenerator->GetShortObjectFileName(*si.Source);
      } else {
        customObjectName =
          this->LocalGenerator->GetCustomObjectFileName(*si.Source);
      }
      if (!customObjectName.empty()) {
        std::string outputName = "ObjectFileName";
        if (si.Source->GetLanguage() == "CUDA"_s) {
          outputName = "CompileOut";
        }
        e2.Element(outputName,
                   cmStrCat("$(IntDir)", customObjectName, ".obj"));
      }

      this->FinishWritingSource(e2, toolSettings);
    } else if (fs && fs->GetType() == "CXX_MODULES"_s) {
      this->GeneratorTarget->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Target \"", this->GeneratorTarget->GetName(),
                 "\" has source file\n  ", si.Source->GetFullPath(),
                 "\nin a \"FILE_SET TYPE CXX_MODULES\" but it is not "
                 "scheduled for compilation."));
    }
  }

  if (this->IsMissingFiles) {
    this->WriteMissingFiles(e1);
  }
}

void cmVisualStudio10TargetGenerator::FinishWritingSource(
  Elem& e2, ConfigToSettings const& toolSettings)
{
  std::vector<std::string> writtenSettings;
  for (auto const& configSettings : toolSettings) {
    for (auto const& setting : configSettings.second) {

      if (std::find(writtenSettings.begin(), writtenSettings.end(),
                    setting.first) != writtenSettings.end()) {
        continue;
      }

      if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) {
        e2.Element(setting.first, setting.second);
        writtenSettings.push_back(setting.first);
      } else {
        e2.WritePlatformConfigTag(setting.first,
                                  cmStrCat("'$(Configuration)|$(Platform)'=='",
                                           configSettings.first, '|',
                                           this->Platform, '\''),
                                  setting.second);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
  Elem& e2, cmSourceFile const* source)
{
  cmSourceFile const& sf = *source;

  std::string objectName;
  if (this->GeneratorTarget->HasExplicitObjectName(&sf)) {
    objectName = this->GeneratorTarget->GetObjectName(&sf);
  }
  std::string flags;
  bool configDependentFlags = false;
  std::string options;
  bool configDependentOptions = false;
  std::string defines;
  bool configDependentDefines = false;
  std::string includes;
  bool configDependentIncludes = false;
  if (cmValue cflags = sf.GetProperty("COMPILE_FLAGS")) {
    configDependentFlags =
      cmGeneratorExpression::Find(*cflags) != std::string::npos;
    flags += *cflags;
  }
  if (cmValue coptions = sf.GetProperty("COMPILE_OPTIONS")) {
    configDependentOptions =
      cmGeneratorExpression::Find(*coptions) != std::string::npos;
    options += *coptions;
  }
  if (cmValue cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
    configDependentDefines =
      cmGeneratorExpression::Find(*cdefs) != std::string::npos;
    defines += *cdefs;
  }
  if (cmValue cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
    configDependentIncludes =
      cmGeneratorExpression::Find(*cincludes) != std::string::npos;
    includes += *cincludes;
  }

  // Force language if the file extension does not match.
  // Note that MSVC treats the upper-case '.C' extension as C and not C++.
  std::string const ext = sf.GetExtension();
  std::string const extLang = ext == "C"_s
    ? "C"
    : this->GlobalGenerator->GetLanguageFromExtension(ext.c_str());
  std::string lang = this->LocalGenerator->GetSourceFileLanguage(sf);
  char const* compileAs = nullptr;
  if (lang != extLang) {
    if (lang == "CXX"_s) {
      // force a C++ file type
      compileAs = "CompileAsCpp";
    } else if (lang == "C"_s) {
      // force to c
      compileAs = "CompileAsC";
    }
  }

  bool noWinRT = this->TargetCompileAsWinRT && lang == "C"_s;
  // for the first time we need a new line if there is something
  // produced here.
  if (!objectName.empty()) {
    if (lang == "CUDA"_s) {
      e2.Element("CompileOut", cmStrCat("$(IntDir)/", objectName));
    } else {
      e2.Element("ObjectFileName", cmStrCat("$(IntDir)/", objectName));
    }
  }

  if (lang == "ASM_NASM"_s) {
    if (cmValue objectDeps = sf.GetProperty("OBJECT_DEPENDS")) {
      cmList depends{ *objectDeps };
      for (auto& d : depends) {
        ConvertToWindowsSlash(d);
      }
      e2.Element("AdditionalDependencies", depends.join(";"));
    }
  }

  bool isCppModule = false;

  for (std::string const& config : this->Configurations) {
    this->GeneratorTarget->NeedCxxModuleSupport(lang, config);

    std::string configUpper = cmSystemTools::UpperCase(config);
    std::string configDefines = defines;
    std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
    if (cmValue ccdefs = sf.GetProperty(defPropName)) {
      if (!configDefines.empty()) {
        configDefines += ';';
      }
      configDependentDefines |=
        cmGeneratorExpression::Find(*ccdefs) != std::string::npos;
      configDefines += *ccdefs;
    }

    bool const shouldScanForModules = lang == "CXX"_s &&
      this->GeneratorTarget->NeedDyndepForSource(lang, config, source);
    auto const* fs =
      this->GeneratorTarget->GetFileSetForSource(config, source);
    char const* compileAsPerConfig = compileAs;
    if (fs && fs->GetType() == "CXX_MODULES"_s) {
      if (lang == "CXX"_s) {
        if (fs->GetType() == "CXX_MODULES"_s) {
          isCppModule = true;
          if (shouldScanForModules &&
              this->GlobalGenerator->IsScanDependenciesSupported()) {
            // ScanSourceForModuleDependencies uses 'cl /scanDependencies' and
            // can distinguish module interface units and internal partitions.
            compileAsPerConfig = "CompileAsCpp";
          } else {
            compileAsPerConfig = "CompileAsCppModule";
          }
        } else {
          compileAsPerConfig = "CompileAsHeaderUnit";
        }
      } else {
        this->Makefile->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat(
            "Target \"", this->GeneratorTarget->Target->GetName(),
            "\" contains the source\n  ", source->GetFullPath(),
            "\nin a file set of type \"", fs->GetType(),
            R"(" but the source is not classified as a "CXX" source.)"));
      }
    }

    // We have pch state in the following situation:
    // 1. We have SKIP_PRECOMPILE_HEADERS == true
    // 2. We are creating the pre-compiled header
    // 3. We are a different language than the linker language AND pch is
    //    enabled.
    std::string const& linkLanguage =
      this->GeneratorTarget->GetLinkerLanguage(config);
    std::string const& pchSource =
      this->GeneratorTarget->GetPchSource(config, lang);
    bool const skipPCH =
      pchSource.empty() || sf.GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS");
    bool const makePCH = (sf.GetFullPath() == pchSource);
    bool const useSharedPCH = !skipPCH && (lang == linkLanguage);
    bool const useDifferentLangPCH = !skipPCH && (lang != linkLanguage);
    bool const useNoPCH = skipPCH && (lang != linkLanguage) &&
      !this->GeneratorTarget->GetPchHeader(config, linkLanguage).empty();
    bool const needsPCHFlags =
      (makePCH || useSharedPCH || useDifferentLangPCH || useNoPCH);

    // if we have flags or defines for this config then
    // use them
    if (!flags.empty() || !options.empty() || !configDefines.empty() ||
        !includes.empty() || compileAsPerConfig || noWinRT ||
        !options.empty() || needsPCHFlags ||
        (shouldScanForModules !=
         this->ScanSourceForModuleDependencies[config])) {
      cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
      cmIDEFlagTable const* flagtable = nullptr;
      std::string const& srclang = source->GetLanguage();
      if (srclang == "C"_s || srclang == "CXX"_s) {
        flagtable = gg->GetClFlagTable();
      } else if (srclang == "ASM_MARMASM"_s &&
                 this->GlobalGenerator->IsMarmasmEnabled()) {
        flagtable = gg->GetMarmasmFlagTable();
      } else if (srclang == "ASM_MASM"_s &&
                 this->GlobalGenerator->IsMasmEnabled()) {
        flagtable = gg->GetMasmFlagTable();
      } else if (lang == "ASM_NASM"_s &&
                 this->GlobalGenerator->IsNasmEnabled()) {
        flagtable = gg->GetNasmFlagTable();
      } else if (srclang == "RC"_s) {
        flagtable = gg->GetRcFlagTable();
      } else if (srclang == "CSharp"_s) {
        flagtable = gg->GetCSharpFlagTable();
      }
      cmGeneratorExpressionInterpreter genexInterpreter(
        this->LocalGenerator, config, this->GeneratorTarget, lang);
      cmVS10GeneratorOptions clOptions(
        this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
        flagtable, this);
      if (compileAsPerConfig) {
        clOptions.AddFlag("CompileAs", compileAsPerConfig);
      }
      if (shouldScanForModules !=
          this->ScanSourceForModuleDependencies[config]) {
        clOptions.AddFlag("ScanSourceForModuleDependencies",
                          shouldScanForModules ? "true" : "false");
      }
      if (noWinRT) {
        clOptions.AddFlag("CompileAsWinRT", "false");
      }
      if (configDependentFlags) {
        clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS"));
      } else {
        clOptions.Parse(flags);
      }

      if (needsPCHFlags) {
        // Add precompile headers compile options.
        if (makePCH) {
          clOptions.AddFlag("PrecompiledHeader", "Create");
          std::string pchHeader =
            this->GeneratorTarget->GetPchHeader(config, lang);
          clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
          std::string pchFile =
            this->GeneratorTarget->GetPchFile(config, lang);
          clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
          clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
        } else if (useNoPCH) {
          clOptions.AddFlag("PrecompiledHeader", "NotUsing");
        } else if (useSharedPCH) {
          std::string pchHeader =
            this->GeneratorTarget->GetPchHeader(config, lang);
          clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
        } else if (useDifferentLangPCH) {
          clOptions.AddFlag("PrecompiledHeader", "Use");
          std::string pchHeader =
            this->GeneratorTarget->GetPchHeader(config, lang);
          clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
          std::string pchFile =
            this->GeneratorTarget->GetPchFile(config, lang);
          clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
          clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
        }
      }

      if (!options.empty()) {
        std::string expandedOptions;
        if (configDependentOptions) {
          this->LocalGenerator->AppendCompileOptions(
            expandedOptions,
            genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
        } else {
          this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
        }
        clOptions.Parse(expandedOptions);
      }
      if (clOptions.HasFlag("DisableSpecificWarnings")) {
        clOptions.AppendFlag("DisableSpecificWarnings",
                             "%(DisableSpecificWarnings)");
      }
      if (clOptions.HasFlag("ForcedIncludeFiles")) {
        clOptions.AppendFlag("ForcedIncludeFiles", "%(ForcedIncludeFiles)");
      }
      if (configDependentDefines) {
        clOptions.AddDefines(
          genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
      } else {
        clOptions.AddDefines(configDefines);
      }
      std::vector<std::string> includeList;
      if (configDependentIncludes) {
        this->LocalGenerator->AppendIncludeDirectories(
          includeList,
          genexInterpreter.Evaluate(includes, "INCLUDE_DIRECTORIES"), *source);
      } else {
        this->LocalGenerator->AppendIncludeDirectories(includeList, includes,
                                                       *source);
      }
      clOptions.AddIncludes(includeList);
      clOptions.SetConfiguration(config);
      OptionsHelper oh(clOptions, e2);
      oh.PrependInheritedString("AdditionalOptions");
      oh.OutputAdditionalIncludeDirectories(lang);
      oh.OutputFlagMap();
      oh.OutputPreprocessorDefinitions(lang);
    }
  }

  if (isCppModule && !objectName.empty()) {
    std::string baseName = cmStrCat("$(IntDir)/", objectName);
    cmStripSuffixIfExists(baseName, ".obj");
    e2.Element("ModuleOutputFile", cmStrCat(baseName, ".ifc"));
    e2.Element("ModuleDependenciesFile", cmStrCat(baseName, ".module.json"));
  }

  if (this->IsXamlSource(source->GetFullPath())) {
    std::string const& fileName = source->GetFullPath();
    e2.Element("DependentUpon",
               fileName.substr(0, fileName.find_last_of('.')));
  }
  if (this->ProjectType == VsProjectType::csproj) {
    using CsPropMap = std::map<std::string, std::string>;
    CsPropMap sourceFileTags;
    this->GetCSharpSourceProperties(&sf, sourceFileTags);
    // write source file specific tags
    if (!sourceFileTags.empty()) {
      this->WriteCSharpSourceProperties(e2, sourceFileTags);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
  Elem& e2, std::vector<size_t> const& exclude_configs)
{
  for (size_t ci : exclude_configs) {
    e2.WritePlatformConfigTag("ExcludedFromBuild",
                              cmStrCat("'$(Configuration)|$(Platform)'=='",
                                       this->Configurations[ci], '|',
                                       this->Platform, '\''),
                              "true");
  }
}

void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
  Elem& e0)
{
  cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
  if (ttype > cmStateEnums::INTERFACE_LIBRARY) {
    return;
  }
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }

  Elem e1(e0, "PropertyGroup");
  e1.Element("_ProjectFileVersion", "10.0.20506.1");
  for (std::string const& config : this->Configurations) {
    std::string const cond = this->CalcCondition(config);

    std::string fullIntermediateDir =
      cmStrCat(this->GeneratorTarget->GetSupportDirectory(), '/', config, '/');
    cmSystemTools::MakeDirectory(fullIntermediateDir);
    std::string intermediateDir =
      this->LocalGenerator->MaybeRelativeToCurBinDir(fullIntermediateDir);
    ConvertToWindowsSlash(intermediateDir);

    if (ttype >= cmStateEnums::UTILITY) {
      if (this->GlobalGenerator->UseShortObjectNames()) {
        e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
      } else {
        e1.WritePlatformConfigTag(
          "IntDir", cond, R"($(Platform)\$(Configuration)\$(ProjectName)\)");
      }
    } else {
      if (ttype == cmStateEnums::SHARED_LIBRARY ||
          ttype == cmStateEnums::MODULE_LIBRARY ||
          ttype == cmStateEnums::EXECUTABLE) {
        auto linker = this->GeneratorTarget->GetLinkerTool(config);
        if (!linker.empty()) {
          ConvertToWindowsSlash(linker);
          e1.WritePlatformConfigTag("LinkToolExe", cond, linker);
        }
      }

      std::string outDir;
      std::string targetNameFull;
      if (ttype == cmStateEnums::OBJECT_LIBRARY) {
        outDir = intermediateDir;
        targetNameFull = cmStrCat(this->GeneratorTarget->GetName(), ".lib");
      } else {
        outDir = cmStrCat(this->GeneratorTarget->GetDirectory(config), '/');
        targetNameFull = this->GeneratorTarget->GetFullName(config);
      }
      ConvertToWindowsSlash(outDir);

      e1.WritePlatformConfigTag("OutDir", cond, outDir);

      e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);

      if (cmValue sdkExecutableDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
        e1.WritePlatformConfigTag("ExecutablePath", cond,
                                  *sdkExecutableDirectories);
      }

      if (cmValue sdkIncludeDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
        e1.WritePlatformConfigTag("IncludePath", cond, *sdkIncludeDirectories);
      }

      if (cmValue sdkReferenceDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
        e1.WritePlatformConfigTag("ReferencePath", cond,
                                  *sdkReferenceDirectories);
      }

      if (cmValue sdkLibraryDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
        e1.WritePlatformConfigTag("LibraryPath", cond, *sdkLibraryDirectories);
      }

      if (cmValue sdkLibraryWDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
        e1.WritePlatformConfigTag("LibraryWPath", cond,
                                  *sdkLibraryWDirectories);
      }

      if (cmValue sdkSourceDirectories =
            this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
        e1.WritePlatformConfigTag("SourcePath", cond, *sdkSourceDirectories);
      }

      if (cmValue sdkExcludeDirectories = this->Makefile->GetDefinition(
            "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
        e1.WritePlatformConfigTag("ExcludePath", cond, *sdkExcludeDirectories);
      }

      std::string name =
        cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
      e1.WritePlatformConfigTag("TargetName", cond, name);

      std::string ext =
        cmSystemTools::GetFilenameLastExtension(targetNameFull);
      if (ext.empty()) {
        // An empty TargetExt causes a default extension to be used.
        // A single "." appears to be treated as an empty extension.
        ext = ".";
      }
      e1.WritePlatformConfigTag("TargetExt", cond, ext);

      this->OutputLinkIncremental(e1, config);
    }

    if (ttype <= cmStateEnums::UTILITY) {
      if (cmValue workingDir =
            this->GlobalGenerator->GetDebuggerWorkingDirectory(
              this->GeneratorTarget)) {
        std::string genWorkingDir = cmGeneratorExpression::Evaluate(
          *workingDir, this->LocalGenerator, config);
        e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
                                  genWorkingDir);
      }

      if (cmValue environment =
            this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
        std::string genEnvironment = cmGeneratorExpression::Evaluate(
          *environment, this->LocalGenerator, config);
        e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
                                  genEnvironment);
      }

      if (cmValue debuggerCommand =
            this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
        std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
          *debuggerCommand, this->LocalGenerator, config);
        e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
                                  genDebuggerCommand);
      }

      if (cmValue commandArguments = this->GeneratorTarget->GetProperty(
            "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
        std::string genCommandArguments = cmGeneratorExpression::Evaluate(
          *commandArguments, this->LocalGenerator, config);
        e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
                                  genCommandArguments);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WritePublicProjectContentOptions(
  Elem& e0)
{
  cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
  if (ttype != cmStateEnums::SHARED_LIBRARY) {
    return;
  }
  if (this->ProjectType != VsProjectType::vcxproj) {
    return;
  }

  Elem e1(e0, "PropertyGroup");
  for (std::string const& config : this->Configurations) {
    if (this->GeneratorTarget->HaveCxx20ModuleSources() &&
        this->GeneratorTarget->HaveCxxModuleSupport(config) ==
          cmGeneratorTarget::Cxx20SupportLevel::Supported) {
      std::string const cond = this->CalcCondition(config);
      // For DLL projects, we export all BMIs for now
      e1.WritePlatformConfigTag("AllProjectBMIsArePublic", cond, "true");
    }
  }
}

void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools) {
    return;
  }
  if (this->WindowsKernelMode) {
    return;
  }
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }

  // static libraries and things greater than modules do not need
  // to set this option
  if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
      this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
    return;
  }
  Options& linkOptions = *(this->LinkOptions[configName]);
  std::string const cond = this->CalcCondition(configName);

  if (this->IPOEnabledConfigurations.count(configName) > 0) {
    // Suppress LinkIncremental in favor of WholeProgramOptimization.
    e1.WritePlatformConfigTag("LinkIncremental", cond, "");
  } else {
    char const* incremental = linkOptions.GetFlag("LinkIncremental");
    e1.WritePlatformConfigTag("LinkIncremental", cond,
                              (incremental ? incremental : "true"));
  }
  linkOptions.RemoveFlag("LinkIncremental");

  char const* manifest = linkOptions.GetFlag("GenerateManifest");
  e1.WritePlatformConfigTag("GenerateManifest", cond,
                            (manifest ? manifest : "true"));
  linkOptions.RemoveFlag("GenerateManifest");

  // Some link options belong here.  Use them now and remove them so that
  // WriteLinkOptions does not use them.
  static std::vector<std::string> const flags{ "LinkDelaySign",
                                               "LinkKeyFile" };
  for (std::string const& flag : flags) {
    if (char const* value = linkOptions.GetFlag(flag)) {
      e1.WritePlatformConfigTag(flag, cond, value);
      linkOptions.RemoveFlag(flag);
    }
  }
}

std::vector<std::string> cmVisualStudio10TargetGenerator::GetIncludes(
  std::string const& config, std::string const& lang) const
{
  std::vector<std::string> includes;
  this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
                                              lang, config);
  for (std::string& i : includes) {
    ConvertToWindowsSlash(i);
  }
  return includes;
}

std::string cmVisualStudio10TargetGenerator::GetTargetOutputName() const
{
  std::string config;
  if (!this->Configurations.empty()) {
    config = this->Configurations[0];
  }
  auto const& nameComponents =
    this->GeneratorTarget->GetFullNameComponents(config);
  return cmStrCat(nameComponents.prefix, nameComponents.base);
}

std::string cmVisualStudio10TargetGenerator::GetAssemblyName(
  std::string const& config) const
{
  std::string postfixName =
    cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
  std::string assemblyName = this->GeneratorTarget->GetOutputName(
    config, cmStateEnums::RuntimeBinaryArtifact);
  if (cmValue postfix = this->GeneratorTarget->GetProperty(postfixName)) {
    assemblyName += *postfix;
  }
  return assemblyName;
}

bool cmVisualStudio10TargetGenerator::ComputeClOptions()
{
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeClOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeClOptions(
  std::string const& configName)
{
  // much of this was copied from here:
  // copied from cmLocalVisualStudio7Generator.cxx 805
  // TODO: Integrate code below with cmLocalVisualStudio7Generator.

  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  std::unique_ptr<Options> pOptions;
  switch (this->ProjectType) {
    case VsProjectType::vcxproj:
      pOptions = cm::make_unique<Options>(
        this->LocalGenerator, Options::Compiler, gg->GetClFlagTable());
      break;
    case VsProjectType::csproj:
      pOptions =
        cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler,
                                 gg->GetCSharpFlagTable());
      break;
    default:
      break;
  }
  Options& clOptions = *pOptions;

  std::string flags;
  std::string const& linkLanguage =
    this->GeneratorTarget->GetLinkerLanguage(configName);
  if (linkLanguage.empty()) {
    cmSystemTools::Error(cmStrCat(
      "CMake can not determine linker language for target: ", this->Name));
    return false;
  }

  // Choose a language whose flags to use for ClCompile.
  static char const* clLangs[] = { "CXX", "C", "Fortran" };
  std::string langForClCompile;
  if (this->ProjectType == VsProjectType::csproj) {
    langForClCompile = "CSharp";
  } else if (cm::contains(clLangs, linkLanguage)) {
    langForClCompile = linkLanguage;
  } else {
    std::set<std::string> languages;
    this->GeneratorTarget->GetLanguages(languages, configName);
    for (char const* l : clLangs) {
      if (languages.count(l)) {
        langForClCompile = l;
        break;
      }
    }
  }
  this->LangForClCompile = langForClCompile;
  if (!langForClCompile.empty()) {
    this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
                                           cmBuildStep::Compile,
                                           langForClCompile, configName);
    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
                                            langForClCompile, configName);
  }
  bool const isCXXwithC = [this, &configName]() -> bool {
    if (this->LangForClCompile != "CXX"_s) {
      return false;
    }
    std::set<std::string> languages;
    this->GeneratorTarget->GetLanguages(languages, configName);
    return languages.find("C") != languages.end();
  }();

  // Put the IPO enabled configurations into a set.
  if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) {
    this->IPOEnabledConfigurations.insert(configName);
  }

  // Check if ASan is enabled.
  if (flags.find("/fsanitize=address") != std::string::npos ||
      flags.find("-fsanitize=address") != std::string::npos) {
    this->ASanEnabledConfigurations.insert(configName);
  }

  // Check if (lib)Fuzzer is enabled.
  if (flags.find("/fsanitize=fuzzer") != std::string::npos ||
      flags.find("-fsanitize=fuzzer") != std::string::npos) {
    this->FuzzerEnabledConfigurations.insert(configName);
  }

  // Precompile Headers
  std::string pchHeader =
    this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
  if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
      pchHeader.empty()) {
    clOptions.AddFlag("PrecompiledHeader", "NotUsing");
  } else if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
             !pchHeader.empty()) {
    clOptions.AddFlag("PrecompiledHeader", "Use");
    clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
    std::string pchFile =
      this->GeneratorTarget->GetPchFile(configName, linkLanguage);
    clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
  }

  // Get preprocessor definitions for this directory.
  std::string defineFlags = this->Makefile->GetDefineFlags();
  if (this->MSTools) {
    if (this->ProjectType == VsProjectType::vcxproj) {
      clOptions.FixExceptionHandlingDefault();
      if (this->GlobalGenerator->GetVersion() >=
          cmGlobalVisualStudioGenerator::VSVersion::VS15) {
        // Toolsets that come with VS 2017 may now enable UseFullPaths
        // by default and there is no negative /FC option that projects
        // can use to switch it back.  Older toolsets disable this by
        // default anyway so this will not hurt them.  If the project
        // is using an explicit /FC option then parsing flags will
        // replace this setting with "true" below.
        clOptions.AddFlag("UseFullPaths", "false");
      }
      clOptions.AddFlag("AssemblerListingLocation", "$(IntDir)");
    }
  }

  // check for managed C++ assembly compiler flag. This overrides any
  // /clr* compiler flags which may be defined in the flags variable(s).
  if (this->ProjectType != VsProjectType::csproj) {
    // Warn if /clr was added manually. This should not be done
    // anymore, because cmGeneratorTarget may not be aware that the
    // target uses C++/CLI.
    if (flags.find("/clr") != std::string::npos ||
        flags.find("-clr") != std::string::npos ||
        defineFlags.find("/clr") != std::string::npos ||
        defineFlags.find("-clr") != std::string::npos) {
      if (configName == this->Configurations[0]) {
        std::string message =
          cmStrCat("For the target \"", this->GeneratorTarget->GetName(),
                   "\" the /clr compiler flag was added manually. "
                   "Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME "
                   "target property.");
        this->Makefile->IssueMessage(MessageType::WARNING, message);
      }
    }
    if (cmValue clr =
          this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
      std::string clrString = *clr;
      if (!clrString.empty()) {
        clrString = cmStrCat(':', clrString);
      }
      flags += cmStrCat(" /clr", clrString);
    }
  }

  // Get includes for this target
  if (!this->LangForClCompile.empty()) {
    auto includeList = this->GetIncludes(configName, this->LangForClCompile);

    auto sysIncludeFlag = this->Makefile->GetDefinition(
      cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile));

    if (sysIncludeFlag) {
      bool gotOneSys = false;
      for (auto i : includeList) {
        cmSystemTools::ConvertToUnixSlashes(i);
        if (this->GeneratorTarget->IsSystemIncludeDirectory(
              i, configName, this->LangForClCompile)) {
          auto flag = cmTrimWhitespace(*sysIncludeFlag);
          if (this->MSTools) {
            cmSystemTools::ReplaceString(flag, "-external:I", "/external:I");
          }
          clOptions.AppendFlagString("AdditionalOptions",
                                     cmStrCat(flag, " \"", i, '"'));
          gotOneSys = true;
        } else {
          clOptions.AddInclude(i);
        }
      }

      if (gotOneSys) {
        if (auto sysIncludeFlagWarning = this->Makefile->GetDefinition(
              cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", this->LangForClCompile,
                       "_WARNING"))) {
          flags = cmStrCat(flags, ' ', *sysIncludeFlagWarning);
        }
      }
    } else {
      clOptions.AddIncludes(includeList);
    }
  }

  if (isCXXwithC) {
    // Modules/Compiler/Clang.cmake has a special case for clang-cl versions
    // that do not have a -std:c++23 flag to pass the standard through to the
    // underlying clang directly.  Unfortunately that flag applies to all
    // sources in a single .vcxproj file, so if we have C sources too then we
    // cannot use it.  Map it back to -std::c++latest, even though that might
    // end up enabling C++26 or later, so it does not apply to C sources.
    static std::string const kClangStdCxx23 = "-clang:-std=c++23";
    std::string::size_type p = flags.find(kClangStdCxx23);
    if (p != std::string::npos) {
      flags.replace(p, kClangStdCxx23.size(), "-std:c++latest");
    }
  }

  clOptions.Parse(flags);
  clOptions.Parse(defineFlags);
  std::vector<std::string> targetDefines;
  switch (this->ProjectType) {
    case VsProjectType::vcxproj:
      if (!langForClCompile.empty()) {
        this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
                                                     langForClCompile);
      }
      break;
    case VsProjectType::csproj:
      this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
                                                   "CSharp");
      cm::erase_if(targetDefines, [](std::string const& def) {
        return def.find('=') != std::string::npos;
      });
      break;
    default:
      break;
  }
  clOptions.AddDefines(targetDefines);

  if (this->ProjectType == VsProjectType::csproj) {
    clOptions.AppendFlag("DefineConstants", targetDefines);
  }

  if (this->MSTools) {
    clOptions.SetVerboseMakefile(
      this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
  }

  // Add C-specific flags expressible in a ClCompile meant for C++.
  if (isCXXwithC) {
    std::string flagsC;
    this->LocalGenerator->AddLanguageFlags(
      flagsC, this->GeneratorTarget, cmBuildStep::Compile, "C", configName);
    this->LocalGenerator->AddCompileOptions(flagsC, this->GeneratorTarget, "C",
                                            configName);

    // Modules/Compiler/Clang-C.cmake has a special case for clang-cl versions
    // that do not have a -std:c23 flag to pass the standard through to the
    // underlying clang directly.  Unfortunately that flag applies to all
    // sources in a single .vcxproj file, so if we have CXX sources too then
    // we cannot use it.  Map it back to -std:clatest, even though that might
    // enable a different C level, so it does not apply to CXX sources.
    static std::string const kClangStdC23 = "-clang:-std=c23";
    std::string::size_type p = flagsC.find(kClangStdC23);
    if (p != std::string::npos) {
      flagsC.replace(p, kClangStdC23.size(), "-std:clatest");
    }

    Options optC(this->LocalGenerator, Options::Compiler,
                 gg->GetClFlagTable());
    optC.Parse(flagsC);
    if (char const* stdC = optC.GetFlag("LanguageStandard_C")) {
      clOptions.AddFlag("LanguageStandard_C", stdC);
    }
  }

  // Add a definition for the configuration name.
  std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
  clOptions.AddDefine(configDefine);
  if (std::string const* exportMacro =
        this->GeneratorTarget->GetExportMacro()) {
    clOptions.AddDefine(*exportMacro);
  }
  // No need to add the SharedLibraryCompileDefs define here:
  // it is added by VisualStudio itself

  if (this->MSTools) {
    // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT
    if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
      clOptions.AddFlag("CompileAsWinRT", "true");
      // For WinRT components, add the _WINRT_DLL define to produce a lib
      if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
          this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
        clOptions.AddDefine("_WINRT_DLL");
      }
    } else if (this->GlobalGenerator->TargetsWindowsStore() ||
               this->GlobalGenerator->TargetsWindowsPhone() ||
               this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) {
      if (!clOptions.IsWinRt()) {
        clOptions.AddFlag("CompileAsWinRT", "false");
      }
    }
    if (char const* winRT = clOptions.GetFlag("CompileAsWinRT")) {
      if (cmIsOn(winRT)) {
        this->TargetCompileAsWinRT = true;
      }
    }
  }

  if (cm::optional<MsvcCharSet> charSet = clOptions.GetCharSet()) {
    this->CharSet.emplace(configName, *charSet);
  }

  if (this->ProjectType != VsProjectType::csproj &&
      (clOptions.IsManaged() || clOptions.HasFlag("CLRSupport"))) {
    this->Managed = true;
    std::string managedType = clOptions.HasFlag("CompileAsManaged")
      ? clOptions.GetFlag("CompileAsManaged")
      : "Mixed";
    if (managedType == "Safe"_s || managedType == "Pure"_s) {
      // force empty calling convention if safe clr is used
      clOptions.AddFlag("CallingConvention", "");
    }
    // The default values of these flags are incompatible to
    // managed assemblies. We have to force valid values if
    // the target is a managed C++ target.
    clOptions.AddFlag("ExceptionHandling", "Async");
    clOptions.AddFlag("BasicRuntimeChecks", "Default");
  }
  if (this->ProjectType == VsProjectType::csproj) {
    // /nowin32manifest overrides /win32manifest: parameter
    if (clOptions.HasFlag("NoWin32Manifest")) {
      clOptions.RemoveFlag("ApplicationManifest");
    }
  }

  if (char const* s = clOptions.GetFlag("SpectreMitigation")) {
    this->SpectreMitigation[configName] = s;
    clOptions.RemoveFlag("SpectreMitigation");
  }

  // Remove any target-wide -TC or -TP flag added by the project.
  // Such flags are unnecessary and break our model of language selection.
  if (langForClCompile == "C"_s || langForClCompile == "CXX"_s) {
    clOptions.RemoveFlag("CompileAs");
  }

  if (this->ProjectType == VsProjectType::vcxproj && this->MSTools) {
    // Suppress Microsoft.Cl.Common.props default settings for which the
    // project specifies no flags.  Do not let UseDebugLibraries affect them.
    if (!clOptions.HasFlag("BasicRuntimeChecks")) {
      clOptions.AddFlag("BasicRuntimeChecks", "Default");
    }
    if (!clOptions.HasFlag("BufferSecurityCheck")) {
      clOptions.AddFlag("BufferSecurityCheck", "");
    }
    if (!clOptions.HasFlag("CallingConvention")) {
      clOptions.AddFlag("CallingConvention", "");
    }
    // We cannot use the `Default` value, because it is incompatible with
    // VS2019 & first releases of VS2022
    if (!clOptions.HasFlag("FloatingPointModel")) {
      clOptions.AddFlag("FloatingPointModel", "");
    }
    if (!clOptions.HasFlag("ForceConformanceInForLoopScope")) {
      clOptions.AddFlag("ForceConformanceInForLoopScope", "");
    }
    if (!clOptions.HasFlag("MinimalRebuild")) {
      clOptions.AddFlag("MinimalRebuild", "");
    }
    if (!clOptions.HasFlag("Optimization")) {
      clOptions.AddFlag("Optimization", "");
    }
    if (!clOptions.HasFlag("RemoveUnreferencedCodeData")) {
      clOptions.AddFlag("RemoveUnreferencedCodeData", "");
    }
    if (!clOptions.HasFlag("RuntimeLibrary")) {
      clOptions.AddFlag("RuntimeLibrary", "");
    }
    if (!clOptions.HasFlag("SupportJustMyCode")) {
      clOptions.AddFlag("SupportJustMyCode", "");
    }
    if (!clOptions.HasFlag("TreatWChar_tAsBuiltInType")) {
      clOptions.AddFlag("TreatWChar_tAsBuiltInType", "");
    }
  }

  this->ClOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteClOptions(
  Elem& e1, std::string const& configName)
{
  Options& clOptions = *(this->ClOptions[configName]);
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }
  Elem e2(e1, "ClCompile");
  OptionsHelper oh(clOptions, e2);
  oh.PrependInheritedString("AdditionalOptions");
  oh.OutputAdditionalIncludeDirectories(this->LangForClCompile);
  oh.OutputFlagMap();
  oh.OutputPreprocessorDefinitions(this->LangForClCompile);

  if (this->NsightTegra) {
    if (cmValue processMax =
          this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
      e2.Element("ProcessMax", *processMax);
    }
  }

  if (this->Android) {
    e2.Element("ObjectFileName", "$(IntDir)%(filename).o");
  } else if (this->MSTools) {
    cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
    char const* toolset = this->GlobalGenerator->GetPlatformToolset();
    cmValue noCompileBatching =
      this->GeneratorTarget->GetProperty("VS_NO_COMPILE_BATCHING");
    if (noCompileBatching.IsOn() || (toolset && clangToolset.find(toolset))) {
      e2.Element("ObjectFileName", "$(IntDir)%(filename).obj");
    } else {
      e2.Element("ObjectFileName", "$(IntDir)");
    }

    // If not in debug mode, write the DebugInformationFormat field
    // without value so PDBs don't get generated uselessly. Each tag
    // goes on its own line because Visual Studio corrects it this
    // way when saving the project after CMake generates it.
    if (!clOptions.UsingDebugInfo()) {
      Elem e3(e2, "DebugInformationFormat");
      e3.SetHasElements();
    }

    // Specify the compiler program database file if configured.
    std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
    if (!pdb.empty()) {
      if (this->GlobalGenerator->IsCudaEnabled()) {
        // CUDA does not quote paths with spaces correctly when forwarding
        // this to the host compiler.  Use a relative path to avoid spaces.
        // FIXME: We can likely do this even when CUDA is not involved,
        // but for now we will make a minimal change.
        pdb = this->ConvertPath(pdb, true);
      }
      ConvertToWindowsSlash(pdb);
      e2.Element("ProgramDataBaseFileName", pdb);
    }

    // add AdditionalUsingDirectories
    if (this->AdditionalUsingDirectories.count(configName) > 0) {
      std::string dirs;
      for (auto const& u : this->AdditionalUsingDirectories[configName]) {
        if (!dirs.empty()) {
          dirs.append(";");
        }
        dirs.append(u);
      }
      e2.Element("AdditionalUsingDirectories", dirs);
    }
  }

  e2.Element("ScanSourceForModuleDependencies",
             this->ScanSourceForModuleDependencies[configName] ? "true"
                                                               : "false");
  if (this->WindowsKernelMode) {
    e2.Element("WppEnabled", "true");
    e2.Element("WppRecorderEnabled", "true");
  }
}

bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
{
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeRcOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
  Options& rcOptions = *pOptions;

  std::string CONFIG = cmSystemTools::UpperCase(configName);
  std::string rcConfigFlagsVar = cmStrCat("CMAKE_RC_FLAGS_", CONFIG);
  std::string flags =
    cmStrCat(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS"), ' ',
             this->Makefile->GetSafeDefinition(rcConfigFlagsVar));

  rcOptions.Parse(flags);

  // For historical reasons, add the C preprocessor defines to RC.
  Options& clOptions = *(this->ClOptions[configName]);
  rcOptions.AddDefines(clOptions.GetDefines());

  // Get includes for this target
  rcOptions.AddIncludes(this->GetIncludes(configName, "RC"));

  this->RcOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteRCOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools) {
    return;
  }
  Elem e2(e1, "ResourceCompile");

  OptionsHelper rcOptions(*(this->RcOptions[configName]), e2);
  rcOptions.OutputPreprocessorDefinitions("RC");
  rcOptions.OutputAdditionalIncludeDirectories("RC");
  rcOptions.PrependInheritedString("AdditionalOptions");
  rcOptions.OutputFlagMap();
}

bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
{
  if (!this->GlobalGenerator->IsCudaEnabled()) {
    return true;
  }
  return std::all_of(this->Configurations.begin(), this->Configurations.end(),
                     [this](std::string const& c) {
                       return !this->GeneratorTarget->IsLanguageUsed("CUDA",
                                                                     c) ||
                         this->ComputeCudaOptions(c);
                     });
}

bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
  Options& cudaOptions = *pOptions;

  auto cudaVersion = this->GlobalGenerator->GetPlatformToolsetCudaString();

  // Get compile flags for CUDA in this directory.
  std::string flags;
  this->LocalGenerator->AddLanguageFlags(
    flags, this->GeneratorTarget, cmBuildStep::Compile, "CUDA", configName);
  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
                                          configName);

  // Get preprocessor definitions for this directory.
  std::string defineFlags = this->Makefile->GetDefineFlags();

  cudaOptions.Parse(flags);
  cudaOptions.Parse(defineFlags);
  cudaOptions.ParseFinish();

  // If we haven't explicitly enabled GPU debug information
  // explicitly disable it
  if (!cudaOptions.HasFlag("GPUDebugInfo")) {
    cudaOptions.AddFlag("GPUDebugInfo", "false");
  }

  // The extension on object libraries the CUDA gives isn't
  // consistent with how MSVC generates object libraries for C+, so set
  // the default to not have any extension
  cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).obj");

  if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
    cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
  }
  bool notPtxLike = true;
  if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
    cudaOptions.AddFlag("NvccCompilation", "ptx");
    // We drop the %(Extension) component as CMake expects all PTX files
    // to not have the source file extension at all
    cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx");
    notPtxLike = false;

    if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                      cudaVersion, "9.0") &&
        cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, cudaVersion,
                                      "11.5")) {
      // The DriverApi flag before 11.5 ( verified back to 9.0 ) which controls
      // PTX compilation doesn't propagate user defines causing
      // target_compile_definitions to behave differently for VS +
      // PTX compared to other generators so we patch the rules
      // to normalize behavior
      cudaOptions.AddFlag("DriverApiCommandLineTemplate",
                          "%(BaseCommandLineTemplate) [CompileOut] [FastMath] "
                          "[Defines] \"%(FullPath)\"");
    }
  } else if (this->GeneratorTarget->GetPropertyAsBool(
               "CUDA_CUBIN_COMPILATION")) {
    cudaOptions.AddFlag("NvccCompilation", "cubin");
    cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).cubin");
    notPtxLike = false;
  } else if (this->GeneratorTarget->GetPropertyAsBool(
               "CUDA_FATBIN_COMPILATION")) {
    cudaOptions.AddFlag("NvccCompilation", "fatbin");
    cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).fatbin");
    notPtxLike = false;
  } else if (this->GeneratorTarget->GetPropertyAsBool(
               "CUDA_OPTIX_COMPILATION")) {
    cudaOptions.AddFlag("NvccCompilation", "optix-ir");
    cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).optixir");
    notPtxLike = false;
  }

  if (notPtxLike &&
      cmSystemTools::VersionCompareGreaterEq(
        "8.0", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
    // Explicitly state that we want this file to be treated as a
    // CUDA file no matter what the file extensions is
    // This is only needed for < CUDA 9
    cudaOptions.AppendFlagString("AdditionalOptions", "-x cu");
  }

  // Specify the compiler program database file if configured.
  std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
  if (!pdb.empty()) {
    // CUDA does not make the directory if it is non-standard.
    std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
    cmSystemTools::MakeDirectory(pdbDir);
    if (cmSystemTools::VersionCompareGreaterEq(
          "9.2", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
      // CUDA does not have a field for this and does not honor the
      // ProgramDataBaseFileName field in ClCompile.  Work around this
      // limitation by creating the directory and passing the flag ourselves.
      pdb = this->ConvertPath(pdb, true);
      ConvertToWindowsSlash(pdb);
      std::string const clFd = cmStrCat(R"(-Xcompiler="-Fd\")", pdb, R"(\"")");
      cudaOptions.AppendFlagString("AdditionalOptions", clFd);
    }
  }

  // CUDA automatically passes the proper '--machine' flag to nvcc
  // for the current architecture, but does not reflect this default
  // in the user-visible IDE settings.  Set it explicitly.
  if (this->Platform == "x64"_s) {
    cudaOptions.AddFlag("TargetMachinePlatform", "64");
  }

  // Convert the host compiler options to the toolset's abstractions
  // using a secondary flag table.
  cudaOptions.ClearTables();
  cudaOptions.AddTable(gg->GetCudaHostFlagTable());
  cudaOptions.Reparse("AdditionalCompilerOptions");

  // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc!
  // Pass them through -Xcompiler in AdditionalOptions instead.
  if (char const* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) {
    std::string aco = acoPtr;
    cudaOptions.RemoveFlag("AdditionalCompilerOptions");
    if (!aco.empty()) {
      aco = this->LocalGenerator->EscapeForShell(aco, false);
      cudaOptions.AppendFlagString("AdditionalOptions",
                                   cmStrCat("-Xcompiler=", aco));
    }
  }

  cudaOptions.FixCudaCodeGeneration();

  std::vector<std::string> targetDefines;
  this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
                                               "CUDA");
  cudaOptions.AddDefines(targetDefines);

  // Add a definition for the configuration name.
  std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
  cudaOptions.AddDefine(configDefine);
  if (std::string const* exportMacro =
        this->GeneratorTarget->GetExportMacro()) {
    cudaOptions.AddDefine(*exportMacro);
  }
  // No need to add the SharedLibraryCompileDefs define here:
  // it is added by VisualStudio itself

  // Get includes for this target
  cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
  cudaOptions.AddFlag("UseHostInclude", "false");

  // Add runtime library selection flag.
  std::string const& cudaRuntime =
    this->GeneratorTarget->GetRuntimeLinkLibrary("CUDA", configName);
  if (cudaRuntime == "STATIC"_s) {
    cudaOptions.AddFlag("CudaRuntime", "Static");
  } else if (cudaRuntime == "SHARED"_s) {
    cudaOptions.AddFlag("CudaRuntime", "Shared");
  } else if (cudaRuntime == "NONE"_s) {
    cudaOptions.AddFlag("CudaRuntime", "None");
  }

  if (cm::optional<MsvcCharSet> charSet = cudaOptions.GetCharSet()) {
    this->CharSet.emplace(configName, *charSet);
  }

  if (this->ProjectType == VsProjectType::vcxproj && this->MSTools) {
    // Suppress inheritance of host compiler optimization flags
    // when the project does not specify any optimization flags for CUDA.
    if (!cudaOptions.HasFlag("Optimization")) {
      cudaOptions.AddFlag("Optimization", "");
    }
  }

  this->CudaOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteCudaOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled() ||
      !this->GeneratorTarget->IsLanguageUsed("CUDA", configName)) {
    return;
  }
  Elem e2(e1, "CudaCompile");

  OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2);
  cudaOptions.OutputAdditionalIncludeDirectories("CUDA");
  cudaOptions.OutputPreprocessorDefinitions("CUDA");
  cudaOptions.PrependInheritedString("AdditionalOptions");
  cudaOptions.OutputFlagMap();
}

bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
{
  if (!this->GlobalGenerator->IsCudaEnabled()) {
    return true;
  }
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeCudaLinkOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
  Options& cudaLinkOptions = *pOptions;

  cmGeneratorTarget::DeviceLinkSetter setter(*this->GeneratorTarget);

  // Determine if we need to do a device link
  bool const doDeviceLinking = requireDeviceLinking(
    *this->GeneratorTarget, *this->LocalGenerator, configName);

  cudaLinkOptions.AddFlag("PerformDeviceLink",
                          doDeviceLinking ? "true" : "false");

  // Add extra flags for device linking
  cudaLinkOptions.AppendFlagString(
    "AdditionalOptions",
    this->Makefile->GetSafeDefinition("_CMAKE_CUDA_EXTRA_FLAGS"));
  cudaLinkOptions.AppendFlagString(
    "AdditionalOptions",
    this->Makefile->GetSafeDefinition("_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS"));

  std::vector<std::string> linkOpts;
  std::string linkFlags;
  this->GeneratorTarget->GetLinkOptions(linkOpts, configName, "CUDA");
  // LINK_OPTIONS are escaped.
  this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts);

  cmComputeLinkInformation* pcli =
    this->GeneratorTarget->GetLinkInformation(configName);
  if (doDeviceLinking && pcli) {

    cmLinkLineDeviceComputer computer(
      this->LocalGenerator,
      this->LocalGenerator->GetStateSnapshot().GetDirectory());
    std::string ignored_;
    this->LocalGenerator->GetDeviceLinkFlags(computer, configName, ignored_,
                                             linkFlags, ignored_, ignored_,
                                             this->GeneratorTarget);

    this->LocalGenerator->AddLanguageFlagsForLinking(
      linkFlags, this->GeneratorTarget, "CUDA", configName);
  }
  cudaLinkOptions.AppendFlagString("AdditionalOptions", linkFlags);

  if (doDeviceLinking) {
    std::vector<std::string> libVec;
    auto const& kinded = this->GeneratorTarget->GetKindedSources(configName);
    // CMake conversion uses full paths when possible to allow deeper trees.
    // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
    // we must use relative paths.
    bool const forceRelative = true;
    for (cmGeneratorTarget::SourceAndKind const& si : kinded.Sources) {
      switch (si.Kind) {
        case cmGeneratorTarget::SourceKindExternalObject: {
          std::string path =
            this->ConvertPath(si.Source.Value->GetFullPath(), forceRelative);
          ConvertToWindowsSlash(path);
          libVec.emplace_back(std::move(path));
        } break;
        default:
          break;
      }
    }
    // For static libraries that have device linking enabled compute
    // the  libraries
    if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
      cmComputeLinkInformation& cli = *pcli;
      cmLinkLineDeviceComputer computer(
        this->LocalGenerator,
        this->LocalGenerator->GetStateSnapshot().GetDirectory());
      std::vector<BT<std::string>> btLibVec;
      computer.ComputeLinkLibraries(cli, std::string{}, btLibVec);
      for (auto const& item : btLibVec) {
        libVec.emplace_back(item.Value);
      }
    }
    if (!libVec.empty()) {
      cudaLinkOptions.AddFlag("AdditionalDependencies", libVec);
    }
  }

  this->CudaLinkOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
  Elem& e1, std::string const& configName)
{
  // We need to write link options for OBJECT libraries so that
  // we override the default device link behavior ( enabled ) when
  // building object libraries with ptx/optix-ir/etc
  if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
    return;
  }

  if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
    return;
  }

  Elem e2(e1, "CudaLink");
  OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2);
  cudaLinkOptions.OutputFlagMap();
}

bool cmVisualStudio10TargetGenerator::ComputeMarmasmOptions()
{
  if (!this->GlobalGenerator->IsMarmasmEnabled()) {
    return true;
  }
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeMarmasmOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeMarmasmOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::MarmasmCompiler, gg->GetMarmasmFlagTable());
  Options& marmasmOptions = *pOptions;

  std::string flags;
  this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
                                         cmBuildStep::Compile, "ASM_MARMASM",
                                         configName);
  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
                                          "ASM_MARMASM", configName);

  marmasmOptions.Parse(flags);

  // Get includes for this target
  marmasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MARMASM"));

  this->MarmasmOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteMarmasmOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools || !this->GlobalGenerator->IsMarmasmEnabled()) {
    return;
  }
  Elem e2(e1, "MARMASM");

  // Preprocessor definitions and includes are shared with clOptions.
  OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
  clOptions.OutputPreprocessorDefinitions("ASM_MARMASM");

  OptionsHelper marmasmOptions(*(this->MarmasmOptions[configName]), e2);
  marmasmOptions.OutputAdditionalIncludeDirectories("ASM_MARMASM");
  marmasmOptions.PrependInheritedString("AdditionalOptions");
  marmasmOptions.OutputFlagMap();
}

bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
{
  if (!this->GlobalGenerator->IsMasmEnabled()) {
    return true;
  }
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeMasmOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
  Options& masmOptions = *pOptions;

  // MSBuild enables debug information by default.
  // Disable it explicitly unless a flag parsed below re-enables it.
  masmOptions.AddFlag("GenerateDebugInformation", "false");

  std::string flags;
  this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
                                         cmBuildStep::Compile, "ASM_MASM",
                                         configName);
  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
                                          "ASM_MASM", configName);

  masmOptions.Parse(flags);

  // Get includes for this target
  masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));

  this->MasmOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteMasmOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
    return;
  }
  Elem e2(e1, "MASM");

  // Preprocessor definitions and includes are shared with clOptions.
  OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
  clOptions.OutputPreprocessorDefinitions("ASM_MASM");

  OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
  masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
  masmOptions.PrependInheritedString("AdditionalOptions");
  masmOptions.OutputFlagMap();
}

bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
{
  if (!this->GlobalGenerator->IsNasmEnabled()) {
    return true;
  }
  return std::all_of(
    this->Configurations.begin(), this->Configurations.end(),
    [this](std::string const& c) { return this->ComputeNasmOptions(c); });
}

bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
  std::string const& configName)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
  Options& nasmOptions = *pOptions;

  std::string flags;
  this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
                                         cmBuildStep::Compile, "ASM_NASM",
                                         configName);
  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
                                          "ASM_NASM", configName);
  flags += " -f";
  flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT");
  nasmOptions.Parse(flags);

  // Get includes for this target
  nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));

  this->NasmOptions[configName] = std::move(pOptions);
  return true;
}

void cmVisualStudio10TargetGenerator::WriteNasmOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->GlobalGenerator->IsNasmEnabled()) {
    return;
  }
  Elem e2(e1, "NASM");

  OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
  nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
  nasmOptions.OutputFlagMap();
  nasmOptions.PrependInheritedString("AdditionalOptions");
  nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");

  // Preprocessor definitions and includes are shared with clOptions.
  OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
  clOptions.OutputPreprocessorDefinitions("ASM_NASM");
}

void cmVisualStudio10TargetGenerator::WriteLibOptions(
  Elem& e1, std::string const& config)
{
  if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
      this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
    return;
  }

  std::string const& linkLanguage =
    this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;

  std::string libflags;
  this->LocalGenerator->GetStaticLibraryFlags(libflags, config, linkLanguage,
                                              this->GeneratorTarget);
  if (!libflags.empty()) {
    Elem e2(e1, "Lib");
    cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
    cmVS10GeneratorOptions libOptions(this->LocalGenerator,
                                      cmVisualStudioGeneratorOptions::Linker,
                                      gg->GetLibFlagTable(), this);
    libOptions.Parse(libflags);
    OptionsHelper oh(libOptions, e2);
    oh.PrependInheritedString("AdditionalOptions");
    oh.OutputFlagMap();
  }

  // We cannot generate metadata for static libraries.  WindowsPhone
  // and WindowsStore tools look at GenerateWindowsMetadata in the
  // Link tool options even for static libraries.
  if (this->GlobalGenerator->TargetsWindowsPhone() ||
      this->GlobalGenerator->TargetsWindowsStore()) {
    Elem e2(e1, "Link");
    e2.Element("GenerateWindowsMetadata", "false");
  }
}

void cmVisualStudio10TargetGenerator::WriteManifestOptions(
  Elem& e1, std::string const& config)
{
  if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
      this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
      this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY) {
    return;
  }

  std::vector<cmSourceFile const*> manifest_srcs;
  this->GeneratorTarget->GetManifests(manifest_srcs, config);

  cmValue dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");

  if (!manifest_srcs.empty() || dpiAware) {
    Elem e2(e1, "Manifest");
    if (!manifest_srcs.empty()) {
      std::ostringstream oss;
      for (cmSourceFile const* mi : manifest_srcs) {
        std::string m = this->ConvertPath(mi->GetFullPath(), false);
        ConvertToWindowsSlash(m);
        oss << m << ";";
      }
      e2.Element("AdditionalManifestFiles", oss.str());
    }
    if (dpiAware) {
      if (*dpiAware == "PerMonitor"_s) {
        e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware");
      } else if (dpiAware.IsOn()) {
        e2.Element("EnableDpiAwareness", "true");
      } else if (dpiAware.IsOff()) {
        e2.Element("EnableDpiAwareness", "false");
      } else {
        cmSystemTools::Error(
          cmStrCat("Bad parameter for VS_DPI_AWARE: ", *dpiAware));
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
  Elem& e1, std::string const& configName)
{
  // Look through the sources for AndroidManifest.xml and use
  // its location as the root source directory.
  std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory();
  {
    for (cmGeneratorTarget::AllConfigSource const& source :
         this->GeneratorTarget->GetAllConfigSources()) {
      if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
          "androidmanifest.xml" ==
            cmSystemTools::LowerCase(source.Source->GetLocation().GetName())) {
        rootDir = source.Source->GetLocation().GetDirectory();
        break;
      }
    }
  }

  // Tell MSBuild to launch Ant.
  Elem e2(e1, "AntBuild");
  {
    std::string antBuildPath = rootDir;
    ConvertToWindowsSlash(antBuildPath);
    e2.Element("AntBuildPath", antBuildPath);
  }

  if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
    e2.Element("SkipAntStep", "true");
  }

  if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
    e2.Element("EnableProGuard", "true");
  }

  if (cmValue proGuardConfigLocation =
        this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
    e2.Element("ProGuardConfigLocation", *proGuardConfigLocation);
  }

  if (cmValue securePropertiesLocation =
        this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
    e2.Element("SecurePropertiesLocation", *securePropertiesLocation);
  }

  if (cmValue nativeLibDirectoriesExpression =
        this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) {
    std::string nativeLibDirs = cmGeneratorExpression::Evaluate(
      *nativeLibDirectoriesExpression, this->LocalGenerator, configName);
    e2.Element("NativeLibDirectories", nativeLibDirs);
  }

  if (cmValue nativeLibDependenciesExpression =
        this->GeneratorTarget->GetProperty(
          "ANDROID_NATIVE_LIB_DEPENDENCIES")) {
    std::string nativeLibDeps = cmGeneratorExpression::Evaluate(
      *nativeLibDependenciesExpression, this->LocalGenerator, configName);
    e2.Element("NativeLibDependencies", nativeLibDeps);
  }

  if (cmValue javaSourceDir =
        this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
    e2.Element("JavaSourceDir", *javaSourceDir);
  }

  if (cmValue jarDirectoriesExpression =
        this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) {
    std::string jarDirectories = cmGeneratorExpression::Evaluate(
      *jarDirectoriesExpression, this->LocalGenerator, configName);
    e2.Element("JarDirectories", jarDirectories);
  }

  if (cmValue jarDeps =
        this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
    e2.Element("JarDependencies", *jarDeps);
  }

  if (cmValue assetsDirectories =
        this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
    e2.Element("AssetsDirectories", *assetsDirectories);
  }

  {
    std::string manifest_xml = cmStrCat(rootDir, "/AndroidManifest.xml");
    ConvertToWindowsSlash(manifest_xml);
    e2.Element("AndroidManifestLocation", manifest_xml);
  }

  if (cmValue antAdditionalOptions =
        this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
    e2.Element("AdditionalOptions",
               cmStrCat(*antAdditionalOptions, " %(AdditionalOptions)"));
  }
}

bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
{
  if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
      this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
      this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
    for (std::string const& c : this->Configurations) {
      if (!this->ComputeLinkOptions(c)) {
        return false;
      }
    }
  }
  return true;
}

bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
  std::string const& config)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  auto pOptions = cm::make_unique<Options>(
    this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
  Options& linkOptions = *pOptions;

  cmGeneratorTarget::LinkClosure const* linkClosure =
    this->GeneratorTarget->GetLinkClosure(config);

  std::string const& linkLanguage = linkClosure->LinkerLanguage;
  if (linkLanguage.empty()) {
    cmSystemTools::Error(cmStrCat(
      "CMake can not determine linker language for target: ", this->Name));
    return false;
  }

  std::string CONFIG = cmSystemTools::UpperCase(config);

  char const* linkType = "SHARED";
  if (this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
    linkType = "MODULE";
  }
  if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
    linkType = "EXE";
  }
  std::string flags;
  this->LocalGenerator->AddConfigVariableFlags(
    flags, cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS"),
    this->GeneratorTarget, cmBuildStep::Link, linkLanguage, config);
  cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
  if (targetLinkFlags) {
    flags += ' ';
    flags += *targetLinkFlags;
  }
  std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
  if (cmValue flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) {
    flags += ' ';
    flags += *flagsConfig;
  }

  std::vector<std::string> opts;
  this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage);
  // LINK_OPTIONS are escaped.
  this->LocalGenerator->AppendCompileOptions(flags, opts);

  this->LocalGenerator->AppendWarningAsErrorLinkerFlags(
    flags, this->GeneratorTarget, linkLanguage);

  cmComputeLinkInformation* pcli =
    this->GeneratorTarget->GetLinkInformation(config);
  if (!pcli) {
    cmSystemTools::Error(
      cmStrCat("CMake can not compute cmComputeLinkInformation for target: ",
               this->Name));
    return false;
  }
  cmComputeLinkInformation& cli = *pcli;

  std::vector<std::string> libVec;
  std::vector<std::string> vsTargetVec;
  this->AddLibraries(cli, libVec, vsTargetVec, config);
  std::string standardLibsVar =
    cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
  std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar);
  cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
  linkOptions.AddFlag("AdditionalDependencies", libVec);

  // Populate TargetsFileAndConfigsVec
  for (std::string const& ti : vsTargetVec) {
    this->AddTargetsFileAndConfigPair(ti, config);
  }

  std::vector<std::string> linkDirs;
  std::vector<std::string> const& ldirs = cli.GetDirectories();
  for (std::string const& d : ldirs) {
    // first just full path
    linkDirs.push_back(d);
    // next path with configuration type Debug, Release, etc
    linkDirs.emplace_back(cmStrCat(d, "/$(Configuration)"));
  }

  std::string const& linkDirsString = this->Makefile->GetSafeDefinition(
    cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LINK_DIRECTORIES"));
  for (std::string const& d : cmList(linkDirsString)) {
    linkDirs.push_back(d);
  }

  linkDirs.push_back("%(AdditionalLibraryDirectories)");
  linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);

  cmGeneratorTarget::Names targetNames;
  if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
    targetNames = this->GeneratorTarget->GetExecutableNames(config);
  } else {
    targetNames = this->GeneratorTarget->GetLibraryNames(config);
  }

  if (this->MSTools) {
    if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
      // Specify an entry point for executables.
      if (this->GeneratorTarget->IsWin32Executable(config)) {
        if (this->GlobalGenerator->TargetsWindowsCE()) {
          linkOptions.AddFlag("SubSystem", "WindowsCE");
          if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
            if (this->CharSet[config] == MsvcCharSet::Unicode) {
              linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup");
            } else {
              linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup");
            }
          }
        } else {
          linkOptions.AddFlag("SubSystem", "Windows");
        }
      } else {
        if (this->GlobalGenerator->TargetsWindowsCE()) {
          linkOptions.AddFlag("SubSystem", "WindowsCE");
          if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
            if (this->CharSet[config] == MsvcCharSet::Unicode) {
              linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup");
            } else {
              linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup");
            }
          }
        } else {
          linkOptions.AddFlag("SubSystem", "Console");
        };
      }
    }

    if (cmValue stackVal = this->Makefile->GetDefinition(
          cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"))) {
      linkOptions.AddFlag("StackReserveSize", *stackVal);
    }

    linkOptions.AddFlag("GenerateDebugInformation", "false");

    std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config),
                               '/', targetNames.PDB);
    if (!targetNames.ImportLibrary.empty()) {
      std::string imLib =
        cmStrCat(this->GeneratorTarget->GetDirectory(
                   config, cmStateEnums::ImportLibraryArtifact),
                 '/', targetNames.ImportLibrary);

      linkOptions.AddFlag("ImportLibrary", imLib);
    }
    linkOptions.AddFlag("ProgramDataBaseFile", pdb);

    // Add image version
    int major, minor;
    this->GeneratorTarget->GetTargetVersion(major, minor);
    if (major || minor) {
      linkOptions.AddFlag("Version", cmStrCat(major, '.', minor));
    }

    // A Windows Runtime component uses internal .NET metadata,
    // so does not have an import library.
    if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") &&
        this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
      linkOptions.AddFlag("GenerateWindowsMetadata", "true");
    } else if (this->GlobalGenerator->TargetsWindowsPhone() ||
               this->GlobalGenerator->TargetsWindowsStore()) {
      // WindowsPhone and WindowsStore components are in an app container
      // and produce WindowsMetadata.  If we are not producing a WINRT
      // component, then do not generate the metadata here.
      linkOptions.AddFlag("GenerateWindowsMetadata", "false");
    }

    if (this->GlobalGenerator->TargetsWindowsPhone() &&
        this->GlobalGenerator->GetSystemVersion() == "8.0"_s) {
      // WindowsPhone 8.0 does not have ole32.
      linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
    }
  } else if (this->NsightTegra) {
    linkOptions.AddFlag("SoName", targetNames.SharedObject);
  }

  linkOptions.Parse(flags);
  linkOptions.FixManifestUACFlags();

  if (this->MSTools) {
    cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
      this->GeneratorTarget->GetModuleDefinitionInfo(config);
    if (mdi && !mdi->DefFile.empty()) {
      linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
    }
    linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
                           "%(IgnoreSpecificDefaultLibraries)");
  }

  // VS 2015 without all updates has a v140 toolset whose
  // GenerateDebugInformation expects No/Debug instead of false/true.
  if (gg->GetPlatformToolsetNeedsDebugEnum()) {
    if (char const* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
      if (strcmp(debug, "false") == 0) {
        linkOptions.AddFlag("GenerateDebugInformation", "No");
      } else if (strcmp(debug, "true") == 0) {
        linkOptions.AddFlag("GenerateDebugInformation", "Debug");
      }
    }
  }

  // Managed code cannot be linked with /DEBUG:FASTLINK
  if (this->Managed) {
    if (char const* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
      if (strcmp(debug, "DebugFastLink") == 0) {
        linkOptions.AddFlag("GenerateDebugInformation", "Debug");
      }
    }
  }

  if (this->ProjectType == VsProjectType::vcxproj && this->MSTools) {
    // Suppress MSBuild default settings for which the project
    // specifies no flags.
    if (!linkOptions.HasFlag("DataExecutionPrevention")) {
      linkOptions.AddFlag("DataExecutionPrevention", "");
    }
    if (!linkOptions.HasFlag("ImageHasSafeExceptionHandlers")) {
      linkOptions.AddFlag("ImageHasSafeExceptionHandlers", "");
    }
    if (!linkOptions.HasFlag("LinkErrorReporting")) {
      linkOptions.AddFlag("LinkErrorReporting", "");
    }
    if (!linkOptions.HasFlag("RandomizedBaseAddress")) {
      linkOptions.AddFlag("RandomizedBaseAddress", "");
    }
    if (!linkOptions.HasFlag("SubSystem")) {
      linkOptions.AddFlag("SubSystem", "");
    }
  }

  this->LinkOptions[config] = std::move(pOptions);
  return true;
}

bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
{
  if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
    for (std::string const& c : this->Configurations) {
      if (!this->ComputeLibOptions(c)) {
        return false;
      }
    }
  }
  return true;
}

bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
  std::string const& config)
{
  cmComputeLinkInformation* pcli =
    this->GeneratorTarget->GetLinkInformation(config);
  if (!pcli) {
    cmSystemTools::Error(
      cmStrCat("CMake can not compute cmComputeLinkInformation for target: ",
               this->Name));
    return false;
  }

  cmComputeLinkInformation& cli = *pcli;
  using ItemVector = cmComputeLinkInformation::ItemVector;
  ItemVector const& libs = cli.GetItems();
  for (cmComputeLinkInformation::Item const& l : libs) {
    if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
        cmVS10IsTargetsFile(l.Value.Value)) {
      std::string path =
        this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
      ConvertToWindowsSlash(path);
      this->AddTargetsFileAndConfigPair(path, config);
    }
  }

  return true;
}

void cmVisualStudio10TargetGenerator::WriteLinkOptions(
  Elem& e1, std::string const& config)
{
  if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
      this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
    return;
  }
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }

  {
    Elem e2(e1, "Link");
    OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
    linkOptions.PrependInheritedString("AdditionalOptions");
    linkOptions.OutputFlagMap();
  }

  if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
        this->GeneratorTarget)) {
    Elem e2(e1, "ProjectReference");
    e2.Element("LinkLibraryDependencies", "false");
  }
}

void cmVisualStudio10TargetGenerator::AddLibraries(
  cmComputeLinkInformation const& cli, std::vector<std::string>& libVec,
  std::vector<std::string>& vsTargetVec, std::string const& config)
{
  using ItemVector = cmComputeLinkInformation::ItemVector;
  ItemVector const& libs = cli.GetItems();
  for (cmComputeLinkInformation::Item const& l : libs) {
    if (l.Target) {
      auto managedType = l.Target->GetManagedType(config);
      if (managedType != cmGeneratorTarget::ManagedType::Native &&
          this->GeneratorTarget->GetManagedType(config) !=
            cmGeneratorTarget::ManagedType::Native &&
          l.Target->IsImported() &&
          l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
        auto location = l.Target->GetFullPath(config);
        if (!location.empty()) {
          ConvertToWindowsSlash(location);
          switch (this->ProjectType) {
            case VsProjectType::csproj:
              // If the target we want to "link" to is an imported managed
              // target and this is a C# project, we add a hint reference. This
              // reference is written to project file in
              // WriteDotNetReferences().
              this->DotNetHintReferences[config].push_back(
                DotNetHintReference(l.Target->GetName(), location));
              break;
            case VsProjectType::vcxproj:
              // Add path of assembly to list of using-directories, so the
              // managed assembly can be used by '#using <assembly.dll>' in
              // code.
              this->AdditionalUsingDirectories[config].insert(
                cmSystemTools::GetFilenamePath(location));
              break;
            default:
              // In .proj files, we wouldn't be referencing libraries.
              break;
          }
        }
      }
      // Do not allow C# targets to be added to the LIB listing. LIB files are
      // used for linking C++ dependencies. C# libraries do not have lib files.
      // Instead, they compile down to C# reference libraries (DLL files). The
      // `<ProjectReference>` elements added to the vcxproj are enough for the
      // IDE to deduce the DLL file required by other C# projects that need its
      // reference library.
      if (managedType == cmGeneratorTarget::ManagedType::Managed) {
        continue;
      }
    }

    if (l.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) {
      std::string path =
        this->LocalGenerator->MaybeRelativeToCurBinDir(l.Value.Value);
      ConvertToWindowsSlash(path);
      if (cmVS10IsTargetsFile(l.Value.Value)) {
        vsTargetVec.push_back(path);
      } else {
        libVec.push_back(l.HasFeature() ? l.GetFormattedItem(path).Value
                                        : path);
      }
    } else if (!l.Target ||
               (l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
                l.Target->GetType() != cmStateEnums::OBJECT_LIBRARY)) {
      libVec.push_back(l.Value.Value);
    }
  }
}

void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
  std::string const& targetsFile, std::string const& config)
{
  for (TargetsFileAndConfigs& i : this->TargetsFileAndConfigsVec) {
    if (cmSystemTools::ComparePath(targetsFile, i.File)) {
      if (!cm::contains(i.Configs, config)) {
        i.Configs.push_back(config);
      }
      return;
    }
  }
  TargetsFileAndConfigs entry;
  entry.File = targetsFile;
  entry.Configs.push_back(config);
  this->TargetsFileAndConfigsVec.push_back(entry);
}

void cmVisualStudio10TargetGenerator::WriteMidlOptions(
  Elem& e1, std::string const& configName)
{
  if (!this->MSTools) {
    return;
  }
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }
  if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
    return;
  }

  // This processes *any* of the .idl files specified in the project's file
  // list (and passed as the item metadata %(Filename) expressing the rule
  // input filename) into output files at the per-config *build* dir
  // ($(IntDir)) each.
  //
  // IOW, this MIDL section is intended to provide a fully generic syntax
  // content suitable for most cases (read: if you get errors, then it's quite
  // probable that the error is on your side of the .idl setup).
  //
  // Also, note that the marked-as-generated _i.c file in the Visual Studio
  // generator case needs to be referred to as $(IntDir)\foo_i.c at the
  // project's file list, otherwise the compiler-side processing won't pick it
  // up (for non-directory form, it ends up looking in project binary dir
  // only).  Perhaps there's something to be done to make this more automatic
  // on the CMake side?
  std::vector<std::string> const includes =
    this->GetIncludes(configName, "MIDL");
  std::ostringstream oss;
  for (std::string const& i : includes) {
    oss << i << ";";
  }
  oss << "%(AdditionalIncludeDirectories)";

  Elem e2(e1, "Midl");
  e2.Element("AdditionalIncludeDirectories", oss.str());
  e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
  e2.Element("HeaderFileName", "%(Filename).h");
  e2.Element("TypeLibraryName", "%(Filename).tlb");
  e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
  e2.Element("ProxyFileName", "%(Filename)_p.c");
}

void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
{
  if (this->ProjectType == VsProjectType::csproj) {
    return;
  }
  for (std::string const& c : this->Configurations) {
    Elem e1(e0, "ItemDefinitionGroup");
    e1.Attribute("Condition", this->CalcCondition(c));

    //    output cl compile flags <ClCompile></ClCompile>
    if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
      this->WriteClOptions(e1, c);
      //    output rc compile flags <ResourceCompile></ResourceCompile>
      this->WriteRCOptions(e1, c);
      this->WriteCudaOptions(e1, c);
      this->WriteMarmasmOptions(e1, c);
      this->WriteMasmOptions(e1, c);
      this->WriteNasmOptions(e1, c);
    }

    if (this->WindowsKernelMode) {
      Elem(e1, "DriverSign").Element("FileDigestAlgorithm", "sha256");
    }
    //    output midl flags       <Midl></Midl>
    this->WriteMidlOptions(e1, c);
    // write events
    if (this->ProjectType != VsProjectType::csproj) {
      this->WriteEvents(e1, c);
    }
    //    output link flags       <Link></Link>
    this->WriteLinkOptions(e1, c);
    this->WriteCudaLinkOptions(e1, c);
    //    output lib flags       <Lib></Lib>
    this->WriteLibOptions(e1, c);
    //    output manifest flags  <Manifest></Manifest>
    this->WriteManifestOptions(e1, c);
    if (this->NsightTegra &&
        this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
      this->WriteAntBuildOptions(e1, c);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteEvents(
  Elem& e1, std::string const& configName)
{
  bool addedPrelink = false;
  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
    this->GeneratorTarget->GetModuleDefinitionInfo(configName);
  if (mdi && mdi->DefFileGenerated) {
    addedPrelink = true;
    std::vector<cmCustomCommand> commands =
      this->GeneratorTarget->GetPreLinkCommands();
    this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
                                                  commands, configName);
    this->WriteEvent(e1, "PreLinkEvent", commands, configName);
  }
  if (!addedPrelink) {
    this->WriteEvent(e1, "PreLinkEvent",
                     this->GeneratorTarget->GetPreLinkCommands(), configName);
  }
  this->WriteEvent(e1, "PreBuildEvent",
                   this->GeneratorTarget->GetPreBuildCommands(), configName);
  this->WriteEvent(e1, "PostBuildEvent",
                   this->GeneratorTarget->GetPostBuildCommands(), configName);
}

void cmVisualStudio10TargetGenerator::WriteEvent(
  Elem& e1, std::string const& name,
  std::vector<cmCustomCommand> const& commands, std::string const& configName)
{
  if (commands.empty()) {
    return;
  }
  cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
  std::string script;
  char const* pre = "";
  std::string comment;
  bool stdPipesUTF8 = false;
  for (cmCustomCommand const& cc : commands) {
    cmCustomCommandGenerator ccg(cc, configName, lg);
    if (!ccg.HasOnlyEmptyCommandLines()) {
      comment += pre;
      comment += lg->ConstructComment(ccg);
      script += pre;
      pre = "\n";
      script += lg->ConstructScript(ccg);

      stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
    }
  }
  if (!script.empty()) {
    script += lg->FinishConstructScript(this->ProjectType);
  }
  comment = cmVS10EscapeComment(comment);
  if (this->ProjectType != VsProjectType::csproj) {
    Elem e2(e1, name);
    if (stdPipesUTF8) {
      this->WriteStdOutEncodingUtf8(e2);
    }
    e2.Element("Message", comment);
    e2.Element("Command", script);
  } else {
    std::string strippedComment = comment;
    strippedComment.erase(
      std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
      strippedComment.end());
    std::ostringstream oss;
    if (!comment.empty() && !strippedComment.empty()) {
      oss << "echo " << comment << "\n";
    }
    oss << script << "\n";
    e1.Element(name, oss.str());
  }
}

void cmVisualStudio10TargetGenerator::WriteSdkStyleEvents(
  Elem& e0, std::string const& configName)
{
  this->WriteSdkStyleEvent(e0, "PreLink", "BeforeTargets", "Link",
                           this->GeneratorTarget->GetPreLinkCommands(),
                           configName);
  this->WriteSdkStyleEvent(e0, "PreBuild", "BeforeTargets", "PreBuildEvent",
                           this->GeneratorTarget->GetPreBuildCommands(),
                           configName);
  this->WriteSdkStyleEvent(e0, "PostBuild", "AfterTargets", "PostBuildEvent",
                           this->GeneratorTarget->GetPostBuildCommands(),
                           configName);
}

void cmVisualStudio10TargetGenerator::WriteSdkStyleEvent(
  Elem& e0, std::string const& name, std::string const& when,
  std::string const& target, std::vector<cmCustomCommand> const& commands,
  std::string const& configName)
{
  if (commands.empty()) {
    return;
  }
  Elem e1(e0, "Target");
  e1.Attribute("Condition",
               cmStrCat("'$(Configuration)' == '", configName, '\''));
  e1.Attribute("Name", name + configName);
  e1.Attribute(when.c_str(), target);
  e1.SetHasElements();

  cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
  std::string script;
  char const* pre = "";
  std::string comment;
  bool stdPipesUTF8 = false;
  for (cmCustomCommand const& cc : commands) {
    cmCustomCommandGenerator ccg(cc, configName, lg);
    if (!ccg.HasOnlyEmptyCommandLines()) {
      comment += pre;
      comment += lg->ConstructComment(ccg);
      script += pre;
      pre = "\n";
      script += lg->ConstructScript(ccg);

      stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
    }
  }
  if (!script.empty()) {
    script += lg->FinishConstructScript(this->ProjectType);
  }
  comment = cmVS10EscapeComment(comment);

  std::string strippedComment = comment;
  strippedComment.erase(
    std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
    strippedComment.end());
  std::ostringstream oss;
  if (!comment.empty() && !strippedComment.empty()) {
    oss << "echo " << comment << "\n";
  }
  oss << script << "\n";

  Elem e2(e1, "Exec");
  e2.Attribute("Command", oss.str());
}

void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
{
  cmGlobalGenerator::TargetDependSet const& unordered =
    this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
  using OrderedTargetDependSet =
    cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
  OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
  Elem e1(e0, "ItemGroup");
  e1.SetHasElements();
  for (cmGeneratorTarget const* dt : depends) {
    if (!dt->IsInBuildSystem()) {
      continue;
    }
    // skip fortran targets as they can not be processed by MSBuild
    // the only reference will be in the .sln file
    if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
      continue;
    }
    cmLocalGenerator* lg = dt->GetLocalGenerator();
    std::string name = dt->GetName();
    std::string path;
    if (cmValue p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
      path = *p;
    } else {
      path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
                      computeProjectFileExtension(dt));
    }
    ConvertToWindowsSlash(path);
    Elem e2(e1, "ProjectReference");
    e2.Attribute("Include", path);
    e2.Element("Project",
               cmStrCat('{', this->GlobalGenerator->GetGUID(name), '}'));
    e2.Element("Name", name);
    this->WriteDotNetReferenceCustomTags(e2, name);
    if (dt->IsCSharpOnly() || cmHasLiteralSuffix(path, "csproj")) {
      e2.Element("SkipGetTargetFrameworkProperties", "true");
    }
    // Don't reference targets that don't produce any output.
    else if (this->Configurations.empty() ||
             dt->GetManagedType(this->Configurations[0]) ==
               cmGeneratorTarget::ManagedType::Undefined) {
      e2.Element("ReferenceOutputAssembly", "false");
      e2.Element("CopyToOutputDirectory", "Never");
    }
  }
}

void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
{
  // This only applies to Windows 10 apps
  if (this->GlobalGenerator->TargetsWindowsStore() &&
      cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
    cmValue desktopExtensionsVersion =
      this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
    if (desktopExtensionsVersion) {
      this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
                                         *desktopExtensionsVersion);
    }
    cmValue mobileExtensionsVersion =
      this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
    if (mobileExtensionsVersion) {
      this->WriteSinglePlatformExtension(e1, "WindowsMobile",
                                         *mobileExtensionsVersion);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
  Elem& e1, std::string const& extension, std::string const& version)
{
  std::string const s =
    cmStrCat("$([Microsoft.Build.Utilities.ToolLocationHelper]"
             "::GetPlatformExtensionSDKLocation(`",
             extension, ", Version=", version,
             "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
             "$(ExtensionSDKDirectoryRoot), null))"
             "\\DesignTime\\CommonConfiguration\\Neutral\\",
             extension, ".props");

  Elem e2(e1, "Import");
  e2.Attribute("Project", s);
  e2.Attribute("Condition", cmStrCat("exists('", s, "')"));
}

void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
{
  cmList sdkReferences;
  std::unique_ptr<Elem> spe1;
  if (cmValue vsSDKReferences =
        this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
    sdkReferences.assign(*vsSDKReferences);
    spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
    for (auto const& ri : sdkReferences) {
      Elem(*spe1, "SDKReference").Attribute("Include", ri);
    }
  }

  // This only applies to Windows 10 apps
  if (this->GlobalGenerator->TargetsWindowsStore() &&
      cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
    cmValue desktopExtensionsVersion =
      this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
    cmValue mobileExtensionsVersion =
      this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
    cmValue iotExtensionsVersion =
      this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION");

    if (desktopExtensionsVersion || mobileExtensionsVersion ||
        iotExtensionsVersion) {
      if (!spe1) {
        spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
      }
      if (desktopExtensionsVersion) {
        this->WriteSingleSDKReference(*spe1, "WindowsDesktop",
                                      *desktopExtensionsVersion);
      }
      if (mobileExtensionsVersion) {
        this->WriteSingleSDKReference(*spe1, "WindowsMobile",
                                      *mobileExtensionsVersion);
      }
      if (iotExtensionsVersion) {
        this->WriteSingleSDKReference(*spe1, "WindowsIoT",
                                      *iotExtensionsVersion);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
  Elem& e1, std::string const& extension, std::string const& version)
{
  Elem(e1, "SDKReference")
    .Attribute("Include", cmStrCat(extension, ", Version=", version));
}

namespace {
std::string ComputeCertificateThumbprint(std::string const& source)
{
  std::string thumbprint;

  CRYPT_INTEGER_BLOB cryptBlob;
  HCERTSTORE certStore = nullptr;
  PCCERT_CONTEXT certContext = nullptr;

  HANDLE certFile = CreateFileW(
    cmsys::Encoding::ToWide(source.c_str()).c_str(), GENERIC_READ,
    FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

  if (certFile != INVALID_HANDLE_VALUE && certFile) {
    DWORD fileSize = GetFileSize(certFile, nullptr);
    if (fileSize != INVALID_FILE_SIZE) {
      auto certData = cm::make_unique<BYTE[]>(fileSize);
      if (certData) {
        DWORD dwRead = 0;
        if (ReadFile(certFile, certData.get(), fileSize, &dwRead, nullptr)) {
          cryptBlob.cbData = fileSize;
          cryptBlob.pbData = certData.get();

          // Verify that this is a valid cert
          if (PFXIsPFXBlob(&cryptBlob)) {
            // Open the certificate as a store
            certStore =
              PFXImportCertStore(&cryptBlob, nullptr, CRYPT_EXPORTABLE);
            if (certStore) {
              // There should only be 1 cert.
              certContext =
                CertEnumCertificatesInStore(certStore, certContext);
              if (certContext) {
                // The hash is 20 bytes
                BYTE hashData[20];
                DWORD hashLength = 20;

                // Buffer to print the hash. Each byte takes 2 chars +
                // terminating character
                char hashPrint[41];
                char* pHashPrint = hashPrint;
                // Get the hash property from the certificate
                if (CertGetCertificateContextProperty(
                      certContext, CERT_HASH_PROP_ID, hashData, &hashLength)) {
                  for (DWORD i = 0; i < hashLength; i++) {
                    // Convert each byte to hexadecimal
                    snprintf(pHashPrint, 3, "%02X", hashData[i]);
                    pHashPrint += 2;
                  }
                  *pHashPrint = '\0';
                  thumbprint = hashPrint;
                }
                CertFreeCertificateContext(certContext);
              }
              CertCloseStore(certStore, 0);
            }
          }
        }
      }
    }
    CloseHandle(certFile);
  }

  return thumbprint;
}
}

void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
  Elem& e0)
{
  if ((this->GlobalGenerator->TargetsWindowsStore() ||
       this->GlobalGenerator->TargetsWindowsPhone()) &&
      (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) {
    std::string pfxFile;
    for (cmGeneratorTarget::AllConfigSource const& source :
         this->GeneratorTarget->GetAllConfigSources()) {
      if (source.Kind == cmGeneratorTarget::SourceKindCertificate) {
        pfxFile = this->ConvertPath(source.Source->GetFullPath(), false);
        ConvertToWindowsSlash(pfxFile);
        break;
      }
    }

    if (this->IsMissingFiles &&
        !(this->GlobalGenerator->TargetsWindowsPhone() &&
          this->GlobalGenerator->GetSystemVersion() == "8.0"_s)) {
      // Move the manifest to a project directory to avoid clashes
      std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
        this->GeneratorTarget->GetSupportDirectory());
      ConvertToWindowsSlash(artifactDir);
      Elem e1(e0, "PropertyGroup");
      e1.Element("AppxPackageArtifactsDir", cmStrCat(artifactDir, '\\'));
      std::string resourcePriFile =
        cmStrCat(this->DefaultArtifactDir, "/resources.pri");
      ConvertToWindowsSlash(resourcePriFile);
      e1.Element("ProjectPriFullPath", resourcePriFile);

      // If we are missing files and we don't have a certificate and
      // aren't targeting WP8.0, add a default certificate
      if (pfxFile.empty()) {
        std::string templateFolder =
          cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/Windows");
        pfxFile =
          cmStrCat(this->DefaultArtifactDir, "/Windows_TemporaryKey.pfx");
        cmSystemTools::CopyAFile(
          cmStrCat(templateFolder, "/Windows_TemporaryKey.pfx"), pfxFile,
          false);
        ConvertToWindowsSlash(pfxFile);
        this->AddedFiles.push_back(pfxFile);
        this->AddedDefaultCertificate = true;
      }

      e1.Element("PackageCertificateKeyFile", pfxFile);
      std::string thumb = ComputeCertificateThumbprint(pfxFile);
      if (!thumb.empty()) {
        e1.Element("PackageCertificateThumbprint", thumb);
      }
    } else if (!pfxFile.empty()) {
      Elem e1(e0, "PropertyGroup");
      e1.Element("PackageCertificateKeyFile", pfxFile);
      std::string thumb = ComputeCertificateThumbprint(pfxFile);
      if (!thumb.empty()) {
        e1.Element("PackageCertificateThumbprint", thumb);
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::ClassifyAllConfigSources()
{
  for (cmGeneratorTarget::AllConfigSource const& source :
       this->GeneratorTarget->GetAllConfigSources()) {
    this->ClassifyAllConfigSource(source);
  }
}

void cmVisualStudio10TargetGenerator::ClassifyAllConfigSource(
  cmGeneratorTarget::AllConfigSource const& acs)
{
  switch (acs.Kind) {
    case cmGeneratorTarget::SourceKindResx: {
      // Build and save the name of the corresponding .h file
      // This relationship will be used later when building the project files.
      // Both names would have been auto generated from Visual Studio
      // where the user supplied the file name and Visual Studio
      // appended the suffix.
      std::string resx = acs.Source->ResolveFullPath();
      std::string hFileName =
        cmStrCat(resx.substr(0, resx.find_last_of('.')), ".h");
      this->ExpectedResxHeaders.insert(hFileName);
    } break;
    case cmGeneratorTarget::SourceKindXaml: {
      // Build and save the name of the corresponding .h and .cpp file
      // This relationship will be used later when building the project files.
      // Both names would have been auto generated from Visual Studio
      // where the user supplied the file name and Visual Studio
      // appended the suffix.
      std::string xaml = acs.Source->ResolveFullPath();
      std::string hFileName = cmStrCat(xaml, ".h");
      std::string cppFileName = cmStrCat(xaml, ".cpp");
      this->ExpectedXamlHeaders.insert(hFileName);
      this->ExpectedXamlSources.insert(cppFileName);
    } break;
    default:
      break;
  }
}

bool cmVisualStudio10TargetGenerator::IsResxHeader(
  std::string const& headerFile)
{
  return this->ExpectedResxHeaders.count(headerFile) > 0;
}

bool cmVisualStudio10TargetGenerator::IsXamlHeader(
  std::string const& headerFile)
{
  return this->ExpectedXamlHeaders.count(headerFile) > 0;
}

bool cmVisualStudio10TargetGenerator::IsXamlSource(
  std::string const& sourceFile)
{
  return this->ExpectedXamlSources.count(sourceFile) > 0;
}

void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
{
  cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
  bool isAppContainer = false;
  bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
  bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
  bool const isAndroid = this->GlobalGenerator->TargetsAndroid();
  std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision();
  if (isWindowsPhone || isWindowsStore) {
    e1.Element("ApplicationType",
               (isWindowsPhone ? "Windows Phone" : "Windows Store"));
    e1.Element("DefaultLanguage", "en-US");
    if (rev == "10.0"_s) {
      e1.Element("ApplicationTypeRevision", rev);
      // Visual Studio 14.0 is necessary for building 10.0 apps
      e1.Element("MinimumVisualStudioVersion", "14.0");

      if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
        isAppContainer = true;
      }
    } else if (rev == "8.1"_s) {
      e1.Element("ApplicationTypeRevision", rev);
      // Visual Studio 12.0 is necessary for building 8.1 apps
      e1.Element("MinimumVisualStudioVersion", "12.0");

      if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
        isAppContainer = true;
      }
    } else if (rev == "8.0"_s) {
      e1.Element("ApplicationTypeRevision", rev);
      // Visual Studio 11.0 is necessary for building 8.0 apps
      e1.Element("MinimumVisualStudioVersion", "11.0");

      if (isWindowsStore &&
          this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
        isAppContainer = true;
      } else if (isWindowsPhone &&
                 this->GeneratorTarget->GetType() ==
                   cmStateEnums::EXECUTABLE) {
        e1.Element("XapOutputs", "true");
        e1.Element("XapFilename",
                   cmStrCat(this->Name, "_$(Configuration)_$(Platform).xap"));
      }
    }
  } else if (isAndroid) {
    e1.Element("ApplicationType", "Android");
    e1.Element("ApplicationTypeRevision",
               gg->GetAndroidApplicationTypeRevision());
  }
  if (isAppContainer) {
    e1.Element("AppContainerApplication", "true");
  } else if (!isAndroid) {
    if (this->Platform == "ARM64"_s) {
      e1.Element("WindowsSDKDesktopARM64Support", "true");
    } else if (this->Platform == "ARM"_s) {
      e1.Element("WindowsSDKDesktopARMSupport", "true");
    }
  }
  std::string const& targetPlatformVersion =
    gg->GetWindowsTargetPlatformVersion();
  if (!targetPlatformVersion.empty()) {
    e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
  }
  cmValue targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
    "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
  if (targetPlatformMinVersion) {
    e1.Element("WindowsTargetPlatformMinVersion", *targetPlatformMinVersion);
  } else if (isWindowsStore && rev == "10.0"_s) {
    // If the min version is not set, then use the TargetPlatformVersion
    if (!targetPlatformVersion.empty()) {
      e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion);
    }
  }

  // Added IoT Startup Task support
  if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
    e1.Element("ContainsStartupTask", "true");
  }
}

void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
{
  // For Windows and Windows Phone executables, we will assume that if a
  // manifest is not present that we need to add all the necessary files
  if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
    std::vector<cmGeneratorTarget::AllConfigSource> manifestSources =
      this->GeneratorTarget->GetAllConfigSources(
        cmGeneratorTarget::SourceKindAppManifest);
    std::string const& v = this->GlobalGenerator->GetSystemVersion();
    if (this->GlobalGenerator->TargetsWindowsPhone()) {
      if (v == "8.0"_s) {
        // Look through the sources for WMAppManifest.xml
        bool foundManifest = false;
        for (cmGeneratorTarget::AllConfigSource const& source :
             this->GeneratorTarget->GetAllConfigSources()) {
          if (source.Kind == cmGeneratorTarget::SourceKindExtra &&
              "wmappmanifest.xml" ==
                cmSystemTools::LowerCase(
                  source.Source->GetLocation().GetName())) {
            foundManifest = true;
            break;
          }
        }
        if (!foundManifest) {
          this->IsMissingFiles = true;
        }
      } else if (v == "8.1"_s) {
        if (manifestSources.empty()) {
          this->IsMissingFiles = true;
        }
      }
    } else if (this->GlobalGenerator->TargetsWindowsStore()) {
      if (manifestSources.empty()) {
        if (v == "8.0"_s) {
          this->IsMissingFiles = true;
        } else if (v == "8.1"_s || cmHasLiteralPrefix(v, "10.0")) {
          this->IsMissingFiles = true;
        }
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteMissingFiles(Elem& e1)
{
  std::string const& v = this->GlobalGenerator->GetSystemVersion();
  if (this->GlobalGenerator->TargetsWindowsPhone()) {
    if (v == "8.0"_s) {
      this->WriteMissingFilesWP80(e1);
    } else if (v == "8.1"_s) {
      this->WriteMissingFilesWP81(e1);
    }
  } else if (this->GlobalGenerator->TargetsWindowsStore()) {
    if (v == "8.0"_s) {
      this->WriteMissingFilesWS80(e1);
    } else if (v == "8.1"_s) {
      this->WriteMissingFilesWS81(e1);
    } else if (cmHasLiteralPrefix(v, "10.0")) {
      this->WriteMissingFilesWS10_0(e1);
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
{
  std::string templateFolder =
    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/Windows");

  // For WP80, the manifest needs to be in the same folder as the project
  // this can cause an overwrite problem if projects aren't organized in
  // folders
  std::string manifestFile = cmStrCat(
    this->LocalGenerator->GetCurrentBinaryDirectory(), "/WMAppManifest.xml");
  std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->GeneratorTarget->GetSupportDirectory());
  ConvertToWindowsSlash(artifactDir);
  std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
  std::string const& targetNameXML = cmVS10EscapeXML(GetTargetOutputName());

  cmGeneratedFileStream fout(manifestFile);
  fout.SetCopyIfDifferent(true);

  /* clang-format off */
  fout <<
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    "<Deployment"
    " xmlns=\"http://schemas.microsoft.com/windowsphone/2012/deployment\""
    " AppPlatformVersion=\"8.0\">\n"
    "\t<DefaultLanguage xmlns=\"\" code=\"en-US\"/>\n"
    "\t<App xmlns=\"\" ProductID=\"{" << this->GUID << "}\""
    " Title=\"CMake Test Program\" RuntimeType=\"Modern Native\""
    " Version=\"1.0.0.0\" Genre=\"apps.normal\"  Author=\"CMake\""
    " Description=\"Default CMake App\" Publisher=\"CMake\""
    " PublisherID=\"{" << this->GUID << "}\">\n"
    "\t\t<IconPath IsRelative=\"true\" IsResource=\"false\">"
       << artifactDirXML << "\\ApplicationIcon.png</IconPath>\n"
    "\t\t<Capabilities/>\n"
    "\t\t<Tasks>\n"
    "\t\t\t<DefaultTask Name=\"_default\""
    " ImagePath=\"" << targetNameXML << ".exe\" ImageParams=\"\" />\n"
    "\t\t</Tasks>\n"
    "\t\t<Tokens>\n"
    "\t\t\t<PrimaryToken TokenID=\"" << targetNameXML << "Token\""
    " TaskName=\"_default\">\n"
    "\t\t\t\t<TemplateFlip>\n"
    "\t\t\t\t\t<SmallImageURI IsRelative=\"true\" IsResource=\"false\">"
       << artifactDirXML << "\\SmallLogo.png</SmallImageURI>\n"
    "\t\t\t\t\t<Count>0</Count>\n"
    "\t\t\t\t\t<BackgroundImageURI IsRelative=\"true\" IsResource=\"false\">"
       << artifactDirXML << "\\Logo.png</BackgroundImageURI>\n"
    "\t\t\t\t</TemplateFlip>\n"
    "\t\t\t</PrimaryToken>\n"
    "\t\t</Tokens>\n"
    "\t\t<ScreenResolutions>\n"
    "\t\t\t<ScreenResolution Name=\"ID_RESOLUTION_WVGA\" />\n"
    "\t\t</ScreenResolutions>\n"
    "\t</App>\n"
    "</Deployment>\n";
  /* clang-format on */

  std::string sourceFile = this->ConvertPath(manifestFile, false);
  ConvertToWindowsSlash(sourceFile);
  {
    Elem e2(e1, "Xml");
    e2.Attribute("Include", sourceFile);
    e2.Element("SubType", "Designer");
  }
  this->AddedFiles.push_back(sourceFile);

  std::string smallLogo = cmStrCat(this->DefaultArtifactDir, "/SmallLogo.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/SmallLogo.png"),
                           smallLogo, false);
  ConvertToWindowsSlash(smallLogo);
  Elem(e1, "Image").Attribute("Include", smallLogo);
  this->AddedFiles.push_back(smallLogo);

  std::string logo = cmStrCat(this->DefaultArtifactDir, "/Logo.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/Logo.png"), logo,
                           cmSystemTools::CopyWhen::OnlyIfDifferent);
  ConvertToWindowsSlash(logo);
  Elem(e1, "Image").Attribute("Include", logo);
  this->AddedFiles.push_back(logo);

  std::string applicationIcon =
    cmStrCat(this->DefaultArtifactDir, "/ApplicationIcon.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/ApplicationIcon.png"),
                           applicationIcon, false);
  ConvertToWindowsSlash(applicationIcon);
  Elem(e1, "Image").Attribute("Include", applicationIcon);
  this->AddedFiles.push_back(applicationIcon);
}

void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1)
{
  std::string manifestFile =
    cmStrCat(this->DefaultArtifactDir, "/package.appxManifest");
  std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->GeneratorTarget->GetSupportDirectory());
  ConvertToWindowsSlash(artifactDir);
  std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
  std::string const& targetNameXML = cmVS10EscapeXML(GetTargetOutputName());

  cmGeneratedFileStream fout(manifestFile);
  fout.SetCopyIfDifferent(true);

  /* clang-format off */
  fout <<
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
    " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\""
    " xmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\">\n"
    "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
    " Version=\"1.0.0.0\" />\n"
    "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << "\""
    " PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
    "\t<Properties>\n"
    "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
    "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
    "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
    "\t</Properties>\n"
    "\t<Prerequisites>\n"
    "\t\t<OSMinVersion>6.3.1</OSMinVersion>\n"
    "\t\t<OSMaxVersionTested>6.3.1</OSMaxVersionTested>\n"
    "\t</Prerequisites>\n"
    "\t<Resources>\n"
    "\t\t<Resource Language=\"x-generate\" />\n"
    "\t</Resources>\n"
    "\t<Applications>\n"
    "\t\t<Application Id=\"App\""
    " Executable=\"" << targetNameXML << ".exe\""
    " EntryPoint=\"" << targetNameXML << ".App\">\n"
    "\t\t\t<m2:VisualElements\n"
    "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
    "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
    "\t\t\t\tBackgroundColor=\"#336699\"\n"
    "\t\t\t\tForegroundText=\"light\"\n"
    "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
    "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
    "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
    "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
    "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
    "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
    "\t\t\t\t</m2:DefaultTile>\n"
    "\t\t\t\t<m2:SplashScreen"
    " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
    "\t\t\t</m2:VisualElements>\n"
    "\t\t</Application>\n"
    "\t</Applications>\n"
    "</Package>\n";
  /* clang-format on */

  this->WriteCommonMissingFiles(e1, manifestFile);
}

void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1)
{
  std::string manifestFile =
    cmStrCat(this->DefaultArtifactDir, "/package.appxManifest");
  std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->GeneratorTarget->GetSupportDirectory());
  ConvertToWindowsSlash(artifactDir);
  std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
  std::string const& targetNameXML = cmVS10EscapeXML(GetTargetOutputName());

  cmGeneratedFileStream fout(manifestFile);
  fout.SetCopyIfDifferent(true);

  /* clang-format off */
  fout <<
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\">\n"
    "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
    " Version=\"1.0.0.0\" />\n"
    "\t<Properties>\n"
    "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
    "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
    "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
    "\t</Properties>\n"
    "\t<Prerequisites>\n"
    "\t\t<OSMinVersion>6.2.1</OSMinVersion>\n"
    "\t\t<OSMaxVersionTested>6.2.1</OSMaxVersionTested>\n"
    "\t</Prerequisites>\n"
    "\t<Resources>\n"
    "\t\t<Resource Language=\"x-generate\" />\n"
    "\t</Resources>\n"
    "\t<Applications>\n"
    "\t\t<Application Id=\"App\""
    " Executable=\"" << targetNameXML << ".exe\""
    " EntryPoint=\"" << targetNameXML << ".App\">\n"
    "\t\t\t<VisualElements"
    " DisplayName=\"" << targetNameXML << "\""
    " Description=\"" << targetNameXML << "\""
    " BackgroundColor=\"#336699\" ForegroundText=\"light\""
    " Logo=\"" << artifactDirXML << "\\Logo.png\""
    " SmallLogo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
    "\t\t\t\t<DefaultTile ShowName=\"allLogos\""
    " ShortName=\"" << targetNameXML << "\" />\n"
    "\t\t\t\t<SplashScreen"
    " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
    "\t\t\t</VisualElements>\n"
    "\t\t</Application>\n"
    "\t</Applications>\n"
    "</Package>\n";
  /* clang-format on */

  this->WriteCommonMissingFiles(e1, manifestFile);
}

void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1)
{
  std::string manifestFile =
    cmStrCat(this->DefaultArtifactDir, "/package.appxManifest");
  std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->GeneratorTarget->GetSupportDirectory());
  ConvertToWindowsSlash(artifactDir);
  std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
  std::string const& targetNameXML = cmVS10EscapeXML(GetTargetOutputName());

  cmGeneratedFileStream fout(manifestFile);
  fout.SetCopyIfDifferent(true);

  /* clang-format off */
  fout <<
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    "<Package xmlns=\"http://schemas.microsoft.com/appx/2010/manifest\""
    " xmlns:m2=\"http://schemas.microsoft.com/appx/2013/manifest\">\n"
    "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
    " Version=\"1.0.0.0\" />\n"
    "\t<Properties>\n"
    "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
    "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
    "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
    "\t</Properties>\n"
    "\t<Prerequisites>\n"
    "\t\t<OSMinVersion>6.3</OSMinVersion>\n"
    "\t\t<OSMaxVersionTested>6.3</OSMaxVersionTested>\n"
    "\t</Prerequisites>\n"
    "\t<Resources>\n"
    "\t\t<Resource Language=\"x-generate\" />\n"
    "\t</Resources>\n"
    "\t<Applications>\n"
    "\t\t<Application Id=\"App\""
    " Executable=\"" << targetNameXML << ".exe\""
    " EntryPoint=\"" << targetNameXML << ".App\">\n"
    "\t\t\t<m2:VisualElements\n"
    "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
    "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
    "\t\t\t\tBackgroundColor=\"#336699\"\n"
    "\t\t\t\tForegroundText=\"light\"\n"
    "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
    "\t\t\t\tSquare30x30Logo=\"" << artifactDirXML << "\\SmallLogo.png\">\n"
    "\t\t\t\t<m2:DefaultTile ShortName=\"" << targetNameXML << "\">\n"
    "\t\t\t\t\t<m2:ShowNameOnTiles>\n"
    "\t\t\t\t\t\t<m2:ShowOn Tile=\"square150x150Logo\" />\n"
    "\t\t\t\t\t</m2:ShowNameOnTiles>\n"
    "\t\t\t\t</m2:DefaultTile>\n"
    "\t\t\t\t<m2:SplashScreen"
    " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
    "\t\t\t</m2:VisualElements>\n"
    "\t\t</Application>\n"
    "\t</Applications>\n"
    "</Package>\n";
  /* clang-format on */

  this->WriteCommonMissingFiles(e1, manifestFile);
}

void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1)
{
  std::string manifestFile =
    cmStrCat(this->DefaultArtifactDir, "/package.appxManifest");
  std::string artifactDir = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->GeneratorTarget->GetSupportDirectory());
  ConvertToWindowsSlash(artifactDir);
  std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
  std::string const& targetNameXML = cmVS10EscapeXML(GetTargetOutputName());

  cmGeneratedFileStream fout(manifestFile);
  fout.SetCopyIfDifferent(true);

  /* clang-format off */
  fout <<
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    "<Package\n\t"
    "xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\""
    "\txmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\n"
    "\txmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\""
    "\n\tIgnorableNamespaces=\"uap mp\">\n\n"
    "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\""
    " Version=\"1.0.0.0\" />\n"
    "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID <<
    "\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n"
    "\t<Properties>\n"
    "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n"
    "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n"
    "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n"
    "\t</Properties>\n"
    "\t<Dependencies>\n"
    "\t\t<TargetDeviceFamily Name=\"Windows.Universal\" "
    "MinVersion=\"10.0.0.0\" MaxVersionTested=\"10.0.0.0\" />\n"
    "\t</Dependencies>\n"

    "\t<Resources>\n"
    "\t\t<Resource Language=\"x-generate\" />\n"
    "\t</Resources>\n"
    "\t<Applications>\n"
    "\t\t<Application Id=\"App\""
    " Executable=\"" << targetNameXML << ".exe\""
    " EntryPoint=\"" << targetNameXML << ".App\">\n"
    "\t\t\t<uap:VisualElements\n"
    "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n"
    "\t\t\t\tDescription=\"" << targetNameXML << "\"\n"
    "\t\t\t\tBackgroundColor=\"#336699\"\n"
    "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n"
    "\t\t\t\tSquare44x44Logo=\"" << artifactDirXML <<
    "\\SmallLogo44x44.png\">\n"
    "\t\t\t\t<uap:SplashScreen"
    " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n"
    "\t\t\t</uap:VisualElements>\n"
    "\t\t</Application>\n"
    "\t</Applications>\n"
    "</Package>\n";
  /* clang-format on */

  this->WriteCommonMissingFiles(e1, manifestFile);
}

void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
  Elem& e1, std::string const& manifestFile)
{
  std::string templateFolder =
    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Templates/Windows");

  std::string sourceFile = this->ConvertPath(manifestFile, false);
  ConvertToWindowsSlash(sourceFile);
  {
    Elem e2(e1, "AppxManifest");
    e2.Attribute("Include", sourceFile);
    e2.Element("SubType", "Designer");
  }
  this->AddedFiles.push_back(sourceFile);

  std::string smallLogo = cmStrCat(this->DefaultArtifactDir, "/SmallLogo.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/SmallLogo.png"),
                           smallLogo, false);
  ConvertToWindowsSlash(smallLogo);
  Elem(e1, "Image").Attribute("Include", smallLogo);
  this->AddedFiles.push_back(smallLogo);

  std::string smallLogo44 =
    cmStrCat(this->DefaultArtifactDir, "/SmallLogo44x44.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/SmallLogo44x44.png"),
                           smallLogo44, false);
  ConvertToWindowsSlash(smallLogo44);
  Elem(e1, "Image").Attribute("Include", smallLogo44);
  this->AddedFiles.push_back(smallLogo44);

  std::string logo = cmStrCat(this->DefaultArtifactDir, "/Logo.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/Logo.png"), logo,
                           cmSystemTools::CopyWhen::OnlyIfDifferent);
  ConvertToWindowsSlash(logo);
  Elem(e1, "Image").Attribute("Include", logo);
  this->AddedFiles.push_back(logo);

  std::string storeLogo = cmStrCat(this->DefaultArtifactDir, "/StoreLogo.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/StoreLogo.png"),
                           storeLogo, false);
  ConvertToWindowsSlash(storeLogo);
  Elem(e1, "Image").Attribute("Include", storeLogo);
  this->AddedFiles.push_back(storeLogo);

  std::string splashScreen =
    cmStrCat(this->DefaultArtifactDir, "/SplashScreen.png");
  cmSystemTools::CopyAFile(cmStrCat(templateFolder, "/SplashScreen.png"),
                           splashScreen, false);
  ConvertToWindowsSlash(splashScreen);
  Elem(e1, "Image").Attribute("Include", splashScreen);
  this->AddedFiles.push_back(splashScreen);

  if (this->AddedDefaultCertificate) {
    // This file has already been added to the build so don't copy it
    std::string keyFile =
      cmStrCat(this->DefaultArtifactDir, "/Windows_TemporaryKey.pfx");
    ConvertToWindowsSlash(keyFile);
    Elem(e1, "None").Attribute("Include", keyFile);
  }
}

bool cmVisualStudio10TargetGenerator::ForceOld(std::string const& source) const
{
  HANDLE h =
    CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(source).c_str(),
                FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING,
                FILE_FLAG_BACKUP_SEMANTICS, 0);
  if (!h) {
    return false;
  }

  FILETIME const ftime_20010101 = { 3365781504u, 29389701u };
  if (!SetFileTime(h, &ftime_20010101, &ftime_20010101, &ftime_20010101)) {
    CloseHandle(h);
    return false;
  }

  CloseHandle(h);
  return true;
}

void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
  cmSourceFile const* sf, std::map<std::string, std::string>& tags)
{
  if (this->ProjectType == VsProjectType::csproj) {
    cmPropertyMap const& props = sf->GetProperties();
    for (std::string const& p : props.GetKeys()) {
      static cm::string_view const propNamePrefix = "VS_CSHARP_";
      if (cmHasPrefix(p, propNamePrefix)) {
        std::string tagName = p.substr(propNamePrefix.length());
        if (!tagName.empty()) {
          cmValue val = props.GetPropertyValue(p);
          if (cmNonempty(val)) {
            tags[tagName] = *val;
          } else {
            tags.erase(tagName);
          }
        }
      }
    }
  }
}

void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
  Elem& e2, std::map<std::string, std::string> const& tags)
{
  for (auto const& i : tags) {
    e2.Element(i.first, i.second);
  }
}

std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
  cmSourceFile const* source)
{
  // For out of source files, we first check if a matching source group
  // for this file exists, otherwise we check if the path relative to current
  // source- or binary-dir is used within the link and return that.
  // In case of .cs files we can't do that automatically for files in the
  // binary directory, because this leads to compilation errors.
  std::string link;
  std::string sourceGroupedFile;
  std::string const& fullFileName = source->GetFullPath();
  std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory();
  std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory();
  // unfortunately we have to copy the source groups, because
  // FindSourceGroup uses a regex which is modifying the group
  std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
  cmSourceGroup* sourceGroup =
    this->Makefile->FindSourceGroup(fullFileName, sourceGroups);
  if (sourceGroup && !sourceGroup->GetFullName().empty()) {
    sourceGroupedFile =
      cmStrCat(sourceGroup->GetFullName(), '/',
               cmsys::SystemTools::GetFilenameName(fullFileName));
    cmsys::SystemTools::ConvertToUnixSlashes(sourceGroupedFile);
  }

  if (!sourceGroupedFile.empty() &&
      cmHasSuffix(fullFileName, sourceGroupedFile)) {
    link = sourceGroupedFile;
  } else if (cmHasPrefix(fullFileName, srcDir)) {
    link = fullFileName.substr(srcDir.length() + 1);
  } else if (!cmHasSuffix(fullFileName, ".cs") &&
             cmHasPrefix(fullFileName, binDir)) {
    link = fullFileName.substr(binDir.length() + 1);
  } else if (cmValue l = source->GetProperty("VS_CSHARP_Link")) {
    link = *l;
  }

  ConvertToWindowsSlash(link);
  return link;
}

std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
  char const* relativeFilePath) const
{
  // Always search in the standard modules location.
  std::string path =
    cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath);
  ConvertToWindowsSlash(path);

  return path;
}

void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
{
  if (this->GlobalGenerator->IsUtf8EncodingSupported()) {
    e1.Element("UseUtf8Encoding", "Always");
  } else if (this->GlobalGenerator->IsStdOutEncodingSupported()) {
    e1.Element("StdOutEncoding", "UTF-8");
  }
}

void cmVisualStudio10TargetGenerator::UpdateCache()
{
  std::vector<std::string> packageReferences;

  if (this->GeneratorTarget->IsDotNetSdkTarget() ||
      this->GeneratorTarget->HasPackageReferences()) {
    // Store a cache entry that later determines, if a package restore is
    // required.
    this->GeneratorTarget->Makefile->AddCacheDefinition(
      cmStrCat(this->GeneratorTarget->GetName(),
               "_REQUIRES_VS_PACKAGE_RESTORE"),
      "ON", "Value Computed by CMake", cmStateEnums::STATIC);
  } else {
    // If there are any dependencies that require package restore, inherit the
    // cache variable.
    cmGlobalGenerator::TargetDependSet const& unordered =
      this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
    using OrderedTargetDependSet =
      cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
    OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);

    for (cmGeneratorTarget const* dt : depends) {
      if (dt->IsDotNetSdkTarget() || dt->HasPackageReferences()) {
        this->GeneratorTarget->Makefile->AddCacheDefinition(
          cmStrCat(this->GeneratorTarget->GetName(),
                   "_REQUIRES_VS_PACKAGE_RESTORE"),
          "ON", "Value Computed by CMake", cmStateEnums::STATIC);
      }
    }
  }
}
