void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile()

in Source/cmVisualStudio10TargetGenerator.cxx [470:895]


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