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

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

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

#include "cm_codecvt.hxx"

#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#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 "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.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 = cmIsOff(*ruleStatus);
  }
  switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) {
    case cmPolicies::WARN:
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      this->CMP0113New = false;
      break;
    case cmPolicies::NEW:
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      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 cmMakefileTargetGenerator::GetConfigName() const
{
  auto const& configNames = this->LocalGenerator->GetConfigNames();
  assert(configNames.size() == 1);
  return configNames.front();
}

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

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

void cmMakefileTargetGenerator::GetTargetLinkFlags(
  std::string& flags, const std::string& linkLanguage)
{
  this->LocalGenerator->AppendFlags(
    flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS"));

  std::string linkFlagsConfig =
    cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->GetConfigName()));
  this->LocalGenerator->AppendFlags(
    flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig));

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

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

void cmMakefileTargetGenerator::CreateRuleFile()
{
  // Create a directory for this target.
  this->TargetBuildDirectory =
    this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
  this->TargetBuildDirectoryFull =
    this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
  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()
{
  this->GeneratorTarget->CheckCxxModuleStatus(this->GetConfigName());

  if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
    this->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("The \"", this->GeneratorTarget->GetName(),
               "\" target contains C++ module sources which are not supported "
               "by the generator"));
  }

  // -- Write the custom commands for this target

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

  // Look for additional files registered for cleaning in this directory.
  if (cmValue prop_value =
        this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) {
    std::vector<std::string> 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")) {
    std::vector<std::string> 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 ispcAdditionalObjs =
    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
  for (std::string const& ispcObj : ispcAdditionalObjs) {
    this->CleanFiles.insert(
      this->LocalGenerator->MaybeRelativeToCurBinDir(ispcObj));
  }

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

  // 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());
  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) {
      const std::vector<std::string>& outputs = ccg.GetOutputs();
      for (std::string const& output : outputs) {
        this->CleanFiles.insert(
          this->LocalGenerator->MaybeRelativeToCurBinDir(output));
      }
      const std::vector<std::string>& byproducts = ccg.GetByproducts();
      for (std::string const& byproduct : byproducts) {
        this->CleanFiles.insert(
          this->LocalGenerator->MaybeRelativeToCurBinDir(byproduct));
      }
    }
  }

  // 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 (const auto& be : buildEventCommands) {
      cmCustomCommandGenerator beg(be, this->GetConfigName(),
                                   this->LocalGenerator);
      const std::vector<std::string>& 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::map<std::string, std::string> file_set_map;

  auto const* tgt = this->GeneratorTarget->Target;
  for (auto const& name : tgt->GetAllFileSetNames()) {
    auto const* file_set = tgt->GetFileSet(name);
    if (!file_set) {
      this->Makefile->IssueMessage(
        MessageType::INTERNAL_ERROR,
        cmStrCat("Target \"", tgt->GetName(),
                 "\" is tracked to have file set \"", name,
                 "\", but it was not found."));
      continue;
    }

    auto fileEntries = file_set->CompileFileEntries();
    auto directoryEntries = file_set->CompileDirectoryEntries();
    auto directories = file_set->EvaluateDirectoryEntries(
      directoryEntries, this->LocalGenerator, this->GetConfigName(),
      this->GeneratorTarget);

    std::map<std::string, std::vector<std::string>> files;
    for (auto const& entry : fileEntries) {
      file_set->EvaluateFileEntry(directories, files, entry,
                                  this->LocalGenerator, this->GetConfigName(),
                                  this->GeneratorTarget);
    }

    for (auto const& it : files) {
      for (auto const& filename : it.second) {
        file_set_map[filename] = file_set->GetType();
      }
    }
  }

  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) {
    auto const& path = sf->GetFullPath();
    auto const it = file_set_map.find(path);
    if (it != file_set_map.end()) {
      auto const& file_set_type = it->second;
      if (file_set_type == "CXX_MODULES"_s ||
          file_set_type == "CXX_MODULE_HEADER_UNITS"_s) {
        if (sf->GetLanguage() != "CXX"_s) {
          this->Makefile->IssueMessage(
            MessageType::FATAL_ERROR,
            cmStrCat(
              "Target \"", tgt->GetName(), "\" contains the source\n  ", path,
              "\nin a file set of type \"", file_set_type,
              R"(" but the source is not classified as a "CXX" source.)"));
        }
      }
    }
  }
}

void cmMakefileTargetGenerator::WriteCommonCodeRules()
{
  const char* 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));

  if (compilerGenerateDeps || ccGenerateDeps) {
    std::string 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(), architectures);
    architectures.emplace_back();

    for (const std::string& 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, const char* pkgloc, const std::string& 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("$(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.
  const std::string& 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 compilerGenerateDeps =
    this->GlobalGenerator->SupportsCompilerDependencies() &&
    cmIsOn(this->Makefile->GetDefinition(
      cmStrCat("CMAKE_", lang, "_DEPENDS_USE_COMPILER")));
  auto 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 obj =
    cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
             '/', 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 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);
  objFullPath = cmSystemTools::CollapseFullPath(objFullPath);
  std::string srcFullPath =
    cmSystemTools::CollapseFullPath(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 config = this->GetConfigName();
  std::string configUpper = cmSystemTools::UpperCase(config);

  // Add precompile headers dependencies
  std::vector<std::string> architectures;
  this->GeneratorTarget->GetAppleArchs(config, architectures);
  if (architectures.empty()) {
    architectures.emplace_back();
  }

  std::string filterArch;
  std::unordered_map<std::string, std::string> pchSources;
  for (const std::string& arch : architectures) {
    const std::string 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() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
    for (const std::string& arch : architectures) {
      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 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 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.
  const std::string COMPILE_FLAGS("COMPILE_FLAGS");
  if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) {
    const std::string& evaluatedFlags =
      genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
    this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
    *this->FlagFileStream << "# Custom flags: " << relativeObj
                          << "_FLAGS = " << evaluatedFlags << "\n"
                          << "\n";
  }

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

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

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

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

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

  const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
  if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
    const std::string& 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.
  const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
  if (cmValue compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
    const std::string& evaluatedDefs =
      genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS);
    this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
    *this->FlagFileStream << "# Custom defines: " << relativeObj
                          << "_DEFINES = " << evaluatedDefs << "\n"
                          << "\n";
  }
  std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
  if (cmValue config_compile_defs = source.GetProperty(defPropName)) {
    const std::string& evaluatedDefs =
      genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS);
    this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
    *this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_"
                          << configUpper << " = " << evaluatedDefs << "\n"
                          << "\n";
  }

  // Get the output paths for source and object files.
  std::string 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() &&
        cmHasLiteralSuffix(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 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 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 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();

  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 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;

  std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
    this->LocalGenerator->CreateRulePlaceholderExpander());

  // Construct the compile rules.
  {
    std::string cudaCompileMode;
    if (lang == "CUDA") {
      if (this->GeneratorTarget->GetPropertyAsBool(
            "CUDA_SEPARABLE_COMPILATION")) {
        const std::string& rdcFlag =
          this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
        cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
      }
      if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
        const std::string& ptxFlag =
          this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
        cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
      } else {
        const std::string& wholeFlag =
          this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
        cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
      }
      vars.CudaCompileMode = cudaCompileMode.c_str();
    }

    std::vector<std::string> compileCommands;
    const std::string& compileRule = this->Makefile->GetRequiredDefinition(
      "CMAKE_" + lang + "_COMPILE_OBJECT");
    cmExpandList(compileRule, compileCommands);

    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 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 langDefines = std::string("$(") + lang + "_DEFINES)";
      std::string::size_type ldPos = compileCommand.find(langDefines);
      if (ldPos != std::string::npos) {
        compileCommand.replace(ldPos, langDefines.size(),
                               this->GetDefines(lang, this->GetConfigName()));
      }
      std::string langIncludes = std::string("$(") + lang + "_INCLUDES)";
      std::string::size_type liPos = compileCommand.find(langIncludes);
      if (liPos != std::string::npos) {
        compileCommand.replace(liPos, langIncludes.size(),
                               this->GetIncludes(lang, this->GetConfigName()));
      }

      cmValue eliminate[] = {
        this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"),
        this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE")
      };
      for (cmValue 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() &&
        (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
         lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
         lang == "OBJCXX")) {
      std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
      cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
      std::string evaluatedClauncher = cmGeneratorExpression::Evaluate(
        *clauncher, this->LocalGenerator, config);
      if (!evaluatedClauncher.empty()) {
        compilerLauncher = evaluatedClauncher;
      }
    }

    // Maybe insert an include-what-you-use runner.
    if (!compileCommands.empty() &&
        (lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
      std::string const tidy_prop = lang + "_CLANG_TIDY";
      cmValue tidy = this->GeneratorTarget->GetProperty(tidy_prop);
      cmValue iwyu = nullptr;
      cmValue cpplint = nullptr;
      cmValue cppcheck = nullptr;
      if (lang == "C" || lang == "CXX") {
        std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
        iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
        std::string const cpplint_prop = lang + "_CPPLINT";
        cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
        std::string const cppcheck_prop = lang + "_CPPCHECK";
        cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
      }
      if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
          cmNonempty(cppcheck)) {
        std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
        if (!compilerLauncher.empty()) {
          // In __run_co_compile case the launcher command is supplied
          // via --launcher=<maybe-list> and consumed
          run_iwyu += " --launcher=";
          run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
          compilerLauncher.clear();
        }
        if (cmNonempty(iwyu)) {
          run_iwyu += " --iwyu=";

          // Only add --driver-mode if it is not already specified, as adding
          // it unconditionally might override a user-specified driver-mode
          if (iwyu.Get()->find("--driver-mode=") == std::string::npos) {
            cmValue p = this->Makefile->GetDefinition(
              cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
            std::string driverMode;

            if (cmNonempty(p)) {
              driverMode = *p;
            } else {
              driverMode = lang == "C" ? "gcc" : "g++";
            }

            run_iwyu += this->LocalGenerator->EscapeForShell(
              cmStrCat(*iwyu, ";--driver-mode=", driverMode));
          } else {
            run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
          }
        }
        if (cmNonempty(tidy)) {
          run_iwyu += " --tidy=";
          cmValue p = this->Makefile->GetDefinition("CMAKE_" + lang +
                                                    "_CLANG_TIDY_DRIVER_MODE");
          std::string driverMode;
          if (cmNonempty(p)) {
            driverMode = *p;
          } else {
            driverMode = lang == "C" ? "gcc" : "g++";
          }
          std::string d =
            this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang);
          std::string exportFixes;
          if (!d.empty()) {
            this->GlobalCommonGenerator->AddClangTidyExportFixesDir(d);
            std::string fixesFile = cmSystemTools::CollapseFullPath(cmStrCat(
              d, '/',
              this->LocalGenerator->MaybeRelativeToTopBinDir(cmStrCat(
                this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
                this->LocalGenerator->GetTargetDirectory(
                  this->GeneratorTarget),
                '/', objectName, ".yaml"))));
            this->GlobalCommonGenerator->AddClangTidyExportFixesFile(
              fixesFile);
            cmSystemTools::MakeDirectory(
              cmSystemTools::GetFilenamePath(fixesFile));
            fixesFile =
              this->LocalGenerator->MaybeRelativeToCurBinDir(fixesFile);
            exportFixes = cmStrCat(";--export-fixes=", fixesFile);
          }
          run_iwyu += this->LocalGenerator->EscapeForShell(
            cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode,
                     exportFixes));
        }
        if (cmNonempty(cpplint)) {
          run_iwyu += " --cpplint=";
          run_iwyu += this->LocalGenerator->EscapeForShell(*cpplint);
        }
        if (cmNonempty(cppcheck)) {
          run_iwyu += " --cppcheck=";
          run_iwyu += this->LocalGenerator->EscapeForShell(*cppcheck);
        }
        if (cmNonempty(tidy) || (cmNonempty(cpplint)) ||
            (cmNonempty(cppcheck))) {
          run_iwyu += " --source=";
          run_iwyu += sourceFile;
        }
        run_iwyu += " -- ";
        compileCommands.front().insert(0, run_iwyu);
      }
    }

    // If compiler launcher was specified and not consumed above, it
    // goes to the beginning of the command line.
    if (!compileCommands.empty() && !compilerLauncher.empty()) {
      std::vector<std::string> args = cmExpandedList(compilerLauncher, true);
      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, cmJoin(args, " ") + " ");
    }

    std::string launcher;
    {
      cmValue val = this->LocalGenerator->GetRuleLauncher(
        this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
      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();

      const auto& extraCommands = this->Makefile->GetSafeDefinition(
        cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
      if (!extraCommands.empty()) {
        auto commandList = cmExpandedList(extraCommands);
        compileCommands.insert(compileCommands.end(), commandList.cbegin(),
                               commandList.cend());
      }

      const auto& 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));
        const auto& 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.
  std::vector<std::string> outputs(1, 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.
      cmExpandList(evaluated_outputs, 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 relativeObjI = relativeObjBase + ".i";
      std::string 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)) {
        std::vector<std::string> preprocessCommands =
          cmExpandedList(*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)) {
        std::vector<std::string> assemblyCommands =
          cmExpandedList(*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 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, const char* comment,
  const std::vector<std::string>& outputs,
  const std::vector<std::string>& depends,
  const std::vector<std::string>& commands, bool in_help)
{
  bool symbolic = false;
  if (outputs.empty()) {
    return symbolic;
  }

  // Check whether we need to bother checking for a symbolic output.
  bool 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* 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::WriteTargetDependRules()
{
  // must write the targets depend info file
  std::string dir =
    this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
  this->InfoFileNameFull = cmStrCat(dir, "/DependInfo.cmake");
  this->InfoFileNameFull =
    this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
  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
        << "  " << cmOutputConverter::EscapeForCMake(pi.first) << " "
        << cmOutputConverter::EscapeForCMake(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 */
    std::vector<std::string> dirs =
      this->GetLinkedTargetDirectories("Fortran", this->GetConfigName());
    for (std::string const& d : dirs) {
      *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->IsFortranBuildingInstrinsicModules()) {
    *this->InfoFileStream
      << "\n"
      << "# Fortran compiler is building intrinsic modules.\n"
      << "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_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 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)
  //
  // 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(
              cmSystemTools::CollapseFullPath(this->InfoFileNameFull),
              cmOutputConverter::SHELL);
  if (this->LocalGenerator->GetColorMakefile()) {
    depCmd << " --color=$(COLOR)";
  }
  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, const std::string& 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 };
  std::vector<std::string> architectures = cmExpandedList(architecturesStr);
  std::string const& relPath = localGen->GetHomeRelativeOutputPath();

  // Ensure there are no duplicates.
  const std::vector<std::string> 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> depsSet(deps.begin(), deps.end());
    deps.clear();
    std::copy(depsSet.begin(), depsSet.end(), std::back_inserter(deps));
    return deps;
  }();

  const std::string objectDir = this->GeneratorTarget->ObjectDirectory;
  const std::string 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 (const std::string& 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.
    const std::string architecture =
      architectureKind.substr(0, architectureKind.find('-'));
    const std::string 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.
  const std::string fatbinaryCommand =
    cmStrCat(this->Makefile->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"),
             " -64 -cmdline=--compile-only -compress-all -link "
             "--embedded-fatbin=$@",
             profiles);
  const std::string fatbinaryOutput =
    cmStrCat(objectDir, "cmake_cuda_fatbin.h");
  const std::string 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();

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

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

  std::string compileCmd = this->GetLinkRule("CMAKE_CUDA_DEVICE_LINK_COMPILE");
  std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
    localGen->CreateRulePlaceholderExpander());
  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 = cmSystemTools::ConvertToOutputPath(
      this->LocalGenerator->MaybeRelativeToTopBinDir(
        cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));

    depends.push_back(dependTimestamp);
  }

  // Write the rule.
  const std::vector<std::string>& outputs = ccg.GetOutputs();
  bool 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 << " =";
  std::string object;
  const auto& 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) {
    object = this->LocalGenerator->MaybeRelativeToCurBinDir(obj);
    *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;
  const char* 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 ispcAdditionalObjs =
    this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
  for (std::string const& obj : ispcAdditionalObjs) {
    helper.Feed(obj);
  }
  helper.Done();
}

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

  // Build the list of target outputs to drive.
  std::vector<std::string> depends;
  depends.push_back(main_output);

  const char* 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;
  }

  // Loop over all library dependencies.
  const std::string& cfg = this->GetConfigName();
  if (cmComputeLinkInformation* 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 a dependency on the rule file itself.
  this->LocalGenerator->AppendRuleDepend(depends,
                                         this->BuildFileNameFull.c_str());
}

void cmMakefileTargetGenerator::AppendLinkDepends(
  std::vector<std::string>& depends, const std::string& 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(
  const std::string& 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(
  const char* 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 cmIsOn(val);
    }
  }

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

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

std::string cmMakefileTargetGenerator::CreateResponseFile(
  const std::string& name, std::string const& options,
  std::vector<std::string>& makefile_depends)
{
  // 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 may not understand a BOM.
  if (responseEncoding == codecvt::UTF8_WITH_BOM &&
      !this->Makefile->IsOn("MSVC")) {
    responseEncoding = codecvt::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,
  ResponseFlagFor responseMode)
{
  std::string frameworkPath;
  std::string linkPath;
  cmComputeLinkInformation* pcli =
    this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
  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 responseFileName =
      (responseMode == Link) ? "linkLibs.rsp" : "deviceLinkLibs.rsp";
    std::string link_rsp =
      this->CreateResponseFile(responseFileName, linkLibs, makefile_depends);

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

void cmMakefileTargetGenerator::CreateObjectLists(
  bool useLinkScript, bool useArchiveRules, bool useResponseFile,
  std::string& buildObjs, std::vector<std::string>& makefile_depends,
  bool useWatcomQuote, 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 const 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 responseFlag = this->GetResponseFlag(responseMode);

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

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

      // Separate from previous response file references.
      buildObjs += sep;
      sep = " ";

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

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

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

  std::string 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 name = cmStrCat("includes_", lang, ".rsp");
    std::string arg = std::move(responseFlag) +
      this->CreateResponseFile(name, includeFlags,
                               this->FlagFileDepends[lang]);
    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 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 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";
  }

  if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
    responseFlag = *p;
  }
  return responseFlag;
}
