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

#include <algorithm>
#include <array>
#include <cassert>
#include <cstdio>
#include <functional>
#include <iterator>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <utility>

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

#include "cm_codecvt_Encoding.hxx"

#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmMakefileExecutableTargetGenerator.h"
#include "cmMakefileLibraryTargetGenerator.h"
#include "cmMakefileUtilityTargetGenerator.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"

cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
  : cmCommonTargetGenerator(target)
{
  this->CustomCommandDriver = OnBuild;
  this->LocalGenerator =
    static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator());
  this->GlobalGenerator = static_cast<cmGlobalUnixMakefileGenerator3*>(
    this->LocalGenerator->GetGlobalGenerator());
  cmake* cm = this->GlobalGenerator->GetCMakeInstance();
  this->NoRuleMessages = false;
  if (cmValue ruleStatus =
        cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) {
    this->NoRuleMessages = ruleStatus.IsOff();
  }
  switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) {
    case cmPolicies::WARN:
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      this->CMP0113New = false;
      break;
    case cmPolicies::NEW:
      this->CMP0113New = true;
      break;
  }
  this->MacOSXContentGenerator =
    cm::make_unique<MacOSXContentGeneratorType>(this);
}

cmMakefileTargetGenerator::~cmMakefileTargetGenerator() = default;

std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
  cmGeneratorTarget* tgt)
{
  std::unique_ptr<cmMakefileTargetGenerator> result;

  switch (tgt->GetType()) {
    case cmStateEnums::EXECUTABLE:
      result = cm::make_unique<cmMakefileExecutableTargetGenerator>(tgt);
      break;
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
    case cmStateEnums::OBJECT_LIBRARY:
      result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt);
      break;
    case cmStateEnums::INTERFACE_LIBRARY:
    case cmStateEnums::UTILITY:
      result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt);
      break;
    default:
      return result;
      // break; /* unreachable */
  }
  return result;
}

std::string const& cmMakefileTargetGenerator::GetConfigName() const
{
  auto const& configNames = this->LocalGenerator->GetConfigNames();
  assert(configNames.size() == 1);
  return configNames.front();
}

void cmMakefileTargetGenerator::GetDeviceLinkFlags(
  std::string& linkFlags, std::string const& linkLanguage)
{
  cmGeneratorTarget::DeviceLinkSetter setter(*this->GetGeneratorTarget());

  std::vector<std::string> linkOpts;
  this->GeneratorTarget->GetLinkOptions(linkOpts, this->GetConfigName(),
                                        linkLanguage);
  this->LocalGenerator->SetLinkScriptShell(
    this->GlobalGenerator->GetUseLinkScript());
  // LINK_OPTIONS are escaped.
  this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts);
  this->LocalGenerator->SetLinkScriptShell(false);
}

void cmMakefileTargetGenerator::GetTargetLinkFlags(
  std::string& flags, std::string const& linkLanguage)
{
  this->LocalGenerator->AddTargetPropertyLinkFlags(
    flags, this->GeneratorTarget, this->GetConfigName());

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

  this->LocalGenerator->AppendLinkerTypeFlags(
    flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
  this->LocalGenerator->AppendPositionIndependentLinkerFlags(
    flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
  this->LocalGenerator->AppendWarningAsErrorLinkerFlags(
    flags, this->GeneratorTarget, linkLanguage);
  this->LocalGenerator->AppendDependencyInfoLinkerFlags(
    flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
}

void cmMakefileTargetGenerator::CreateRuleFile()
{
  // Create a directory for this target.
  this->TargetBuildDirectoryFull =
    this->GeneratorTarget->GetSupportDirectory();
  this->TargetBuildDirectory = this->LocalGenerator->MaybeRelativeToCurBinDir(
    this->TargetBuildDirectoryFull);
  cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull);

  // Construct the rule file name.
  this->BuildFileName = cmStrCat(this->TargetBuildDirectory, "/build.make");
  this->BuildFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, "/build.make");

  // Construct the rule file name.
  this->ProgressFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, "/progress.make");

  // reset the progress count
  this->NumberOfProgressActions = 0;

  // Open the rule file.  This should be copy-if-different because the
  // rules may depend on this file itself.
  this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>(
    this->BuildFileNameFull, false,
    this->GlobalGenerator->GetMakefileEncoding());
  if (!this->BuildFileStream) {
    return;
  }
  this->BuildFileStream->SetCopyIfDifferent(true);
  this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
  if (this->GlobalGenerator->AllowDeleteOnError()) {
    std::vector<std::string> no_depends;
    std::vector<std::string> no_commands;
    this->LocalGenerator->WriteMakeRule(
      *this->BuildFileStream, "Delete rule output on recipe failure.",
      ".DELETE_ON_ERROR", no_depends, no_commands, false);
  }
  this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
}

void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
  cm::GenEx::Context context(this->LocalGenerator, this->GetConfigName());
  this->GeneratorTarget->CheckCxxModuleStatus(this->GetConfigName());

  // -- Write the custom commands for this target

  // Evaluates generator expressions and expands prop_value
  auto evaluatedFiles = [this](std::string const& prop_value) -> cmList {
    cmList files{ cmGeneratorExpression::Evaluate(
      prop_value, this->LocalGenerator, this->GetConfigName(),
      this->GeneratorTarget) };
    return files;
  };

  // Look for additional files registered for cleaning in this directory.
  if (cmValue prop_value =
        this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) {
    auto const files = evaluatedFiles(*prop_value);
    this->CleanFiles.insert(files.begin(), files.end());
  }

  // Look for additional files registered for cleaning in this target.
  if (cmValue prop_value =
        this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
    auto const files = evaluatedFiles(*prop_value);
    // For relative path support
    std::string const& binaryDir =
      this->LocalGenerator->GetCurrentBinaryDirectory();
    for (std::string const& cfl : files) {
      this->CleanFiles.insert(cmSystemTools::CollapseFullPath(cfl, binaryDir));
    }
  }

  // Look for ISPC extra object files generated by this target
  auto const ispcAdditionalObjs =
    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
  for (auto const& ispcObj : ispcAdditionalObjs) {
    this->CleanFiles.insert(
      this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj.second));
  }

  // add custom commands to the clean rules?
  bool const clean = this->Makefile->GetProperty("CLEAN_NO_CUSTOM").IsOff();

  // First generate the object rule files.  Save a list of all object
  // files for this target.
  std::vector<cmSourceFile const*> customCommands;
  this->GeneratorTarget->GetCustomCommands(customCommands,
                                           this->GetConfigName());
  std::vector<std::string> codegen_depends;
  codegen_depends.reserve(customCommands.size());
  for (cmSourceFile const* sf : customCommands) {
    if (this->CMP0113New &&
        !this->LocalGenerator->GetCommandsVisited(this->GeneratorTarget)
           .insert(sf)
           .second) {
      continue;
    }
    cmCustomCommandGenerator ccg(*sf->GetCustomCommand(),
                                 this->GetConfigName(), this->LocalGenerator);
    this->GenerateCustomRuleFile(ccg);
    if (clean) {
      std::vector<std::string> const& outputs = ccg.GetOutputs();
      for (std::string const& output : outputs) {
        this->CleanFiles.insert(
          this->LocalGenerator->MaybeRelativeToCurBinDir(output));
      }
      std::vector<std::string> const& byproducts = ccg.GetByproducts();
      for (std::string const& byproduct : byproducts) {
        this->CleanFiles.insert(
          this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
      }
    }

    if (ccg.GetCC().GetCodegen()) {
      std::string const& output = ccg.GetOutputs().front();

      // We always attach the actual commands to the first output.
      codegen_depends.emplace_back(output);
    }
  }

  // Some make tools need a special dependency for an empty rule.
  if (codegen_depends.empty()) {
    std::string hack = this->GlobalGenerator->GetEmptyRuleHackDepends();
    if (!hack.empty()) {
      codegen_depends.emplace_back(std::move(hack));
    }
  }

  // Construct the codegen target.
  {
    std::string const codegenTarget = cmStrCat(
      this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
      "/codegen");

    // Write the rule.
    this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                        codegenTarget, codegen_depends, {},
                                        true);
  }

  // Add byproducts from build events to the clean rules
  if (clean) {
    std::vector<cmCustomCommand> buildEventCommands =
      this->GeneratorTarget->GetPreBuildCommands();

    cm::append(buildEventCommands,
               this->GeneratorTarget->GetPreLinkCommands());
    cm::append(buildEventCommands,
               this->GeneratorTarget->GetPostBuildCommands());

    for (auto const& be : buildEventCommands) {
      cmCustomCommandGenerator beg(be, this->GetConfigName(),
                                   this->LocalGenerator);
      std::vector<std::string> const& byproducts = beg.GetByproducts();
      for (std::string const& byproduct : byproducts) {
        this->CleanFiles.insert(
          this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
      }
    }
  }
  std::vector<cmSourceFile const*> headerSources;
  this->GeneratorTarget->GetHeaderSources(headerSources,
                                          this->GetConfigName());
  this->OSXBundleGenerator->GenerateMacOSXContentStatements(
    headerSources, this->MacOSXContentGenerator.get(), this->GetConfigName());
  std::vector<cmSourceFile const*> extraSources;
  this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName());
  this->OSXBundleGenerator->GenerateMacOSXContentStatements(
    extraSources, this->MacOSXContentGenerator.get(), this->GetConfigName());
  cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
  std::vector<cmSourceFile const*> externalObjects;
  this->GeneratorTarget->GetExternalObjects(externalObjects,
                                            this->GetConfigName());
  for (cmSourceFile const* sf : externalObjects) {
    auto const& objectFileName = sf->GetFullPath();
    if (!cmHasSuffix(objectFileName, pchExtension)) {
      this->ExternalObjects.push_back(objectFileName);
    }
  }

  std::vector<cmSourceFile const*> objectSources;
  this->GeneratorTarget->GetObjectSources(objectSources,
                                          this->GetConfigName());

  // validate that all languages requested are enabled.
  std::set<std::string> requiredLangs;
  if (this->HaveRequiredLanguages(objectSources, requiredLangs)) {
    for (cmSourceFile const* sf : objectSources) {
      // Generate this object file's rule file.
      this->WriteObjectRuleFiles(*sf);
    }
  }

  for (cmSourceFile const* sf : objectSources) {
    cmGeneratorFileSet const* fileSet =
      this->GeneratorTarget->GetFileSetForSource(this->GetConfigName(), sf);
    if (fileSet && fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES &&
        sf->GetLanguage() != "CXX"_s) {
      this->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Target \"", this->GeneratorTarget->GetName(),
                 "\" contains the source\n  ", sf->GetFullPath(),
                 "\nin a file set of type \"",
                 cm::FileSetMetadata::CXX_MODULES,
                 R"(" but the source is not classified as a "CXX" source.)"));
    }
  }
}

void cmMakefileTargetGenerator::WriteCommonCodeRules()
{
  char const* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
                        ? "$(CMAKE_BINARY_DIR)/"
                        : "");

  // Include the dependencies for the target.
  std::string dependFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, "/depend.make");
  *this->BuildFileStream
    << "# Include any dependencies generated for this target.\n"
    << this->GlobalGenerator->IncludeDirective << " " << root
    << cmSystemTools::ConvertToOutputPath(
         this->LocalGenerator->MaybeRelativeToTopBinDir(dependFileNameFull))
    << "\n";

  // Scan any custom commands to check if DEPFILE option is specified
  bool ccGenerateDeps = false;
  std::vector<cmSourceFile const*> customCommands;
  this->GeneratorTarget->GetCustomCommands(customCommands,
                                           this->GetConfigName());
  for (cmSourceFile const* sf : customCommands) {
    if (!sf->GetCustomCommand()->GetDepfile().empty()) {
      ccGenerateDeps = true;
      break;
    }
  }

  std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER";
  bool compilerGenerateDeps =
    this->GlobalGenerator->SupportsCompilerDependencies() &&
    (!this->Makefile->IsDefinitionSet(depsUseCompiler) ||
     this->Makefile->IsOn(depsUseCompiler));
  bool linkerGenerateDeps =
    this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName());

  if (compilerGenerateDeps || linkerGenerateDeps || ccGenerateDeps) {
    std::string const compilerDependFile =
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
    *this->BuildFileStream << "# Include any dependencies generated by the "
                              "compiler for this target.\n"
                           << this->GlobalGenerator->IncludeDirective << " "
                           << root
                           << cmSystemTools::ConvertToOutputPath(
                                this->LocalGenerator->MaybeRelativeToTopBinDir(
                                  compilerDependFile))
                           << "\n\n";

    // Write an empty dependency file.
    cmGeneratedFileStream depFileStream(
      compilerDependFile, false, this->GlobalGenerator->GetMakefileEncoding());
    depFileStream << "# Empty compiler generated dependencies file for "
                  << this->GeneratorTarget->GetName() << ".\n"
                  << "# This may be replaced when dependencies are built.\n";
    // remove internal dependency file
    cmSystemTools::RemoveFile(
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.internal"));

    std::string compilerDependTimestamp =
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
    if (!cmSystemTools::FileExists(compilerDependTimestamp)) {
      // Write a dependency timestamp file.
      cmGeneratedFileStream timestampFileStream(
        compilerDependTimestamp, false,
        this->GlobalGenerator->GetMakefileEncoding());
      timestampFileStream
        << "# CMAKE generated file: DO NOT EDIT!\n"
        << "# Timestamp file for compiler generated dependencies "
           "management for "
        << this->GeneratorTarget->GetName() << ".\n";
    }
  }

  if (compilerGenerateDeps) {
    // deactivate no longer needed legacy dependency files
    // Write an empty dependency file.
    cmGeneratedFileStream legacyDepFileStream(
      dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
    legacyDepFileStream
      << "# Empty dependencies file for " << this->GeneratorTarget->GetName()
      << ".\n"
      << "# This may be replaced when dependencies are built.\n";
    // remove internal dependency file
    cmSystemTools::RemoveFile(
      cmStrCat(this->TargetBuildDirectoryFull, "/depend.internal"));
  } else {
    // make sure the depend file exists
    if (!cmSystemTools::FileExists(dependFileNameFull)) {
      // Write an empty dependency file.
      cmGeneratedFileStream depFileStream(
        dependFileNameFull, false,
        this->GlobalGenerator->GetMakefileEncoding());
      depFileStream << "# Empty dependencies file for "
                    << this->GeneratorTarget->GetName() << ".\n"
                    << "# This may be replaced when dependencies are built.\n";
    }
  }

  if (!this->NoRuleMessages) {
    // Include the progress variables for the target.
    *this->BuildFileStream
      << "# Include the progress variables for this target.\n"
      << this->GlobalGenerator->IncludeDirective << " " << root
      << cmSystemTools::ConvertToOutputPath(
           this->LocalGenerator->MaybeRelativeToTopBinDir(
             this->ProgressFileNameFull))
      << "\n\n";
  }

  // Open the flags file.  This should be copy-if-different because the
  // rules may depend on this file itself.
  this->FlagFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, "/flags.make");
  this->FlagFileStream = cm::make_unique<cmGeneratedFileStream>(
    this->FlagFileNameFull, false,
    this->GlobalGenerator->GetMakefileEncoding());
  if (!this->FlagFileStream) {
    return;
  }
  this->FlagFileStream->SetCopyIfDifferent(true);
  this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);

  // Include the flags for the target.
  *this->BuildFileStream
    << "# Include the compile flags for this target's objects.\n"
    << this->GlobalGenerator->IncludeDirective << " " << root
    << cmSystemTools::ConvertToOutputPath(
         this->LocalGenerator->MaybeRelativeToTopBinDir(
           this->FlagFileNameFull))
    << "\n\n";
}

void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
{
  // write language flags for target
  std::set<std::string> languages;
  this->GeneratorTarget->GetLanguages(
    languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
  // put the compiler in the rules.make file so that if it changes
  // things rebuild
  for (std::string const& language : languages) {
    std::string compiler = cmStrCat("CMAKE_", language, "_COMPILER");
    *this->FlagFileStream << "# compile " << language << " with "
                          << this->Makefile->GetSafeDefinition(compiler)
                          << "\n";
  }

  bool const escapeOctothorpe = this->GlobalGenerator->CanEscapeOctothorpe();

  for (std::string const& language : languages) {
    std::string defines = this->GetDefines(language, this->GetConfigName());
    std::string includes = this->GetIncludes(language, this->GetConfigName());
    if (escapeOctothorpe) {
      // Escape comment characters so they do not terminate assignment.
      cmSystemTools::ReplaceString(defines, "#", "\\#");
      cmSystemTools::ReplaceString(includes, "#", "\\#");
    }
    *this->FlagFileStream << language << "_DEFINES = " << defines << "\n\n";
    *this->FlagFileStream << language << "_INCLUDES = " << includes << "\n\n";

    std::vector<std::string> architectures =
      this->GeneratorTarget->GetAppleArchs(this->GetConfigName(), language);
    architectures.emplace_back();

    for (std::string const& arch : architectures) {
      std::string flags =
        this->GetFlags(language, this->GetConfigName(), arch);
      if (escapeOctothorpe) {
        cmSystemTools::ReplaceString(flags, "#", "\\#");
      }
      *this->FlagFileStream << language << "_FLAGS" << arch << " = " << flags
                            << "\n\n";
    }
  }
}

void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
  cmSourceFile const& source, char const* pkgloc, std::string const& config)
{
  // Skip OS X content when not building a Framework or Bundle.
  if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) {
    return;
  }

  std::string macdir =
    this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc,
                                                                    config);

  // Get the input file location.
  std::string const& input = source.GetFullPath();

  // Get the output file location.
  std::string output =
    cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
  this->Generator->CleanFiles.insert(
    this->Generator->LocalGenerator->MaybeRelativeToCurBinDir(output));
  output = this->Generator->LocalGenerator->MaybeRelativeToTopBinDir(output);

  // Create a rule to copy the content into the bundle.
  std::vector<std::string> depends;
  std::vector<std::string> commands;
  depends.push_back(input);
  std::string copyEcho = cmStrCat("Copying OS X content ", output);
  this->Generator->LocalGenerator->AppendEcho(
    commands, copyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
  std::string copyCommand =
    cmStrCat(cmSystemTools::FileIsDirectory(input)
               ? "$(CMAKE_COMMAND) -E copy_directory "
               : "$(CMAKE_COMMAND) -E copy ",
             this->Generator->LocalGenerator->ConvertToOutputFormat(
               input, cmOutputConverter::SHELL),
             ' ',
             this->Generator->LocalGenerator->ConvertToOutputFormat(
               output, cmOutputConverter::SHELL));
  commands.push_back(std::move(copyCommand));
  this->Generator->LocalGenerator->WriteMakeRule(
    *this->Generator->BuildFileStream, nullptr, output, depends, commands,
    false);
  this->Generator->ExtraFiles.insert(output);
}

void cmMakefileTargetGenerator::WriteObjectRuleFiles(
  cmSourceFile const& source)
{
  // Identify the language of the source file.
  std::string const& lang = source.GetLanguage();
  if (lang.empty()) {
    // don't know anything about this file so skip it
    return;
  }

  // Use compiler to generate dependencies, if supported.
  bool const compilerGenerateDeps =
    this->GlobalGenerator->SupportsCompilerDependencies() &&
    this->Makefile
      ->GetDefinition(cmStrCat("CMAKE_", lang, "_DEPENDS_USE_COMPILER"))
      .IsOn();
  auto const scanner = compilerGenerateDeps ? cmDependencyScannerKind::Compiler
                                            : cmDependencyScannerKind::CMake;

  // Get the full path name of the object file.
  std::string const& objectName =
    this->GeneratorTarget->GetObjectName(&source);
  std::string const obj =
    cmStrCat(this->TargetBuildDirectory, '/', objectName);

  // Avoid generating duplicate rules.
  if (this->ObjectFiles.find(obj) == this->ObjectFiles.end()) {
    this->ObjectFiles.insert(obj);
  } else {
    std::ostringstream err;
    err << "Warning: Source file \"" << source.GetFullPath()
        << "\" is listed multiple times for target \""
        << this->GeneratorTarget->GetName() << "\".";
    cmSystemTools::Message(err.str(), "Warning");
    return;
  }

  // Create the directory containing the object file.  This may be a
  // subdirectory under the target's directory.
  {
    std::string const dir = cmSystemTools::GetFilenamePath(obj);
    cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir));
  }

  // Save this in the target's list of object files.
  this->Objects.push_back(obj);
  this->CleanFiles.insert(obj);

  std::vector<std::string> depends;

  // The object file should be checked for dependency integrity.
  std::string objFullPath =
    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj);
  std::string const srcFullPath = source.GetFullPath();
  this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
                                           objFullPath, srcFullPath, scanner);

  this->LocalGenerator->AppendRuleDepend(depends,
                                         this->FlagFileNameFull.c_str());
  this->LocalGenerator->AppendRuleDepends(depends,
                                          this->FlagFileDepends[lang]);

  // generate the depend scanning rule
  this->WriteObjectDependRules(source, depends);

  std::string const config = this->GetConfigName();
  std::string const configUpper = cmSystemTools::UpperCase(config);

  // lookup for the associated file set, if any.
  auto const* fileSet =
    this->GeneratorTarget->GetFileSetForSource(config, &source);

  // Add precompile headers dependencies
  std::vector<std::string> pchArchs =
    this->GeneratorTarget->GetPchArchs(config, lang);

  std::string filterArch;
  std::unordered_map<std::string, std::string> pchSources;
  for (std::string const& arch : pchArchs) {
    std::string const pchSource =
      this->GeneratorTarget->GetPchSource(config, lang, arch);
    if (pchSource == source.GetFullPath()) {
      filterArch = arch;
    }
    if (!pchSource.empty()) {
      pchSources.insert(std::make_pair(pchSource, arch));
    }
  }

  if (!pchSources.empty() &&
      !((fileSet && fileSet->GetProperty("SKIP_PRECOMPILE_HEADERS")) ||
        source.GetProperty("SKIP_PRECOMPILE_HEADERS"))) {
    for (std::string const& arch : pchArchs) {
      std::string const& pchHeader =
        this->GeneratorTarget->GetPchHeader(config, lang, arch);
      depends.push_back(pchHeader);
      if (pchSources.find(source.GetFullPath()) == pchSources.end()) {
        depends.push_back(
          this->GeneratorTarget->GetPchFile(config, lang, arch));
      }
      this->LocalGenerator->AddImplicitDepends(
        this->GeneratorTarget, lang, objFullPath, pchHeader, scanner);
    }
  }

  if (lang != "ISPC") {
    auto const& headers =
      this->GeneratorTarget->GetGeneratedISPCHeaders(config);
    if (!headers.empty()) {
      depends.insert(depends.end(), headers.begin(), headers.end());
    }
  }

  std::string relativeObj =
    cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj);
  // Write the build rule.

  // Build the set of compiler flags.
  std::string flags;

  // Explicitly add the explicit language flag before any other flag
  // so user flags can override it.
  this->GeneratorTarget->AddExplicitLanguageFlags(flags, source);

  // Add language-specific flags.
  std::string const langFlags =
    cmStrCat("$(", lang, "_FLAGS", filterArch, ')');
  this->LocalGenerator->AppendFlags(flags, langFlags);

  cmGeneratorExpressionInterpreter genexInterpreter(
    this->LocalGenerator, config, this->GeneratorTarget, lang);

  // Add Fortran format flags.
  if (lang == "Fortran") {
    this->AppendFortranFormatFlags(flags, source);
    this->AppendFortranPreprocessFlags(flags, source);
  }

  std::string ispcHeaderRelative;
  std::string ispcHeaderForShell;
  if (lang == "ISPC") {
    std::string ispcSource =
      cmSystemTools::GetFilenameWithoutLastExtension(objectName);
    ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource);

    cmValue const ispcSuffixProp =
      this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX");
    assert(ispcSuffixProp);

    std::string directory = this->GeneratorTarget->GetObjectDirectory(config);
    if (cmValue prop =
          this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) {
      directory =
        cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop);
    }
    ispcHeaderRelative = cmStrCat(directory, '/', ispcSource, *ispcSuffixProp);
    ispcHeaderForShell = this->LocalGenerator->ConvertToOutputFormat(
      ispcHeaderRelative, cmOutputConverter::SHELL);
  }

  // Add flags from source file properties.
  std::string const COMPILE_FLAGS("COMPILE_FLAGS");
  if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) {
    std::string const& evaluatedFlags =
      genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
    this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
    *this->FlagFileStream << "# Custom flags: " << relativeObj
                          << "_FLAGS = " << evaluatedFlags << "\n"
                          << "\n";
  }

  std::string const COMPILE_OPTIONS("COMPILE_OPTIONS");
  if (cmValue coptions = source.GetProperty(COMPILE_OPTIONS)) {
    std::string const& evaluatedOptions =
      genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS);
    this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
    *this->FlagFileStream << "# Custom options: " << relativeObj
                          << "_OPTIONS = " << evaluatedOptions << "\n"
                          << "\n";
  }

  // Add flags from file set properties.
  if (fileSet) {
    auto options = fileSet->BelongsTo(this->GeneratorTarget)
      ? fileSet->GetCompileOptions(config, lang)
      : fileSet->GetInterfaceCompileOptions(config, lang);
    if (!options.empty()) {
      this->LocalGenerator->AppendCompileOptions(flags,
                                                 cm::remove_BT(options));
      *this->FlagFileStream << "# Custom options (File Set '"
                            << fileSet->GetName() << "'): " << relativeObj
                            << "_OPTIONS = " << cmList::to_string(options)
                            << "\n"
                            << "\n";
    }
  }

  // Add precompile headers compile options.
  if (!pchSources.empty() &&
      !((fileSet && fileSet->GetProperty("SKIP_PRECOMPILE_HEADERS")) ||
        source.GetProperty("SKIP_PRECOMPILE_HEADERS"))) {
    std::string pchOptions;
    auto const pchIt = pchSources.find(source.GetFullPath());
    if (pchIt != pchSources.end()) {
      pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions(
        config, lang, pchIt->second);
    } else {
      pchOptions =
        this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
    }

    std::string const& evaluatedFlags =
      genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS);

    this->LocalGenerator->AppendCompileOptions(flags, evaluatedFlags);
    *this->FlagFileStream << "# PCH options: " << relativeObj
                          << "_OPTIONS = " << evaluatedFlags << "\n"
                          << "\n";
  }

  // Add include directories from file set properties.
  std::vector<std::string> includes;

  if (fileSet) {
    auto fsIncludes = fileSet->BelongsTo(this->GeneratorTarget)
      ? fileSet->GetIncludeDirectories(config, lang)
      : fileSet->GetInterfaceIncludeDirectories(config, lang);
    if (!fsIncludes.empty()) {
      this->LocalGenerator->AppendIncludeDirectories(
        includes, cm::remove_BT(fsIncludes), source);
      *this->FlagFileStream
        << "# Custom include directories (File Set '" << fileSet->GetName()
        << "'): " << relativeObj
        << "_INCLUDE_DIRECTORIES = " << cmList::to_string(fsIncludes) << "\n"
        << "\n";
    }
  }

  // Add include directories from source file properties.
  std::string const INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
  if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
    std::string const& evaluatedIncludes =
      genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES);
    this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes,
                                                   source);
    *this->FlagFileStream << "# Custom include directories: " << relativeObj
                          << "_INCLUDE_DIRECTORIES = " << evaluatedIncludes
                          << "\n"
                          << "\n";
  }

  // Add language-specific defines.
  std::set<std::string> defines;

  // Add source-specific preprocessor definitions.
  std::string const COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
  if (cmValue compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
    std::string const& evaluatedDefs =
      genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS);
    this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
    *this->FlagFileStream << "# Custom defines: " << relativeObj
                          << "_DEFINES = " << evaluatedDefs << "\n"
                          << "\n";
  }
  std::string const defPropName =
    cmStrCat("COMPILE_DEFINITIONS_", configUpper);
  if (cmValue config_compile_defs = source.GetProperty(defPropName)) {
    std::string const& evaluatedDefs =
      genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS);
    this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
    *this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_"
                          << configUpper << " = " << evaluatedDefs << "\n"
                          << "\n";
  }

  // Add file set preprocessor definitions
  if (fileSet) {
    auto fsDefines = fileSet->BelongsTo(this->GeneratorTarget)
      ? fileSet->GetCompileDefinitions(config, lang)
      : fileSet->GetInterfaceCompileDefinitions(config, lang);
    if (!fsDefines.empty()) {
      this->LocalGenerator->AppendDefines(defines, fsDefines);
      *this->FlagFileStream << "# Custom defines (File Set '"
                            << fileSet->GetName() << "'): " << relativeObj
                            << "_DEFINES = " << cmList::to_string(fsDefines)
                            << "\n"
                            << "\n";
    }
  }

  // Get the output paths for source and object files.
  std::string const sourceFile = this->LocalGenerator->ConvertToOutputFormat(
    source.GetFullPath(), cmOutputConverter::SHELL);

  // Construct the build message.
  std::vector<std::string> no_depends;
  std::vector<std::string> commands;

  // add in a progress call if needed
  this->NumberOfProgressActions++;

  if (!this->NoRuleMessages) {
    cmLocalUnixMakefileGenerator3::EchoProgress progress;
    this->MakeEchoProgress(progress);
    std::string buildEcho =
      cmStrCat("Building ", lang, " object ", relativeObj);
    this->LocalGenerator->AppendEcho(commands, buildEcho,
                                     cmLocalUnixMakefileGenerator3::EchoBuild,
                                     &progress);
  }

  std::string targetOutPathReal;
  std::string targetOutPathPDB;
  std::string targetOutPathCompilePDB;
  {
    std::string targetFullPathReal;
    std::string targetFullPathPDB;
    std::string targetFullPathCompilePDB =
      this->ComputeTargetCompilePDB(this->GetConfigName());
    if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
        this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
        this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
        this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
      targetFullPathReal = this->GeneratorTarget->GetFullPath(
        this->GetConfigName(), cmStateEnums::RuntimeBinaryArtifact, true);
      targetFullPathPDB = cmStrCat(
        this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
        this->GeneratorTarget->GetPDBName(this->GetConfigName()));
    }

    targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
      cmOutputConverter::SHELL);
    targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
      targetFullPathPDB, cmOutputConverter::SHELL);
    targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(
      this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathCompilePDB),
      cmOutputConverter::SHELL);

    if (this->LocalGenerator->IsMinGWMake() &&
        cmHasSuffix(targetOutPathCompilePDB, '\\')) {
      // mingw32-make incorrectly interprets 'a\ b c' as 'a b' and 'c'
      // (but 'a\ b "c"' as 'a\', 'b', and 'c'!).  Workaround this by
      // avoiding a trailing backslash in the argument.
      targetOutPathCompilePDB.back() = '/';
    }

    std::string const compilePdbOutputPath =
      this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName());
    cmSystemTools::MakeDirectory(compilePdbOutputPath);
  }
  cmRulePlaceholderExpander::RuleVariables vars;
  vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
  vars.CMTargetType =
    cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
  vars.Language = lang.c_str();
  vars.Target = targetOutPathReal.c_str();
  vars.TargetPDB = targetOutPathPDB.c_str();
  vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
  vars.Source = sourceFile.c_str();
  std::string const shellObj =
    this->LocalGenerator->ConvertToOutputFormat(obj, cmOutputConverter::SHELL);
  vars.Object = shellObj.c_str();
  std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
  objectDir = this->LocalGenerator->ConvertToOutputFormat(
    this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
    cmOutputConverter::SHELL);
  vars.ObjectDir = objectDir.c_str();
  std::string targetSupportDir =
    this->GeneratorTarget->GetCMFSupportDirectory();
  targetSupportDir = this->LocalGenerator->ConvertToOutputFormat(
    this->LocalGenerator->MaybeRelativeToTopBinDir(targetSupportDir),
    cmOutputConverter::SHELL);
  vars.TargetSupportDir = targetSupportDir.c_str();
  std::string objectFileDir = cmSystemTools::GetFilenamePath(obj);
  objectFileDir = this->LocalGenerator->ConvertToOutputFormat(
    this->LocalGenerator->MaybeRelativeToCurBinDir(objectFileDir),
    cmOutputConverter::SHELL);
  vars.ObjectFileDir = objectFileDir.c_str();
  vars.Flags = flags.c_str();
  vars.ISPCHeader = ispcHeaderForShell.c_str();
  vars.Config = this->GetConfigName().c_str();
  vars.RustEmit = source.GetRustEmitProperty()->c_str();

  std::string definesString = cmStrCat("$(", lang, "_DEFINES)");

  this->LocalGenerator->JoinDefines(defines, definesString, lang);

  vars.Defines = definesString.c_str();

  std::string includesString = this->LocalGenerator->GetIncludeFlags(
    includes, this->GeneratorTarget, lang, config);
  this->LocalGenerator->AppendFlags(includesString,
                                    "$(" + lang + "_INCLUDES)");
  vars.Includes = includesString.c_str();

  std::string dependencyTarget;
  std::string shellDependencyFile;
  std::string dependencyTimestamp;
  if (compilerGenerateDeps) {
    dependencyTarget = this->LocalGenerator->EscapeForShell(
      this->LocalGenerator->ConvertToMakefilePath(
        this->LocalGenerator->MaybeRelativeToTopBinDir(relativeObj)));
    vars.DependencyTarget = dependencyTarget.c_str();

    auto depFile = cmStrCat(obj, ".d");
    shellDependencyFile = this->LocalGenerator->ConvertToOutputFormat(
      depFile, cmOutputConverter::SHELL);
    vars.DependencyFile = shellDependencyFile.c_str();
    this->CleanFiles.insert(depFile);

    dependencyTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir(
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
  }

  // At the moment, it is assumed that C, C++, Fortran, and CUDA have both
  // assembly and preprocessor capabilities. The same is true for the
  // ability to export compile commands
  bool const lang_has_preprocessor =
    ((lang == "C") || (lang == "CXX") || (lang == "OBJC") ||
     (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") ||
     lang == "ISPC" || lang == "HIP" || lang == "ASM");
  bool const lang_has_assembly = lang_has_preprocessor;
  bool const lang_can_export_cmds = lang_has_preprocessor;

  auto rulePlaceholderExpander =
    this->LocalGenerator->CreateRulePlaceholderExpander();

  // Construct the compile rules.
  {
    std::string cudaCompileMode;
    if (lang == "CUDA") {
      if (this->GeneratorTarget->GetPropertyAsBool(
            "CUDA_SEPARABLE_COMPILATION")) {
        std::string const& rdcFlag =
          this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
        cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, ' ');
      }

      static std::array<cm::string_view, 4> const compileModes{
        { "PTX"_s, "CUBIN"_s, "FATBIN"_s, "OPTIX"_s }
      };
      bool useNormalCompileMode = true;
      for (cm::string_view mode : compileModes) {
        auto propName = cmStrCat("CUDA_", mode, "_COMPILATION");
        auto defName = cmStrCat("_CMAKE_CUDA_", mode, "_FLAG");
        if (this->GeneratorTarget->GetPropertyAsBool(propName)) {
          std::string const& flag =
            this->Makefile->GetRequiredDefinition(defName);
          cudaCompileMode = cmStrCat(cudaCompileMode, flag);
          useNormalCompileMode = false;
          break;
        }
      }
      if (useNormalCompileMode) {
        std::string const& wholeFlag =
          this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
        cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
      }
      vars.CudaCompileMode = cudaCompileMode.c_str();
    }

    cmList compileCommands;
    std::string const& compileRule = this->Makefile->GetRequiredDefinition(
      "CMAKE_" + lang + "_COMPILE_OBJECT");
    compileCommands.assign(compileRule);

    if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") &&
        lang_can_export_cmds && compileCommands.size() == 1) {
      std::string compileCommand = compileCommands[0];

      // no launcher for CMAKE_EXPORT_COMPILE_COMMANDS
      rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
                                                   compileCommand, vars);
      std::string const workingDirectory =
        this->LocalGenerator->GetCurrentBinaryDirectory();
      std::string::size_type lfPos = compileCommand.find(langFlags);
      if (lfPos != std::string::npos) {
        compileCommand.replace(lfPos, langFlags.size(),
                               this->GetFlags(lang, this->GetConfigName()));
      }
      std::string const langDefines = std::string("$(") + lang + "_DEFINES)";
      std::string::size_type const ldPos = compileCommand.find(langDefines);
      if (ldPos != std::string::npos) {
        compileCommand.replace(ldPos, langDefines.size(),
                               this->GetDefines(lang, this->GetConfigName()));
      }
      std::string const langIncludes = std::string("$(") + lang + "_INCLUDES)";
      std::string::size_type const liPos = compileCommand.find(langIncludes);
      if (liPos != std::string::npos) {
        compileCommand.replace(liPos, langIncludes.size(),
                               this->GetIncludes(lang, this->GetConfigName()));
      }

      cmValue const eliminate[] = {
        this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"),
        this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE")
      };
      for (cmValue const& el : eliminate) {
        if (el) {
          cmSystemTools::ReplaceString(compileCommand, *el, "");
        }
      }

      this->GlobalGenerator->AddCXXCompileCommand(
        source.GetFullPath(), workingDirectory, compileCommand, relativeObj);
    }

    // See if we need to use a compiler launcher like ccache or distcc
    std::string compilerLauncher;
    if (!compileCommands.empty()) {
      compilerLauncher = GetCompilerLauncher(lang, config);
    }

    cmValue const fsSkipCodeCheckVal =
      fileSet ? fileSet->GetProperty("SKIP_LINTING") : nullptr;
    cmValue const srcSkipCodeCheckVal = source.GetProperty("SKIP_LINTING");
    bool const skipCodeCheck = fsSkipCodeCheckVal.IsSet()
      ? fsSkipCodeCheckVal.IsOn()
      : (srcSkipCodeCheckVal.IsSet()
           ? srcSkipCodeCheckVal.IsOn()
           : this->GetGeneratorTarget()->GetPropertyAsBool("SKIP_LINTING"));

    if (!skipCodeCheck) {
      std::string const codeCheck = this->GenerateCodeCheckRules(
        source, compilerLauncher, "$(CMAKE_COMMAND)", config, nullptr);
      if (!codeCheck.empty()) {
        compileCommands.front().insert(0, codeCheck);
      }
    }

    // If compiler launcher was specified and not consumed above, it
    // goes to the beginning of the command line.
    if (!compileCommands.empty() && !compilerLauncher.empty()) {
      cmList args{ compilerLauncher, cmList::EmptyElements::Yes };
      if (!args.empty()) {
        args[0] = this->LocalGenerator->ConvertToOutputFormat(
          args[0], cmOutputConverter::SHELL);
        for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
          i = this->LocalGenerator->EscapeForShell(i);
        }
      }
      compileCommands.front().insert(0, args.join(" ") + " ");
    }

    std::string launcher;
    {
      std::string val = this->LocalGenerator->GetRuleLauncher(
        this->GeneratorTarget, "RULE_LAUNCH_COMPILE",
        this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
      if (cmNonempty(val)) {
        launcher = cmStrCat(val, ' ');
      }
    }

    std::string flagsWithDeps(flags);

    if (compilerGenerateDeps) {
      // Injects dependency computation
      auto depFlags = this->Makefile->GetSafeDefinition(
        cmStrCat("CMAKE_DEPFILE_FLAGS_", lang));

      if (!depFlags.empty()) {
        // Add dependency flags
        rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
                                                     depFlags, vars);
        flagsWithDeps.append(1, ' ');
        flagsWithDeps.append(depFlags);
      }
      vars.Flags = flagsWithDeps.c_str();

      auto const& extraCommands = this->Makefile->GetSafeDefinition(
        cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
      if (!extraCommands.empty()) {
        compileCommands.append(extraCommands);
      }

      auto const& depFormat = this->Makefile->GetRequiredDefinition(
        cmStrCat("CMAKE_", lang, "_DEPFILE_FORMAT"));

      if (depFormat == "msvc"_s) {
        // compiler must be launched through a wrapper to pick-up dependencies
        std::string depFilter =
          "$(CMAKE_COMMAND) -E cmake_cl_compile_depends ";
        depFilter += cmStrCat("--dep-file=", shellDependencyFile);
        depFilter +=
          cmStrCat(" --working-dir=",
                   this->LocalGenerator->ConvertToOutputFormat(
                     this->LocalGenerator->GetCurrentBinaryDirectory(),
                     cmOutputConverter::SHELL));
        auto const& prefix = this->Makefile->GetSafeDefinition(
          cmStrCat("CMAKE_", lang, "_CL_SHOWINCLUDES_PREFIX"));
        depFilter += cmStrCat(" --filter-prefix=",
                              this->LocalGenerator->ConvertToOutputFormat(
                                prefix, cmOutputConverter::SHELL));
        depFilter += " -- ";
        compileCommands.front().insert(0, depFilter);
      }
    }

    // Expand placeholders in the commands.
    for (std::string& compileCommand : compileCommands) {
      compileCommand = cmStrCat(launcher, compileCommand);
      rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
                                                   compileCommand, vars);
    }

    // Change the command working directory to the local build tree.
    this->LocalGenerator->CreateCDCommand(
      compileCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
      this->LocalGenerator->GetBinaryDirectory());
    cm::append(commands, compileCommands);
  }

  // Check for extra outputs created by the compilation.
  cmList outputs;
  outputs.emplace_back(relativeObj);
  if (cmValue extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) {
    std::string evaluated_outputs = cmGeneratorExpression::Evaluate(
      *extra_outputs_str, this->LocalGenerator, config);

    if (!evaluated_outputs.empty()) {
      // Register these as extra files to clean.
      outputs.append(evaluated_outputs);
    }
  }
  if (!ispcHeaderRelative.empty()) {
    // can't move ispcHeader as vars is using it
    outputs.emplace_back(ispcHeaderRelative);
  }

  if (outputs.size() > 1) {
    this->CleanFiles.insert(outputs.begin() + 1, outputs.end());
  }

  if (compilerGenerateDeps) {
    depends.push_back(dependencyTimestamp);
  }

  // Write the rule.
  this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
                      commands);

  if (compilerGenerateDeps) {
    // set back flags without dependency generation
    vars.Flags = flags.c_str();
  }

  bool do_preprocess_rules = lang_has_preprocessor &&
    this->LocalGenerator->GetCreatePreprocessedSourceRules();
  bool do_assembly_rules =
    lang_has_assembly && this->LocalGenerator->GetCreateAssemblySourceRules();
  if (do_preprocess_rules || do_assembly_rules) {
    std::vector<std::string> force_depends;
    force_depends.emplace_back("cmake_force");
    std::string::size_type dot_pos = relativeObj.rfind('.');
    std::string relativeObjBase = relativeObj.substr(0, dot_pos);
    dot_pos = obj.rfind('.');
    std::string objBase = obj.substr(0, dot_pos);

    if (do_preprocess_rules) {
      commands.clear();
      std::string const relativeObjI = relativeObjBase + ".i";
      std::string const objI = objBase + ".i";

      std::string preprocessEcho =
        cmStrCat("Preprocessing ", lang, " source to ", objI);
      this->LocalGenerator->AppendEcho(
        commands, preprocessEcho, cmLocalUnixMakefileGenerator3::EchoBuild);

      std::string preprocessRuleVar =
        cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE");
      if (cmValue preprocessRule =
            this->Makefile->GetDefinition(preprocessRuleVar)) {
        cmList preprocessCommands{ *preprocessRule };

        std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat(
          objI, cmOutputConverter::SHELL);
        vars.PreprocessedSource = shellObjI.c_str();

        // Expand placeholders in the commands.
        for (std::string& preprocessCommand : preprocessCommands) {
          // no launcher for preprocessor commands
          rulePlaceholderExpander->ExpandRuleVariables(
            this->LocalGenerator, preprocessCommand, vars);
        }

        this->LocalGenerator->CreateCDCommand(
          preprocessCommands,
          this->LocalGenerator->GetCurrentBinaryDirectory(),
          this->LocalGenerator->GetBinaryDirectory());
        cm::append(commands, preprocessCommands);
      } else {
        std::string cmd =
          cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
                   preprocessRuleVar);
        commands.push_back(std::move(cmd));
      }

      this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                          relativeObjI, force_depends,
                                          commands, false);
    }

    if (do_assembly_rules) {
      commands.clear();
      std::string relativeObjS = relativeObjBase + ".s";
      std::string objS = objBase + ".s";

      std::string assemblyEcho =
        cmStrCat("Compiling ", lang, " source to assembly ", objS);
      this->LocalGenerator->AppendEcho(
        commands, assemblyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);

      std::string assemblyRuleVar =
        cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE");
      if (cmValue assemblyRule =
            this->Makefile->GetDefinition(assemblyRuleVar)) {
        cmList assemblyCommands{ *assemblyRule };

        std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat(
          objS, cmOutputConverter::SHELL);
        vars.AssemblySource = shellObjS.c_str();

        // Expand placeholders in the commands.
        for (std::string& assemblyCommand : assemblyCommands) {
          // no launcher for assembly commands
          rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
                                                       assemblyCommand, vars);
        }

        this->LocalGenerator->CreateCDCommand(
          assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
          this->LocalGenerator->GetBinaryDirectory());
        cm::append(commands, assemblyCommands);
      } else {
        std::string cmd =
          cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
                   assemblyRuleVar);
        commands.push_back(std::move(cmd));
      }

      this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                          relativeObjS, force_depends,
                                          commands, false);
    }
  }
}

void cmMakefileTargetGenerator::WriteTargetCleanRules()
{
  std::vector<std::string> depends;
  std::vector<std::string> commands;

  // Construct the clean target name.
  std::string const cleanTarget = cmStrCat(
    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
    "/clean");

  // Construct the clean command.
  this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
                                           this->GeneratorTarget);
  this->LocalGenerator->CreateCDCommand(
    commands, this->LocalGenerator->GetCurrentBinaryDirectory(),
    this->LocalGenerator->GetBinaryDirectory());

  // Write the rule.
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                      cleanTarget, depends, commands, true);
}

bool cmMakefileTargetGenerator::WriteMakeRule(
  std::ostream& os, char const* comment,
  std::vector<std::string> const& outputs,
  std::vector<std::string> const& depends,
  std::vector<std::string> const& commands, bool in_help)
{
  bool symbolic = false;
  if (outputs.empty()) {
    return symbolic;
  }

  // Check whether we need to bother checking for a symbolic output.
  bool const need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();

  // Check whether the first output is marked as symbolic.
  if (need_symbolic) {
    if (cmSourceFile* sf = this->Makefile->GetSource(outputs[0])) {
      symbolic = sf->GetPropertyAsBool("SYMBOLIC");
    }
  }

  // We always attach the actual commands to the first output.
  this->LocalGenerator->WriteMakeRule(os, comment, outputs[0], depends,
                                      commands, symbolic, in_help);

  // For single outputs, we are done.
  if (outputs.size() == 1) {
    return symbolic;
  }

  // For multiple outputs, make the extra ones depend on the first one.
  std::vector<std::string> const output_depends(1, outputs[0]);
  for (std::string const& output : cmMakeRange(outputs).advance(1)) {
    // Touch the extra output so "make" knows that it was updated,
    // but only if the output was actually created.
    std::string const out = this->LocalGenerator->ConvertToOutputFormat(
      this->LocalGenerator->MaybeRelativeToTopBinDir(output),
      cmOutputConverter::SHELL);
    std::vector<std::string> output_commands;

    bool o_symbolic = false;
    if (need_symbolic) {
      if (cmSourceFile const* sf = this->Makefile->GetSource(output)) {
        o_symbolic = sf->GetPropertyAsBool("SYMBOLIC");
      }
    }
    symbolic = symbolic && o_symbolic;

    if (!o_symbolic) {
      output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
    }
    this->LocalGenerator->WriteMakeRule(os, nullptr, output, output_depends,
                                        output_commands, o_symbolic, in_help);

    if (!o_symbolic) {
      // At build time, remove the first output if this one does not exist
      // so that "make" will rerun the real commands that create this one.
      MultipleOutputPairsType::value_type p(output, outputs[0]);
      this->MultipleOutputPairs.insert(p);
    }
  }
  return symbolic;
}

void cmMakefileTargetGenerator::WriteTargetLinkDependRules()
{
  if (!this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName())) {
    return;
  }

  auto depFile = this->LocalGenerator->GetLinkDependencyFile(
    this->GeneratorTarget, this->GetConfigName());
  this->CleanFiles.insert(depFile);
  this->LocalGenerator->AddImplicitDepends(
    this->GeneratorTarget, "LINK",
    this->GeneratorTarget->GetFullPath(this->GetConfigName()), depFile,
    cmDependencyScannerKind::Compiler);
}
std::string cmMakefileTargetGenerator::GetClangTidyReplacementsFilePath(
  std::string const& directory, cmSourceFile const& source,
  std::string const& config) const
{
  (void)config;
  auto const& objectName = this->GeneratorTarget->GetObjectName(&source);
  // NOTE: This may be better to use `this->TargetBuildDirectory` instead of
  // `MaybeRelativeToTopBinDir(this->TargetBuildDirectoryFull)` here. The main
  // difference is that the current behavior looks odd to relative
  // `<LANG>_CLANG_TIDY_EXPORT_FIXES_DIR` settings. Each subdirectory has its
  // own export fixes directory *and* adds its relative-from-root path
  // underneath it. However, when using an absolute export fixes directory, the
  // source directory structure is preserved. The main benefit of the former is
  // shorter paths everywhere versus the status quo of the existing code.
  cmLocalGenerator* lg = this->GeneratorTarget->GetLocalGenerator();
  auto fixesFile = cmSystemTools::CollapseFullPath(
    cmStrCat(directory, '/',
             lg->CreateSafeObjectFileName(
               lg->MaybeRelativeToTopBinDir(this->TargetBuildDirectoryFull)),
             '/', objectName, ".yaml"));
  return fixesFile;
}

void cmMakefileTargetGenerator::WriteTargetDependRules()
{
  // must write the targets depend info file
  this->InfoFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, "/DependInfo.cmake");
  this->InfoFileStream =
    cm::make_unique<cmGeneratedFileStream>(this->InfoFileNameFull);
  if (!this->InfoFileStream) {
    return;
  }
  this->InfoFileStream->SetCopyIfDifferent(true);
  this->LocalGenerator->WriteDependLanguageInfo(*this->InfoFileStream,
                                                this->GeneratorTarget);

  // Store multiple output pairs in the depend info file.
  if (!this->MultipleOutputPairs.empty()) {
    /* clang-format off */
    *this->InfoFileStream
      << "\n"
      << "# Pairs of files generated by the same build rule.\n"
      << "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
    /* clang-format on */
    for (auto const& pi : this->MultipleOutputPairs) {
      *this->InfoFileStream << "  " << cmScriptGenerator::Quote(pi.first)
                            << ' ' << cmScriptGenerator::Quote(pi.second)
                            << '\n';
    }
    *this->InfoFileStream << "  )\n\n";
  }

  // Store list of targets linked directly or transitively.
  {
    /* clang-format off */
  *this->InfoFileStream
    << "\n"
       "# Targets to which this target links which contain Fortran sources.\n"
       "set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n";
    /* clang-format on */
    auto const dirs =
      this->GetLinkedTargetDirectories("Fortran", this->GetConfigName());
    for (std::string const& d : dirs.Direct) {
      *this->InfoFileStream << "  \"" << d << "/DependInfo.cmake\"\n";
    }
    *this->InfoFileStream << "  )\n";

    /* clang-format off */
  *this->InfoFileStream
    << "\n"
       "# Targets to which this target links which contain Fortran sources.\n"
       "set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES\n";
    /* clang-format on */
    for (std::string const& d : dirs.Forward) {
      *this->InfoFileStream << "  \"" << d << "/DependInfo.cmake\"\n";
    }
    *this->InfoFileStream << "  )\n";
  }

  std::string const& working_dir =
    this->LocalGenerator->GetCurrentBinaryDirectory();

  /* clang-format off */
  *this->InfoFileStream
    << "\n"
    << "# Fortran module output directory.\n"
    << "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
    << this->GeneratorTarget->GetFortranModuleDirectory(working_dir)
    << "\")\n";

  if (this->GeneratorTarget->IsFortranBuildingIntrinsicModules()) {
    *this->InfoFileStream
      << "\n"
      << "# Fortran compiler is building intrinsic modules.\n"
      << "set(CMAKE_Fortran_TARGET_BUILDING_INTRINSIC_MODULES ON) \n";
  }
  /* clang-format on */

  // and now write the rule to use it
  std::vector<std::string> depends;
  std::vector<std::string> commands;

  // Construct the name of the dependency generation target.
  std::string const depTarget = cmStrCat(
    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
    "/depend");

  // Add a command to call CMake to scan dependencies.  CMake will
  // touch the corresponding depends file after scanning dependencies.
  std::ostringstream depCmd;
// TODO: Account for source file properties and directory-level
// definitions when scanning for dependencies.
#if !defined(_WIN32) || defined(__CYGWIN__)
  // This platform supports symlinks, so cmSystemTools will translate
  // paths.  Make sure PWD is set to the original name of the home
  // output directory to help cmSystemTools to create the same
  // translation table for the dependency scanning process.
  depCmd << "cd "
         << (this->LocalGenerator->ConvertToOutputFormat(
              this->LocalGenerator->GetBinaryDirectory(),
              cmOutputConverter::SHELL))
         << " && ";
#endif
  // Generate a call this signature:
  //
  //   cmake -E cmake_depends <generator>
  //                          <home-src-dir> <start-src-dir>
  //                          <home-out-dir> <start-out-dir>
  //                          <dep-info> --color=$(COLOR)
  //                          <target-name>
  //
  // This gives the dependency scanner enough information to recreate
  // the state of our local generator sufficiently for its needs.
  depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
         << this->GlobalGenerator->GetName() << "\" "
         << this->LocalGenerator->ConvertToOutputFormat(
              this->LocalGenerator->GetSourceDirectory(),
              cmOutputConverter::SHELL)
         << " "
         << this->LocalGenerator->ConvertToOutputFormat(
              this->LocalGenerator->GetCurrentSourceDirectory(),
              cmOutputConverter::SHELL)
         << " "
         << this->LocalGenerator->ConvertToOutputFormat(
              this->LocalGenerator->GetBinaryDirectory(),
              cmOutputConverter::SHELL)
         << " "
         << this->LocalGenerator->ConvertToOutputFormat(
              this->LocalGenerator->GetCurrentBinaryDirectory(),
              cmOutputConverter::SHELL)
         << " "
         << this->LocalGenerator->ConvertToOutputFormat(
              this->InfoFileNameFull, cmOutputConverter::SHELL);
  if (this->LocalGenerator->GetColorMakefile()) {
    depCmd << " \"--color=$(COLOR)\"";
  }
  depCmd << ' '
         << this->LocalGenerator->ConvertToOutputFormat(
              this->GeneratorTarget->GetName(), cmOutputConverter::SHELL);
  commands.push_back(depCmd.str());

  // Make sure all custom command outputs in this target are built.
  if (this->CustomCommandDriver == OnDepends) {
    this->DriveCustomCommands(depends);
  }

  // Write the rule.
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                      depTarget, depends, commands, true);
}

void cmMakefileTargetGenerator::DriveCustomCommands(
  std::vector<std::string>& depends)
{
  // Depend on all custom command outputs.
  cm::append(depends, this->CustomCommandOutputs);
}

void cmMakefileTargetGenerator::WriteObjectDependRules(
  cmSourceFile const& source, std::vector<std::string>& depends)
{
  // Create the list of dependencies known at cmake time.  These are
  // shared between the object file and dependency scanning rule.
  depends.push_back(source.GetFullPath());
  if (cmValue objectDeps = source.GetProperty("OBJECT_DEPENDS")) {
    cmExpandList(*objectDeps, depends);
  }
}

void cmMakefileTargetGenerator::WriteDeviceLinkRule(
  std::vector<std::string>& commands, std::string const& output)
{
  std::string architecturesStr =
    this->GeneratorTarget->GetSafeProperty("CUDA_ARCHITECTURES");

  if (cmIsOff(architecturesStr)) {
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                 "CUDA_SEPARABLE_COMPILATION on Clang "
                                 "requires CUDA_ARCHITECTURES to be set.");
    return;
  }

  cmLocalUnixMakefileGenerator3* localGen{ this->LocalGenerator };
  cmList architectures{ architecturesStr };
  std::string const& relPath = localGen->GetHomeRelativeOutputPath();

  // Ensure there are no duplicates.
  std::vector<std::string> const linkDeps = [&]() -> std::vector<std::string> {
    std::vector<std::string> deps;
    this->AppendTargetDepends(deps, true);
    this->GeneratorTarget->GetLinkDepends(deps, this->GetConfigName(), "CUDA");

    for (std::string const& obj : this->Objects) {
      deps.emplace_back(cmStrCat(relPath, obj));
    }

    std::unordered_set<std::string> const depsSet(deps.begin(), deps.end());
    deps.clear();
    std::copy(depsSet.begin(), depsSet.end(), std::back_inserter(deps));
    return deps;
  }();

  std::string const objectDir = this->GeneratorTarget->ObjectDirectory;
  std::string const relObjectDir =
    localGen->MaybeRelativeToCurBinDir(objectDir);

  // Construct a list of files associated with this executable that
  // may need to be cleaned.
  std::vector<std::string> cleanFiles;
  cleanFiles.push_back(localGen->MaybeRelativeToCurBinDir(output));

  std::string profiles;
  std::vector<std::string> fatbinaryDepends;
  std::string const registerFile =
    cmStrCat(objectDir, "cmake_cuda_register.h");

  // Link device code for each architecture.
  for (std::string const& architectureKind : architectures) {
    std::string registerFileCmd;

    // The generated register file contains macros that when expanded
    // register the device routines. Because the routines are the same for
    // all architectures the register file will be the same too. Thus
    // generate it only on the first invocation to reduce overhead.
    if (fatbinaryDepends.empty()) {
      std::string const registerFileRel =
        cmStrCat(relPath, relObjectDir, "cmake_cuda_register.h");
      registerFileCmd =
        cmStrCat(" --register-link-binaries=", registerFileRel);
      cleanFiles.push_back(registerFileRel);
    }

    // Clang always generates real code, so strip the specifier.
    std::string const architecture =
      architectureKind.substr(0, architectureKind.find('-'));
    std::string const cubin =
      cmStrCat(objectDir, "sm_", architecture, ".cubin");

    profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
    fatbinaryDepends.emplace_back(cubin);

    std::string command = cmStrCat(
      this->Makefile->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"),
      " -arch=sm_", architecture, registerFileCmd, " -o=$@ ",
      cmJoin(linkDeps, " "));

    localGen->WriteMakeRule(*this->BuildFileStream, nullptr, cubin, linkDeps,
                            { command }, false);
  }

  // Combine all architectures into a single fatbinary.
  std::string const fatbinaryCommand =
    cmStrCat(this->Makefile->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"),
             " -64 -cmdline=--compile-only -compress-all -link "
             "--embedded-fatbin=$@",
             profiles);
  std::string const fatbinaryOutput =
    cmStrCat(objectDir, "cmake_cuda_fatbin.h");
  std::string const fatbinaryOutputRel =
    cmStrCat(relPath, relObjectDir, "cmake_cuda_fatbin.h");

  localGen->WriteMakeRule(*this->BuildFileStream, nullptr, fatbinaryOutputRel,
                          fatbinaryDepends, { fatbinaryCommand }, false);

  // Compile the stub that registers the kernels and contains the
  // fatbinaries.
  cmRulePlaceholderExpander::RuleVariables vars;
  vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
  vars.CMTargetType =
    cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str();
  vars.Language = "CUDA";
  vars.Object = output.c_str();
  vars.Fatbinary = fatbinaryOutput.c_str();
  vars.RegisterFile = registerFile.c_str();
  vars.Config = this->GetConfigName().c_str();

  std::string linkFlags;
  this->GetDeviceLinkFlags(linkFlags, "CUDA");
  vars.LinkFlags = linkFlags.c_str();

  std::string const flags = this->GetFlags("CUDA", this->GetConfigName());
  vars.Flags = flags.c_str();

  std::string compileCmd = this->GetLinkRule("CMAKE_CUDA_DEVICE_LINK_COMPILE");
  auto rulePlaceholderExpander =
    localGen->CreateRulePlaceholderExpander(cmBuildStep::Link);
  rulePlaceholderExpander->ExpandRuleVariables(localGen, compileCmd, vars);

  commands.emplace_back(compileCmd);
  localGen->WriteMakeRule(*this->BuildFileStream, nullptr, output,
                          { fatbinaryOutputRel }, commands, false);

  // Clean all the possible executable names and symlinks.
  this->CleanFiles.insert(cleanFiles.begin(), cleanFiles.end());
}

void cmMakefileTargetGenerator::GenerateCustomRuleFile(
  cmCustomCommandGenerator const& ccg)
{
  // Collect the commands.
  std::vector<std::string> commands;
  std::string comment = this->LocalGenerator->ConstructComment(ccg);
  if (!comment.empty()) {
    // add in a progress call if needed
    this->NumberOfProgressActions++;
    if (!this->NoRuleMessages) {
      cmLocalUnixMakefileGenerator3::EchoProgress progress;
      this->MakeEchoProgress(progress);
      this->LocalGenerator->AppendEcho(
        commands, comment, cmLocalUnixMakefileGenerator3::EchoGenerate,
        &progress);
    }
  }

  // Now append the actual user-specified commands.
  std::ostringstream content;
  this->LocalGenerator->AppendCustomCommand(
    commands, ccg, this->GeneratorTarget,
    this->LocalGenerator->GetBinaryDirectory(), false, &content);

  // Collect the dependencies.
  std::vector<std::string> depends;
  this->LocalGenerator->AppendCustomDepend(depends, ccg);

  if (!ccg.GetCC().GetDepfile().empty()) {
    // Add dependency over timestamp file for dependencies management
    auto dependTimestamp = this->LocalGenerator->MaybeRelativeToTopBinDir(
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));

    depends.emplace_back(std::move(dependTimestamp));
  }

  // Write the rule.
  std::vector<std::string> const& outputs = ccg.GetOutputs();
  bool const symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr,
                                            outputs, depends, commands);

  // Symbolic inputs are not expected to exist, so add dummy rules.
  if (this->CMP0113New && !depends.empty()) {
    std::vector<std::string> no_depends;
    std::vector<std::string> no_commands;
    for (std::string const& dep : depends) {
      if (cmSourceFile* dsf =
            this->Makefile->GetSource(dep, cmSourceFileLocationKind::Known)) {
        if (dsf->GetPropertyAsBool("SYMBOLIC")) {
          this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                              dep, no_depends, no_commands,
                                              true);
        }
      }
    }
  }

  // If the rule has changed make sure the output is rebuilt.
  if (!symbolic) {
    this->GlobalGenerator->AddRuleHash(ccg.GetOutputs(), content.str());
  }

  // Setup implicit dependency scanning.
  for (auto const& idi : ccg.GetCC().GetImplicitDepends()) {
    std::string objFullPath = cmSystemTools::CollapseFullPath(
      outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
    std::string srcFullPath = cmSystemTools::CollapseFullPath(
      idi.second, this->LocalGenerator->GetCurrentBinaryDirectory());
    this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first,
                                             objFullPath, srcFullPath);
  }

  // Setup implicit depend for depfile if any
  if (!ccg.GetCC().GetDepfile().empty()) {
    std::string objFullPath = cmSystemTools::CollapseFullPath(
      outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
    this->LocalGenerator->AddImplicitDepends(
      this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(),
      cmDependencyScannerKind::Compiler);
  }

  this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
}

void cmMakefileTargetGenerator::MakeEchoProgress(
  cmLocalUnixMakefileGenerator3::EchoProgress& progress) const
{
  progress.Dir =
    cmStrCat(this->LocalGenerator->GetBinaryDirectory(), "/CMakeFiles");
  std::ostringstream progressArg;
  progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
  progress.Arg = progressArg.str();
}

void cmMakefileTargetGenerator::WriteObjectsVariable(
  std::string& variableName, std::string& variableNameExternal,
  bool useWatcomQuote)
{
  // Write a make variable assignment that lists all objects for the
  // target.
  variableName = this->LocalGenerator->CreateMakeVariable(
    this->GeneratorTarget->GetName(), "_OBJECTS");
  *this->BuildFileStream << "# Object files for target "
                         << this->GeneratorTarget->GetName() << "\n"
                         << variableName << " =";
  auto const& lineContinue = this->GlobalGenerator->LineContinueDirective;

  cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");

  for (std::string const& obj : this->Objects) {
    if (cmHasSuffix(obj, pchExtension)) {
      continue;
    }
    *this->BuildFileStream << " " << lineContinue;
    *this->BuildFileStream
      << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
           obj, useWatcomQuote);
  }
  *this->BuildFileStream << "\n";

  // Write a make variable assignment that lists all external objects
  // for the target.
  variableNameExternal = this->LocalGenerator->CreateMakeVariable(
    this->GeneratorTarget->GetName(), "_EXTERNAL_OBJECTS");
  /* clang-format off */
  *this->BuildFileStream
    << "\n"
    << "# External object files for target "
    << this->GeneratorTarget->GetName() << "\n"
    << variableNameExternal << " =";
  /* clang-format on */
  for (std::string const& obj : this->ExternalObjects) {
    *this->BuildFileStream << " " << lineContinue;
    *this->BuildFileStream
      << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
           obj, useWatcomQuote);
  }
  *this->BuildFileStream << "\n"
                         << "\n";
}

class cmMakefileTargetGeneratorObjectStrings
{
public:
  cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
                                         cmOutputConverter* outputConverter,
                                         bool useWatcomQuote,
                                         cmStateDirectory const& stateDir,
                                         std::string::size_type limit)
    : Strings(strings)
    , OutputConverter(outputConverter)
    , UseWatcomQuote(useWatcomQuote)
    , StateDir(stateDir)
    , LengthLimit(limit)
  {
    this->Space = "";
  }
  void Feed(std::string const& obj)
  {
    // Construct the name of the next object.
    this->NextObject = this->OutputConverter->ConvertToOutputFormat(
      this->OutputConverter->MaybeRelativeToCurBinDir(obj),
      cmOutputConverter::RESPONSE, this->UseWatcomQuote);

    // Roll over to next string if the limit will be exceeded.
    if (this->LengthLimit != std::string::npos &&
        (this->CurrentString.length() + 1 + this->NextObject.length() >
         this->LengthLimit)) {
      this->Strings.push_back(this->CurrentString);
      this->CurrentString.clear();
      this->Space = "";
    }

    // Separate from previous object.
    this->CurrentString += this->Space;
    this->Space = " ";

    // Append this object.
    this->CurrentString += this->NextObject;
  }
  void Done() { this->Strings.push_back(this->CurrentString); }

private:
  std::vector<std::string>& Strings;
  cmOutputConverter* OutputConverter;
  bool UseWatcomQuote;
  cmStateDirectory StateDir;
  std::string::size_type LengthLimit;
  std::string CurrentString;
  std::string NextObject;
  char const* Space;
};

void cmMakefileTargetGenerator::WriteObjectsStrings(
  std::vector<std::string>& objStrings, bool useWatcomQuote,
  std::string::size_type limit)
{
  cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");

  cmMakefileTargetGeneratorObjectStrings helper(
    objStrings, this->LocalGenerator, useWatcomQuote,
    this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit);
  for (std::string const& obj : this->Objects) {
    if (cmHasSuffix(obj, pchExtension)) {
      continue;
    }
    helper.Feed(obj);
  }
  for (std::string const& obj : this->ExternalObjects) {
    helper.Feed(obj);
  }
  auto const ispcAdditionalObjs =
    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
  for (auto const& obj : ispcAdditionalObjs) {
    helper.Feed(obj.second);
  }
  helper.Done();
}

void cmMakefileTargetGenerator::WriteTargetDriverRule(
  std::string const& main_output, bool relink)
{
  // Compute the name of the driver target.
  std::string dir =
    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
  std::string buildTargetRuleName =
    cmStrCat(std::move(dir), relink ? "/preinstall" : "/build");
  buildTargetRuleName =
    this->LocalGenerator->MaybeRelativeToTopBinDir(buildTargetRuleName);

  // Build the list of target outputs to drive.
  std::vector<std::string> depends{ main_output };

  char const* comment = nullptr;
  if (relink) {
    // Setup the comment for the preinstall driver.
    comment = "Rule to relink during preinstall.";
  } else {
    // Setup the comment for the main build driver.
    comment = "Rule to build all files generated by this target.";

    // Make sure all custom command outputs in this target are built.
    if (this->CustomCommandDriver == OnBuild) {
      this->DriveCustomCommands(depends);
    }

    // Make sure the extra files are built.
    cm::append(depends, this->ExtraFiles);
  }

  // Write the driver rule.
  std::vector<std::string> no_commands;
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
                                      buildTargetRuleName, depends,
                                      no_commands, true);
}

void cmMakefileTargetGenerator::AppendTargetDepends(
  std::vector<std::string>& depends, bool ignoreType)
{
  // Static libraries never depend on anything for linking.
  if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY &&
      !ignoreType) {
    return;
  }

  std::string const& cfg = this->GetConfigName();

  if (this->GeneratorTarget->HasLinkDependencyFile(cfg)) {
    depends.push_back(
      cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
  }

  // Loop over all library dependencies.
  if (cmComputeLinkInformation const* cli =
        this->GeneratorTarget->GetLinkInformation(cfg)) {
    cm::append(depends, cli->GetDepends());
  }
}

void cmMakefileTargetGenerator::AppendObjectDepends(
  std::vector<std::string>& depends)
{
  // Add dependencies on the compiled object files.
  std::string const& relPath =
    this->LocalGenerator->GetHomeRelativeOutputPath();
  for (std::string const& obj : this->Objects) {
    std::string objTarget = cmStrCat(relPath, obj);
    depends.push_back(std::move(objTarget));
  }

  // Add dependencies on the external object files.
  cm::append(depends, this->ExternalObjects);

  // Add dependency on the Rust main crate root file.
  if (cmSourceFile const* mainCrateRoot =
        this->GeneratorTarget->GetRustMainCrateRoot(this->GetConfigName())) {
    depends.push_back(mainCrateRoot->GetFullPath());
  }

  // Add a dependency on the rule file itself.
  this->LocalGenerator->AppendRuleDepend(depends,
                                         this->BuildFileNameFull.c_str());
}

void cmMakefileTargetGenerator::AppendLinkDepends(
  std::vector<std::string>& depends, std::string const& linkLanguage)
{
  this->AppendObjectDepends(depends);

  // Add dependencies on targets that must be built first.
  this->AppendTargetDepends(depends);

  // Add a dependency on the link definitions file, if any.
  if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
        this->GeneratorTarget->GetModuleDefinitionInfo(
          this->GetConfigName())) {
    for (cmSourceFile const* src : mdi->Sources) {
      depends.push_back(src->GetFullPath());
    }
  }

  // Add a dependency on user-specified manifest files, if any.
  std::vector<cmSourceFile const*> manifest_srcs;
  this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName());
  for (cmSourceFile const* manifest_src : manifest_srcs) {
    depends.push_back(manifest_src->GetFullPath());
  }

  // Add user-specified dependencies.
  this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(),
                                        linkLanguage);
}

std::string cmMakefileTargetGenerator::GetLinkRule(
  std::string const& linkRuleVar)
{
  std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
  if (this->GeneratorTarget->HasImplibGNUtoMS(this->GetConfigName())) {
    std::string ruleVar =
      cmStrCat("CMAKE_",
               this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
               "_GNUtoMS_RULE");
    if (cmValue rule = this->Makefile->GetDefinition(ruleVar)) {
      linkRule += *rule;
    }
  }
  return linkRule;
}

void cmMakefileTargetGenerator::CloseFileStreams()
{
  this->BuildFileStream.reset();
  this->InfoFileStream.reset();
  this->FlagFileStream.reset();
}

void cmMakefileTargetGenerator::CreateLinkScript(
  char const* name, std::vector<std::string> const& link_commands,
  std::vector<std::string>& makefile_commands,
  std::vector<std::string>& makefile_depends)
{
  // Create the link script file.
  std::string linkScriptName =
    cmStrCat(this->TargetBuildDirectoryFull, '/', name);
  cmGeneratedFileStream linkScriptStream(linkScriptName);
  linkScriptStream.SetCopyIfDifferent(true);
  for (std::string const& link_command : link_commands) {
    // Do not write out empty commands or commands beginning in the
    // shell no-op ":".
    if (!link_command.empty() && link_command[0] != ':') {
      linkScriptStream << link_command << "\n";
    }
  }

  // Create the makefile command to invoke the link script.
  std::string link_command =
    cmStrCat("$(CMAKE_COMMAND) -E cmake_link_script ",
             this->LocalGenerator->ConvertToOutputFormat(
               this->LocalGenerator->MaybeRelativeToCurBinDir(linkScriptName),
               cmOutputConverter::SHELL),
             " --verbose=$(VERBOSE)");
  makefile_commands.push_back(std::move(link_command));
  makefile_depends.push_back(std::move(linkScriptName));
}

bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
  std::string const& l) const
{
  // Check for an explicit setting one way or the other.
  std::string const responseVar =
    "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS";
  if (cmValue val = this->Makefile->GetDefinition(responseVar)) {
    if (!val->empty()) {
      return val.IsOn();
    }
  }

  // Check for a system limit.
  if (size_t const limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
    // Compute the total length of our list of object files with room
    // for argument separation and quoting.  This does not convert paths
    // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so
    // the actual list will likely be much shorter than this.  However, in
    // the worst case all objects will remain as absolute paths.
    size_t length = 0;
    for (std::string const& obj : this->Objects) {
      length += obj.size() + 3;
    }
    for (std::string const& ext_obj : this->ExternalObjects) {
      length += ext_obj.size() + 3;
    }

    // We need to guarantee room for both objects and libraries, so
    // if the objects take up more than half then use a response file
    // for them.
    if (length > (limit / 2)) {
      return true;
    }
  }

  // We do not need a response file for objects.
  return false;
}

bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
  std::string const& l) const
{
  // Check for an explicit setting one way or the other.
  std::string const responseVar =
    "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES";
  if (cmValue val = this->Makefile->GetDefinition(responseVar)) {
    if (!val->empty()) {
      return val.IsOn();
    }
  }

  // We do not need a response file for libraries.
  return false;
}

std::string cmMakefileTargetGenerator::CreateResponseFile(
  std::string const& name, std::string const& options,
  std::vector<std::string>& makefile_depends, std::string const& language)
{
  // FIXME: Find a better way to determine the response file encoding,
  // perhaps using tool-specific platform information variables.
  // For now, use the makefile encoding as a heuristic.
  codecvt_Encoding responseEncoding =
    this->GlobalGenerator->GetMakefileEncoding();
  // Non-MSVC tooling doesn't understand BOM encoded files.
  if (responseEncoding == codecvt_Encoding::UTF8_WITH_BOM &&
      (language == "CUDA" || !this->Makefile->IsOn("MSVC"))) {
    responseEncoding = codecvt_Encoding::UTF8;
  }

  // Create the response file.
  std::string responseFileNameFull =
    cmStrCat(this->TargetBuildDirectoryFull, '/', name);
  cmGeneratedFileStream responseStream(responseFileNameFull, false,
                                       responseEncoding);
  responseStream.SetCopyIfDifferent(true);
  responseStream << options << "\n";

  // Add a dependency so the target will rebuild when the set of
  // objects changes.
  makefile_depends.push_back(std::move(responseFileNameFull));

  // Construct the name to be used on the command line.
  std::string responseFileName =
    cmStrCat(this->TargetBuildDirectory, '/', name);
  return responseFileName;
}

std::unique_ptr<cmLinkLineComputer>
cmMakefileTargetGenerator::CreateLinkLineComputer(
  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
{
  if (this->Makefile->IsOn("MSVC60")) {
    return this->GlobalGenerator->CreateMSVC60LinkLineComputer(outputConverter,
                                                               stateDir);
  }
  return this->GlobalGenerator->CreateLinkLineComputer(outputConverter,
                                                       stateDir);
}

void cmMakefileTargetGenerator::CreateLinkLibs(
  cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
  bool useResponseFile, std::vector<std::string>& makefile_depends,
  std::string const& linkLanguage, ResponseFlagFor responseMode)
{
  if (cmComputeLinkInformation* pcli =
        this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) {
    std::string frameworkPath;
    std::string linkPath;
    this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
                                              frameworkPath, linkPath);
    linkLibs = frameworkPath + linkPath + linkLibs;
  }

  if (useResponseFile &&
      linkLibs.find_first_not_of(' ') != std::string::npos) {
    // Lookup the response file reference flag.
    std::string responseFlag = this->GetResponseFlag(responseMode);

    // Create this response file.
    std::string const responseFileName =
      (responseMode == DeviceLink) ? "deviceLinkLibs.rsp" : "linkLibs.rsp";
    std::string const responseLang =
      (responseMode == DeviceLink) ? "CUDA" : linkLanguage;
    std::string link_rsp = this->CreateResponseFile(
      responseFileName, linkLibs, makefile_depends, responseLang);

    // Reference the response file.
    linkLibs = cmStrCat(std::move(responseFlag),
                        this->LocalGenerator->ConvertToOutputFormat(
                          std::move(link_rsp), cmOutputConverter::SHELL));
  }
}

void cmMakefileTargetGenerator::CreateObjectLists(
  bool useLinkScript, bool useArchiveRules, bool useResponseFile,
  std::string& buildObjs, std::vector<std::string>& makefile_depends,
  bool useWatcomQuote, std::string const& linkLanguage,
  ResponseFlagFor responseMode)
{
  std::string variableName;
  std::string variableNameExternal;
  this->WriteObjectsVariable(variableName, variableNameExternal,
                             useWatcomQuote);
  if (useResponseFile) {
    // MSVC response files cannot exceed 128K.
    std::string::size_type constexpr responseFileLimit = 131000;

    // Construct the individual object list strings.
    std::vector<std::string> object_strings;
    this->WriteObjectsStrings(object_strings, useWatcomQuote,
                              responseFileLimit);

    // Lookup the response file reference flag.
    std::string const responseFlag = this->GetResponseFlag(responseMode);

    // Write a response file for each string.
    char const* sep = "";
    for (unsigned int i = 0; i < object_strings.size(); ++i) {
      // Number the response files.
      std::string responseFileName =
        cmStrCat((responseMode == DeviceLink) ? "deviceObjects" : "objects",
                 i + 1, ".rsp");

      // Create this response file.
      std::string objects_rsp = this->CreateResponseFile(
        responseFileName, object_strings[i], makefile_depends, linkLanguage);

      buildObjs +=
        cmStrCat(sep, // Separate from previous response file references.
                 responseFlag, // Reference the response file.
                 this->LocalGenerator->ConvertToOutputFormat(
                   objects_rsp, cmOutputConverter::SHELL));
      sep = " ";
    }
  } else if (useLinkScript) {
    if (!useArchiveRules) {
      std::vector<std::string> objStrings;
      this->WriteObjectsStrings(objStrings, useWatcomQuote);
      buildObjs = objStrings[0];
    }
  } else {
    buildObjs =
      cmStrCat("$(", variableName, ") $(", variableNameExternal, ')');
  }
}

bool cmMakefileTargetGenerator::CreateRustLinkArguments(
  std::string const& linkLanguage, std::string& rustMainCrateRootPath,
  std::string& rustLinkCrates, std::string& rustNativeObjects)
{
  if (linkLanguage == "Rust") {
    this->ComputeRustFlagsForObjects(rustLinkCrates, rustNativeObjects,
                                     this->Objects);
    this->ComputeRustFlagsForObjects(rustLinkCrates, rustNativeObjects,
                                     this->ExternalObjects);

    cmSourceFile const* mainCrateRoot =
      this->GeneratorTarget->GetRustMainCrateRoot(this->GetConfigName());
    if (!mainCrateRoot) {
      this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                   "Target " +
                                     this->GeneratorTarget->GetName() +
                                     " has no main crate root.");
      return false;
    }
    rustMainCrateRootPath = mainCrateRoot->GetFullPath();
    rustMainCrateRootPath = this->LocalGenerator->ConvertToOutputFormat(
      rustMainCrateRootPath, cmOutputConverter::SHELL);
    return true;
  }
  return false;
}

void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
                                                std::string const& lang,
                                                std::string const& /*config*/)
{
  std::string const responseVar =
    cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES");
  bool const useResponseFile = this->Makefile->IsOn(responseVar);

  std::vector<std::string> includes;
  this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
                                              lang, this->GetConfigName());

  std::string const includeFlags = this->LocalGenerator->GetIncludeFlags(
    includes, this->GeneratorTarget, lang, this->GetConfigName(),
    useResponseFile);
  if (includeFlags.empty()) {
    return;
  }

  if (useResponseFile) {
    std::string const responseFlagVar =
      "CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
    std::string responseFlag =
      this->Makefile->GetSafeDefinition(responseFlagVar);
    if (responseFlag.empty()) {
      responseFlag = "@";
    }
    std::string const name = cmStrCat("includes_", lang, ".rsp");
    std::string const includes_rsp = this->CreateResponseFile(
      name, includeFlags, this->FlagFileDepends[lang], lang);
    std::string const arg =
      cmStrCat(std::move(responseFlag),
               this->LocalGenerator->ConvertToOutputFormat(
                 includes_rsp, cmOutputConverter::SHELL));
    this->LocalGenerator->AppendFlags(flags, arg);
  } else {
    this->LocalGenerator->AppendFlags(flags, includeFlags);
  }
}

void cmMakefileTargetGenerator::GenDefFile(
  std::vector<std::string>& real_link_commands)
{
  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
  if (!mdi || !mdi->DefFileGenerated) {
    return;
  }
  std::string cmd = cmSystemTools::GetCMakeCommand();
  cmd = cmStrCat(
    this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL),
    " -E __create_def ",
    this->LocalGenerator->ConvertToOutputFormat(
      this->LocalGenerator->MaybeRelativeToCurBinDir(mdi->DefFile),
      cmOutputConverter::SHELL),
    ' ');
  std::string objlist_file = mdi->DefFile + ".objs";
  cmd += this->LocalGenerator->ConvertToOutputFormat(
    this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file),
    cmOutputConverter::SHELL);
  cmValue const nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
  if (cmNonempty(nm_executable)) {
    cmd += " --nm=";
    cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
      *nm_executable, cmOutputConverter::SHELL);
  }
  real_link_commands.insert(real_link_commands.begin(), cmd);
  // create a list of obj files for the -E __create_def to read
  cmGeneratedFileStream fout(objlist_file);

  if (mdi->WindowsExportAllSymbols) {
    for (std::string const& obj : this->Objects) {
      if (cmHasLiteralSuffix(obj, ".obj")) {
        fout << obj << "\n";
      }
    }
    for (std::string const& obj : this->ExternalObjects) {
      fout << obj << "\n";
    }
  }

  for (cmSourceFile const* src : mdi->Sources) {
    fout << src->GetFullPath() << "\n";
  }
}

std::string cmMakefileTargetGenerator::GetResponseFlag(
  ResponseFlagFor mode) const
{
  std::string responseFlag = "@";
  std::string responseFlagVar;

  auto const lang =
    this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
  if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) {
    responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG");
  } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) {
    responseFlagVar = "CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG";
  } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Archive) {
    responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_ARCHIVE_FLAG");
  }

  if (cmValue const p = this->Makefile->GetDefinition(responseFlagVar)) {
    responseFlag = *p;
  } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Archive) {
    responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG");
    if (cmValue const q = this->Makefile->GetDefinition(responseFlagVar)) {
      responseFlag = *q;
    }
  }
  return responseFlag;
}
