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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <functional>
#include <iostream>
#include <utility>

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

#include "cmsys/FStream.hxx"

#include "cmCMakePath.h"
#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
#include "cmDependsCompiler.h"
#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmInstrumentation.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmScriptGenerator.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStdIoStream.h"
#include "cmStdIoTerminal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetDepend.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"

// Include dependency scanners for supported languages.  Only the
// C/C++ scanner is needed for bootstrapping CMake.
#include "cmDependsC.h"
#ifndef CMAKE_BOOTSTRAP
#  include "cmDependsFortran.h"
#  include "cmDependsJava.h"
#endif

namespace {
// Helper function used below.
std::string cmSplitExtension(std::string const& in, std::string& base)
{
  std::string ext;
  std::string::size_type dot_pos = in.rfind('.');
  if (dot_pos != std::string::npos) {
    // Remove the extension first in case &base == &in.
    ext = in.substr(dot_pos);
    base = in.substr(0, dot_pos);
  } else {
    base = in;
  }
  return ext;
}

#ifndef CMAKE_BOOTSTRAP
// Helper function to add the Start Instrumentation command
void addInstrumentationCommand(cmInstrumentation* instrumentation,
                               std::vector<std::string>& commands)
{
  if (instrumentation->HasQuery()) {
    std::string instrumentationCommand =
      "$(CTEST_COMMAND) --start-instrumentation $(CMAKE_BINARY_DIR)";
#  ifndef _WIN32
    /*
     * On Unix systems, Make will prefix the command with `/bin/sh -c`.
     * Use exec so that Make is the parent process of the command.
     * Add a `;` to convince BSD make to not optimize out the shell.
     */
    instrumentationCommand = cmStrCat("exec ", instrumentationCommand, " ;");
#  endif
    commands.push_back(instrumentationCommand);
  }
}
#endif

// Helper predicate for removing absolute paths that don't point to the
// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
// is set ON, to only consider in-project dependencies during the build.
class NotInProjectDir
{
public:
  // Constructor with the source and binary directory's path
  NotInProjectDir(cm::string_view sourceDir, cm::string_view binaryDir)
    : SourceDir(sourceDir)
    , BinaryDir(binaryDir)
  {
  }

  // Operator evaluating the predicate
  bool operator()(std::string const& p) const
  {
    auto path = cmCMakePath(p).Normal();

    // Keep all relative paths:
    if (path.IsRelative()) {
      return false;
    }

    // If it's an absolute path, check if it starts with the source
    // directory:
    return !(cmCMakePath(this->SourceDir).IsPrefix(path) ||
             cmCMakePath(this->BinaryDir).IsPrefix(path));
  }

private:
  // The path to the source directory
  cm::string_view SourceDir;
  // The path to the binary directory
  cm::string_view BinaryDir;
};
}

cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
  cmGlobalGenerator* gg, cmMakefile* mf)
  : cmLocalCommonGenerator(gg, mf)
{
  this->MakefileVariableSize = 0;
  this->ColorMakefile = false;
  this->SkipPreprocessedSourceRules = false;
  this->SkipAssemblySourceRules = false;
  this->MakeCommandEscapeTargetTwice = false;
  this->BorlandMakeCurlyHack = false;
}

cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default;

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

void cmLocalUnixMakefileGenerator3::Generate()
{
  // Record whether some options are enabled to avoid checking many
  // times later.
  if (!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) {
    if (this->Makefile->IsSet("CMAKE_COLOR_MAKEFILE")) {
      this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_MAKEFILE");
    } else {
      this->ColorMakefile = this->Makefile->IsOn("CMAKE_COLOR_DIAGNOSTICS");
    }
  }
  this->SkipPreprocessedSourceRules =
    this->Makefile->IsOn("CMAKE_SKIP_PREPROCESSED_SOURCE_RULES");
  this->SkipAssemblySourceRules =
    this->Makefile->IsOn("CMAKE_SKIP_ASSEMBLY_SOURCE_RULES");

  // Generate the rule files for each target.
  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  for (cmGeneratorTarget* gt :
       this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) {
    if (!gt->IsInBuildSystem()) {
      continue;
    }

    auto& gtVisited = this->GetCommandsVisited(gt);
    auto const& deps = this->GlobalGenerator->GetTargetDirectDepends(gt);
    for (auto const& d : deps) {
      // Take the union of visited source files of custom commands
      auto depVisited = this->GetCommandsVisited(d);
      gtVisited.insert(depVisited.begin(), depVisited.end());
    }

    std::unique_ptr<cmMakefileTargetGenerator> tg(
      cmMakefileTargetGenerator::New(gt));
    if (tg) {
      tg->WriteRuleFiles();
      gg->RecordTargetProgress(tg.get());
    }
  }

  // write the local Makefile
  this->WriteLocalMakefile();

  // Write the cmake file with information for this directory.
  this->WriteDirectoryInformationFile();
}

std::string cmLocalUnixMakefileGenerator3::GetObjectOutputRoot(
  cmStateEnums::IntermediateDirKind kind) const
{
  if (this->UseShortObjectNames(kind)) {
    return cmStrCat(this->GetCurrentBinaryDirectory(), '/',
                    this->GetGlobalGenerator()->GetShortBinaryOutputDir());
  }
  return cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
}

void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
{
  // Compute the path to use when referencing the current output
  // directory from the top output directory.
  this->HomeRelativeOutputPath =
    this->MaybeRelativeToTopBinDir(this->GetCurrentBinaryDirectory());
  if (this->HomeRelativeOutputPath == ".") {
    this->HomeRelativeOutputPath.clear();
  }
  if (!this->HomeRelativeOutputPath.empty()) {
    this->HomeRelativeOutputPath += "/";
  }
}

void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
  std::map<std::string, LocalObjectInfo>& localObjectFiles)
{
  for (auto const& gt : this->GetGeneratorTargets()) {
    if (!gt->CanCompileSources()) {
      continue;
    }
    std::vector<cmSourceFile const*> objectSources;
    gt->GetObjectSources(objectSources, this->GetConfigName());
    // Compute full path to object file directory for this target.
    std::string dir = cmStrCat(gt->GetSupportDirectory(), '/');
    // Compute the name of each object file.
    for (cmSourceFile const* sf : objectSources) {
      bool hasSourceExtension = true;
      std::string objectName =
        this->GetObjectFileNameWithoutTarget(*sf, dir, &hasSourceExtension);
      if (cmSystemTools::FileIsFullPath(objectName)) {
        objectName = cmSystemTools::GetFilenameName(objectName);
      }
      LocalObjectInfo& info = localObjectFiles[objectName];
      info.HasSourceExtension = hasSourceExtension;
      info.emplace_back(gt.get(), sf->GetLanguage());
    }
  }
}

void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets(
  std::vector<std::string>& targets)
{
  std::map<std::string, LocalObjectInfo> localObjectFiles;
  this->GetLocalObjectFiles(localObjectFiles);
  for (auto const& localObjectFile : localObjectFiles) {
    targets.push_back(localObjectFile.first);

    std::string::size_type dot_pos = localObjectFile.first.rfind('.');
    std::string base = localObjectFile.first.substr(0, dot_pos);
    if (localObjectFile.second.HasPreprocessRule) {
      targets.push_back(base + ".i");
    }

    if (localObjectFile.second.HasAssembleRule) {
      targets.push_back(base + ".s");
    }
  }
}

std::string cmLocalUnixMakefileGenerator3::GetLinkDependencyFile(
  cmGeneratorTarget* target, std::string const& /*config*/) const
{
  return cmStrCat(target->GetSupportDirectory(), "/link.d");
}

void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
{
  // generate the includes
  std::string ruleFileName = "Makefile";

  // Open the rule file.  This should be copy-if-different because the
  // rules may depend on this file itself.
  std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
  cmGeneratedFileStream ruleFileStream(
    ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
  if (!ruleFileStream) {
    return;
  }
  // always write the top makefile
  if (!this->IsRootMakefile()) {
    ruleFileStream.SetCopyIfDifferent(true);
  }

  // write the all rules
  this->WriteLocalAllRules(ruleFileStream);

  // only write local targets unless at the top Keep track of targets already
  // listed.
  std::set<std::string> emittedTargets;
  if (!this->IsRootMakefile()) {
    // write our targets, and while doing it collect up the object
    // file rules
    this->WriteLocalMakefileTargets(ruleFileStream, emittedTargets);
  } else {
    cmGlobalUnixMakefileGenerator3* gg =
      static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
    gg->WriteConvenienceRules(ruleFileStream, emittedTargets);
  }

  bool do_preprocess_rules = this->GetCreatePreprocessedSourceRules();
  bool do_assembly_rules = this->GetCreateAssemblySourceRules();

  std::map<std::string, LocalObjectInfo> localObjectFiles;
  this->GetLocalObjectFiles(localObjectFiles);

  // now write out the object rules
  // for each object file name
  for (auto& localObjectFile : localObjectFiles) {
    // Add a convenience rule for building the object file.
    this->WriteObjectConvenienceRule(
      ruleFileStream, "target to build an object file", localObjectFile.first,
      localObjectFile.second);

    // Check whether preprocessing and assembly rules make sense.
    // They make sense only for C and C++ sources.
    bool lang_has_preprocessor = false;
    bool lang_has_assembly = false;

    for (LocalObjectEntry const& entry : localObjectFile.second) {
      if (entry.Language == "C" || entry.Language == "CXX" ||
          entry.Language == "CUDA" || entry.Language == "Fortran" ||
          entry.Language == "HIP" || entry.Language == "ISPC") {
        // Right now, C, C++, CUDA, Fortran, HIP and ISPC have both a
        // preprocessor and the ability to generate assembly code
        lang_has_preprocessor = true;
        lang_has_assembly = true;
        break;
      }
    }

    // Add convenience rules for preprocessed and assembly files.
    if (lang_has_preprocessor && do_preprocess_rules) {
      std::string::size_type dot_pos = localObjectFile.first.rfind(".");
      std::string base = localObjectFile.first.substr(0, dot_pos);
      this->WriteObjectConvenienceRule(ruleFileStream,
                                       "target to preprocess a source file",
                                       (base + ".i"), localObjectFile.second);
      localObjectFile.second.HasPreprocessRule = true;
    }

    if (lang_has_assembly && do_assembly_rules) {
      std::string::size_type dot_pos = localObjectFile.first.rfind(".");
      std::string base = localObjectFile.first.substr(0, dot_pos);
      this->WriteObjectConvenienceRule(
        ruleFileStream, "target to generate assembly for a file",
        (base + ".s"), localObjectFile.second);
      localObjectFile.second.HasAssembleRule = true;
    }
  }

  // add a help target as long as there isn;t a real target named help
  if (emittedTargets.insert("help").second) {
    cmGlobalUnixMakefileGenerator3* gg =
      static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
    gg->WriteHelpRule(ruleFileStream, this);
  }

  this->WriteSpecialTargetsBottom(ruleFileStream);
}

void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule(
  std::ostream& ruleFileStream, char const* comment, std::string const& output,
  LocalObjectInfo const& info)
{
  // If the rule includes the source file extension then create a
  // version that has the extension removed.  The help should include
  // only the version without source extension.
  bool inHelp = true;
  if (info.HasSourceExtension) {
    // Remove the last extension.  This should be kept.
    std::string outBase1 = output;
    std::string outExt1 = cmSplitExtension(outBase1, outBase1);

    // Now remove the source extension and put back the last
    // extension.
    std::string outNoExt;
    cmSplitExtension(outBase1, outNoExt);
    outNoExt += outExt1;

    // Add a rule to drive the rule below.
    std::vector<std::string> depends;
    depends.emplace_back(output);
    std::vector<std::string> no_commands;
    this->WriteMakeRule(ruleFileStream, nullptr, outNoExt, depends,
                        no_commands, true, true);
    inHelp = false;
  }

  // Recursively make the rule for each target using the object file.
  std::vector<std::string> commands;
  for (LocalObjectEntry const& t : info) {
    std::string tgtMakefileName = this->GetRelativeTargetDirectory(t.Target);
    std::string targetName = tgtMakefileName;
    tgtMakefileName += "/build.make";
    targetName += "/";
    targetName += output;
    commands.push_back(
      this->GetRecursiveMakeCall(tgtMakefileName, targetName));
  }
  this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                        this->GetCurrentBinaryDirectory());

  // Write the rule to the makefile.
  std::vector<std::string> no_depends;
  this->WriteMakeRule(ruleFileStream, comment, output, no_depends, commands,
                      true, inHelp);
}

void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
  std::ostream& ruleFileStream, std::set<std::string>& emitted)
{
  std::vector<std::string> depends;
  std::vector<std::string> commands;

  // for each target we just provide a rule to cd up to the top and do a make
  // on the target
  std::string localName;
  for (auto const& target : this->GetGeneratorTargets()) {
    if ((target->GetType() == cmStateEnums::EXECUTABLE) ||
        (target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
        (target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
        (target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
        (target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
        (target->GetType() == cmStateEnums::UTILITY)) {
      emitted.insert(target->GetName());

      // for subdirs add a rule to build this specific target by name.
      localName =
        cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/rule");
      commands.clear();
      depends.clear();

      // Build the target for this pass.
      std::string makefile2 = "CMakeFiles/Makefile2";
      commands.push_back(this->GetRecursiveMakeCall(makefile2, localName));
      this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                            this->GetCurrentBinaryDirectory());
      this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
                          localName, depends, commands, true);

      // Add a target with the canonical name (no prefix, suffix or path).
      if (localName != target->GetName()) {
        commands.clear();
        depends.push_back(localName);
        this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
                            target->GetName(), depends, commands, true);
      }

      // Add a fast rule to build the target
      std::string makefileName = cmStrCat(
        this->GetRelativeTargetDirectory(target.get()), "/build.make");
      // make sure the makefile name is suitable for a makefile
      std::string makeTargetName =
        cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/build");
      localName = cmStrCat(target->GetName(), "/fast");
      depends.clear();
      commands.clear();
      commands.push_back(
        this->GetRecursiveMakeCall(makefileName, makeTargetName));
      this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                            this->GetCurrentBinaryDirectory());
      this->WriteMakeRule(ruleFileStream, "fast build rule for target.",
                          localName, depends, commands, true);

      // Add a local name for the rule to relink the target before
      // installation.
      if (target->NeedRelinkBeforeInstall(this->GetConfigName())) {
        makeTargetName = cmStrCat(
          this->GetRelativeTargetDirectory(target.get()), "/preinstall");
        localName = cmStrCat(target->GetName(), "/preinstall");
        depends.clear();
        commands.clear();
        commands.push_back(
          this->GetRecursiveMakeCall(makefile2, makeTargetName));
        this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                              this->GetCurrentBinaryDirectory());
        this->WriteMakeRule(ruleFileStream,
                            "Manual pre-install relink rule for target.",
                            localName, depends, commands, true);
      }
    }
  }
}

void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
{
  std::string infoFileName =
    cmStrCat(this->GetCurrentBinaryDirectory(),
             "/CMakeFiles/CMakeDirectoryInformation.cmake");

  // Open the output file.
  cmGeneratedFileStream infoFileStream(infoFileName);
  if (!infoFileStream) {
    return;
  }

  infoFileStream.SetCopyIfDifferent(true);
  // Write the do not edit header.
  this->WriteDisclaimer(infoFileStream);

  // Setup relative path conversion tops.
  infoFileStream << "# Relative path conversion top directories.\n"
                    "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \""
                 << this->GetRelativePathTopSource() << "\")\n"
                 << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \""
                 << this->GetRelativePathTopBinary() << "\")\n"
                 << '\n';

  // Tell the dependency scanner to use unix paths if necessary.
  if (cmSystemTools::GetForceUnixPaths()) {
    infoFileStream << "# Force unix paths in dependencies.\n"
                      "set(CMAKE_FORCE_UNIX_PATHS 1)\n"
                      "\n";
  }

  // Store the include regular expressions for this directory.
  infoFileStream << "\n"
                    "# The C and CXX include file regular expressions for "
                    "this directory.\n"
                    "set(CMAKE_C_INCLUDE_REGEX_SCAN ";
  cmLocalUnixMakefileGenerator3::WriteCMakeArgument(
    infoFileStream, this->Makefile->GetIncludeRegularExpression());
  infoFileStream << ")\n"
                    "set(CMAKE_C_INCLUDE_REGEX_COMPLAIN ";
  cmLocalUnixMakefileGenerator3::WriteCMakeArgument(
    infoFileStream, this->Makefile->GetComplainRegularExpression());
  infoFileStream
    << ")\n"
    << "set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n"
       "set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN "
       "${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
}

std::string cmLocalUnixMakefileGenerator3::ConvertToFullPath(
  std::string const& localPath)
{
  std::string dir =
    cmStrCat(this->GetCurrentBinaryDirectory(), '/', localPath);
  return dir;
}

std::string const& cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
{
  return this->HomeRelativeOutputPath;
}

std::string cmLocalUnixMakefileGenerator3::ConvertToMakefilePath(
  std::string const& path) const
{
  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  return gg->ConvertToMakefilePath(path);
}

void cmLocalUnixMakefileGenerator3::WriteMakeRule(
  std::ostream& os, char const* comment, std::string const& target,
  std::vector<std::string> const& depends,
  std::vector<std::string> const& commands, bool symbolic, bool in_help)
{
  // Make sure there is a target.
  if (target.empty()) {
    std::string err("No target for WriteMakeRule! called with comment: ");
    if (comment) {
      err += comment;
    }
    cmSystemTools::Error(err);
    return;
  }

  std::string replace;

  // Write the comment describing the rule in the makefile.
  if (comment) {
    replace = comment;
    std::string::size_type lpos = 0;
    std::string::size_type rpos;
    while ((rpos = replace.find('\n', lpos)) != std::string::npos) {
      os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
      lpos = rpos + 1;
    }
    os << "# " << replace.substr(lpos) << "\n";
  }

  // Construct the left hand side of the rule.
  std::string tgt =
    this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(target));

  char const* space = "";
  if (tgt.size() == 1) {
    // Add a space before the ":" to avoid drive letter confusion on
    // Windows.
    space = " ";
  }

  // Mark the rule as symbolic if requested.
  if (symbolic) {
    if (cmValue sym =
          this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) {
      os << tgt << space << ": " << *sym << '\n';
    }
  }

  // Write the rule.
  if (depends.empty()) {
    // No dependencies.  The commands will always run.
    os << tgt << space << ":\n";
  } else {
    // Split dependencies into multiple rule lines.  This allows for
    // very long dependency lists even on older make implementations.
    for (std::string const& depend : depends) {
      os << tgt << space << ": "
         << this->ConvertToMakefilePath(this->MaybeRelativeToTopBinDir(depend))
         << '\n';
    }
  }

  if (!commands.empty()) {
    // Write the list of commands.
    os << cmWrap("\t", commands, "", "\n") << '\n';
  }
  if (symbolic && !this->IsWatcomWMake()) {
    os << ".PHONY : " << tgt << '\n';
  }
  os << '\n';
  // Add the output to the local help if requested.
  if (in_help) {
    this->LocalHelp.push_back(target);
  }
}

std::string cmLocalUnixMakefileGenerator3::MaybeConvertWatcomShellCommand(
  std::string const& cmd)
{
  if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd) &&
      cmd.find_first_of("( )") != std::string::npos) {
    // On Watcom WMake use the windows short path for the command
    // name.  This is needed to avoid funny quoting problems on
    // lines with shell redirection operators.
    std::string scmd;
    if (cmSystemTools::GetShortPath(cmd, scmd)) {
      return this->ConvertToOutputFormat(scmd, cmOutputConverter::SHELL);
    }
  }
  return std::string();
}

void cmLocalUnixMakefileGenerator3::WriteMakeVariables(
  std::ostream& makefileStream)
{
  this->WriteDivider(makefileStream);
  makefileStream << "# Set environment variables for the build.\n"
                    "\n";
  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  if (gg->DefineWindowsNULL) {
    makefileStream << "!IF \"$(OS)\" == \"Windows_NT\"\n"
                      "NULL=\n"
                      "!ELSE\n"
                      "NULL=nul\n"
                      "!ENDIF\n";
  }
  if (this->IsWindowsShell()) {
    makefileStream << "SHELL = cmd.exe\n"
                      "\n";
  } else {
#if !defined(__VMS)
    makefileStream << "# The shell in which to execute make rules.\n"
                      "SHELL = /bin/sh\n"
                      "\n";
#endif
  }

  auto getShellCommand = [this](std::string command) -> std::string {
    std::string shellCommand = this->MaybeConvertWatcomShellCommand(command);
    return shellCommand.empty()
      ? this->ConvertToOutputFormat(command, cmOutputConverter::SHELL)
      : shellCommand;
  };

  std::string cmakeShellCommand =
    getShellCommand(cmSystemTools::GetCMakeCommand());

  makefileStream << "# The CMake executable.\n"
                    "CMAKE_COMMAND = "
                 << cmakeShellCommand << "\n";

#ifndef CMAKE_BOOTSTRAP
  if (this->GetCMakeInstance()->GetInstrumentation()->HasQuery() &&
      // FIXME(#27079): This does not work for MSYS Makefiles.
      this->GlobalGenerator->GetName() != "MSYS Makefiles") {
    std::string ctestShellCommand =
      getShellCommand(cmSystemTools::GetCTestCommand());
    makefileStream << "# The CTest executable.\n"
                      "CTEST_COMMAND = "
                   << ctestShellCommand << "\n";
  }
#endif

  makefileStream
    << "\n"
       "# The command to remove a file.\n"
       "RM = "
    << cmakeShellCommand
    << " -E rm -f\n"
       "\n"
       "# Escaping for special characters.\n"
       "EQUALS = =\n"
       "\n"
       "# The top-level source directory on which CMake was run.\n"
       "CMAKE_SOURCE_DIR = "
    << this->ConvertToOutputFormat(this->GetSourceDirectory(),
                                   cmOutputConverter::SHELL)
    << "\n"
       "\n"
       "# The top-level build directory on which CMake was run.\n"
       "CMAKE_BINARY_DIR = "
    << this->ConvertToOutputFormat(this->GetBinaryDirectory(),
                                   cmOutputConverter::SHELL)
    << "\n"
       "\n";
}

void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop(
  std::ostream& makefileStream)
{
  this->WriteDivider(makefileStream);
  makefileStream << "# Special targets provided by cmake.\n"
                    "\n";

  std::vector<std::string> no_commands;
  std::vector<std::string> no_depends;

  // Special target to cleanup operation of make tool.
  // This should be the first target except for the default_target in
  // the interface Makefile.
  this->WriteMakeRule(makefileStream,
                      "Disable implicit rules so canonical targets will work.",
                      ".SUFFIXES", no_depends, no_commands, false);

  if (!this->IsNMake() && !this->IsWatcomWMake() &&
      !this->BorlandMakeCurlyHack) {
    // turn off RCS and SCCS automatic stuff from gmake
    constexpr char const* vcs_rules[] = {
      "%,v", "RCS/%", "RCS/%,v", "SCCS/s.%", "s.%",
    };
    for (auto const* vcs_rule : vcs_rules) {
      std::vector<std::string> vcs_depend;
      vcs_depend.emplace_back(vcs_rule);
      this->WriteMakeRule(makefileStream, "Disable VCS-based implicit rules.",
                          "%", vcs_depend, no_commands, false);
    }
  }
  // Add a fake suffix to keep HP happy.  Must be max 32 chars for SGI make.
  std::vector<std::string> depends;
  depends.emplace_back(".hpux_make_needs_suffix_list");
  this->WriteMakeRule(makefileStream, nullptr, ".SUFFIXES", depends,
                      no_commands, false);
  if (this->IsWatcomWMake()) {
    // Switch on WMake feature, if an error or interrupt occurs during
    // makefile processing, the current target being made may be deleted
    // without prompting (the same as command line -e option).
    makefileStream << "\n"
                      ".ERASE\n"
                      "\n";
  }
  if (this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")) {
    makefileStream << "# Produce verbose output by default.\n"
                      "VERBOSE = 1\n"
                      "\n";
  }
  if (this->IsWatcomWMake()) {
    makefileStream << "!ifndef VERBOSE\n"
                      ".SILENT\n"
                      "!endif\n"
                      "\n";
  } else {
    makefileStream << "# Command-line flag to silence nested $(MAKE).\n"
                      "$(VERBOSE)MAKESILENT = -s\n"
                      "\n";

    // Write special target to silence make output.  This must be after
    // the default target in case VERBOSE is set (which changes the
    // name).  The setting of CMAKE_VERBOSE_MAKEFILE to ON will cause a
    // "VERBOSE=1" to be added as a make variable which will change the
    // name of this special target.  This gives a make-time choice to
    // the user.
    // Write directly to the stream since WriteMakeRule escapes '$'.
    makefileStream << "#Suppress display of executed commands.\n"
                      "$(VERBOSE).SILENT:\n"
                      "\n";
  }

  // Work-around for makes that drop rules that have no dependencies
  // or commands.
  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  std::string hack = gg->GetEmptyRuleHackDepends();
  if (!hack.empty()) {
    no_depends.push_back(std::move(hack));
  }
  std::string hack_cmd = gg->GetEmptyRuleHackCommand();
  if (!hack_cmd.empty()) {
    no_commands.push_back(std::move(hack_cmd));
  }

  // Special symbolic target that never exists to force dependers to
  // run their rules.
  this->WriteMakeRule(makefileStream, "A target that is always out of date.",
                      "cmake_force", no_depends, no_commands, true);

  // Variables for reference by other rules.
  this->WriteMakeVariables(makefileStream);
}

void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
  std::ostream& makefileStream)
{
  this->WriteDivider(makefileStream);
  makefileStream << "# Special targets to cleanup operation of make.\n"
                    "\n";

  // Write special "cmake_check_build_system" target to run cmake with
  // the --check-build-system flag.
  if (!this->GlobalGenerator->GlobalSettingIsOn(
        "CMAKE_SUPPRESS_REGENERATION")) {
    // Build command to run CMake to check if anything needs regenerating.
    std::vector<std::string> commands;
    cmake* cm = this->GlobalGenerator->GetCMakeInstance();
    if (cm->DoWriteGlobVerifyTarget()) {
      std::string rescanRule =
        cmStrCat("$(CMAKE_COMMAND) -P ",
                 this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
                                             cmOutputConverter::SHELL));
      commands.push_back(rescanRule);
    }
    std::string cmakefileName = "CMakeFiles/Makefile.cmake";
    std::string runRule = cmStrCat(
      "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) ",
      cm->GetIgnoreCompileWarningAsError() ? "--compile-no-warning-as-error "
                                           : "",
      cm->GetIgnoreLinkWarningAsError() ? "--link-no-warning-as-error " : "",
      "--check-build-system ",
      this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
      " 0");

    std::vector<std::string> no_depends;
    commands.push_back(std::move(runRule));
#ifndef CMAKE_BOOTSTRAP
    // FIXME(#27079): This does not work for MSYS Makefiles.
    if (this->GlobalGenerator->GetName() != "MSYS Makefiles") {
      addInstrumentationCommand(this->GetCMakeInstance()->GetInstrumentation(),
                                commands);
    }
#endif
    if (!this->IsRootMakefile()) {
      this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                            this->GetCurrentBinaryDirectory());
    }
    this->WriteMakeRule(makefileStream,
                        "Special rule to run CMake to check the build system "
                        "integrity.\n"
                        "No rule that depends on this can have "
                        "commands that come from listfiles\n"
                        "because they might be regenerated.",
                        "cmake_check_build_system", no_depends, commands,
                        true);
  }
}

void cmLocalUnixMakefileGenerator3::WriteConvenienceRule(
  std::ostream& ruleFileStream, std::string const& realTarget,
  std::string const& helpTarget)
{
  // A rule is only needed if the names are different.
  if (realTarget != helpTarget) {
    // The helper target depends on the real target.
    std::vector<std::string> depends;
    depends.push_back(realTarget);

    // There are no commands.
    std::vector<std::string> no_commands;

    // Write the rule.
    this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
                        helpTarget, depends, no_commands, true);
  }
}

std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
  cmGeneratorTarget const* target) const
{
  return this->MaybeRelativeToTopBinDir(target->GetSupportDirectory());
}

void cmLocalUnixMakefileGenerator3::AppendFlags(
  std::string& flags, std::string const& newFlags) const
{
  if (this->IsWatcomWMake() && !newFlags.empty()) {
    std::string newf = newFlags;
    if (newf.find("\\\"") != std::string::npos) {
      cmSystemTools::ReplaceString(newf, "\\\"", "\"");
      this->cmLocalGenerator::AppendFlags(flags, newf);
      return;
    }
  }
  this->cmLocalGenerator::AppendFlags(flags, newFlags);
}

void cmLocalUnixMakefileGenerator3::AppendRuleDepend(
  std::vector<std::string>& depends, char const* ruleFileName)
{
  // Add a dependency on the rule file itself unless an option to skip
  // it is specifically enabled by the user or project.
  cmValue nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
  if (nodep.IsOff()) {
    depends.emplace_back(ruleFileName);
  }
}

void cmLocalUnixMakefileGenerator3::AppendRuleDepends(
  std::vector<std::string>& depends, std::vector<std::string> const& ruleFiles)
{
  // Add a dependency on the rule file itself unless an option to skip
  // it is specifically enabled by the user or project.
  if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) {
    cm::append(depends, ruleFiles);
  }
}

void cmLocalUnixMakefileGenerator3::AppendCustomDepends(
  std::vector<std::string>& depends, std::vector<cmCustomCommand> const& ccs)
{
  for (cmCustomCommand const& cc : ccs) {
    cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this);
    this->AppendCustomDepend(depends, ccg);
  }
}

void cmLocalUnixMakefileGenerator3::AppendCustomDepend(
  std::vector<std::string>& depends, cmCustomCommandGenerator const& ccg)
{
  for (std::string const& d : ccg.GetDepends()) {
    // Lookup the real name of the dependency in case it is a CMake target.
    std::string dep;
    if (this->GetRealDependency(d, this->GetConfigName(), dep)) {
      depends.push_back(std::move(dep));
    }
  }
}

void cmLocalUnixMakefileGenerator3::AppendCustomCommands(
  std::vector<std::string>& commands, std::vector<cmCustomCommand> const& ccs,
  cmGeneratorTarget* target, std::string const& relative)
{
  for (cmCustomCommand const& cc : ccs) {
    cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this);
    this->AppendCustomCommand(commands, ccg, target, relative, true);
  }
}

void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
  std::vector<std::string>& commands, cmCustomCommandGenerator const& ccg,
  cmGeneratorTarget* target, std::string const& relative, bool echo_comment,
  std::ostream* content)
{
  // Optionally create a command to display the custom command's
  // comment text.  This is used for pre-build, pre-link, and
  // post-build command comments.  Custom build step commands have
  // their comments generated elsewhere.
  if (echo_comment) {
    if (cm::optional<std::string> comment = ccg.GetComment()) {
      this->AppendEcho(commands, *comment,
                       cmLocalUnixMakefileGenerator3::EchoGenerate);
    }
  }

  // if the command specified a working directory use it.
  std::string dir = this->GetCurrentBinaryDirectory();
  std::string workingDir = ccg.GetWorkingDirectory();
  if (!workingDir.empty()) {
    dir = workingDir;
  }
  if (content) {
    *content << dir;
  }

  auto rulePlaceholderExpander = this->CreateRulePlaceholderExpander();

  // Add each command line to the set of commands.
  std::vector<std::string> commands1;
  for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
    // Build the command line in a single string.
    std::string cmd = ccg.GetCommand(c);
    if (!cmd.empty()) {
      // Use "call " before any invocations of .bat or .cmd files
      // invoked as custom commands in the WindowsShell.
      //
      bool useCall = false;

      if (this->IsWindowsShell()) {
        std::string suffix;
        if (cmd.size() > 4) {
          suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4));
          if (suffix == ".bat" || suffix == ".cmd") {
            useCall = true;
          }
        }
      }

      cmSystemTools::ReplaceString(cmd, "/./", "/");
      // Convert the command to a relative path only if the current
      // working directory will be the start-output directory.
      bool had_slash = cmd.find('/') != std::string::npos;
      if (workingDir.empty()) {
        cmd = this->MaybeRelativeToCurBinDir(cmd);
      }
      bool has_slash = cmd.find('/') != std::string::npos;
      if (had_slash && !has_slash) {
        // This command was specified as a path to a file in the
        // current directory.  Add a leading "./" so it can run
        // without the current directory being in the search path.
        cmd = cmStrCat("./", cmd);
      }

      std::string launcher;
      // Short-circuit if there is no launcher.
      std::string val = this->GetRuleLauncher(
        target, "RULE_LAUNCH_CUSTOM",
        this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
      if (cmNonempty(val)) {
        // Expand rule variables referenced in the given launcher command.
        cmRulePlaceholderExpander::RuleVariables vars;
        std::string targetSupportDir =
          target->GetGlobalGenerator()->ConvertToOutputPath(
            target->GetCMFSupportDirectory());
        targetSupportDir = target->GetLocalGenerator()->ConvertToOutputFormat(
          target->GetLocalGenerator()->MaybeRelativeToTopBinDir(
            targetSupportDir),
          cmOutputConverter::SHELL);
        vars.TargetSupportDir = targetSupportDir.c_str();
        vars.CMTargetName = target->GetName().c_str();
        vars.CMTargetType =
          cmState::GetTargetTypeName(target->GetType()).c_str();
        std::string output;
        std::vector<std::string> const& outputs = ccg.GetOutputs();
        for (size_t i = 0; i < outputs.size(); ++i) {
          output = cmStrCat(output,
                            this->ConvertToOutputFormat(
                              ccg.GetWorkingDirectory().empty()
                                ? this->MaybeRelativeToCurBinDir(outputs[i])
                                : outputs[i],
                              cmOutputConverter::SHELL));
          if (i != outputs.size() - 1) {
            output = cmStrCat(output, ',');
          }
        }
        vars.Output = output.c_str();
        vars.Role = ccg.GetCC().GetRole().c_str();
        vars.CMTargetName = ccg.GetCC().GetTarget().c_str();
        vars.Config = ccg.GetOutputConfig().c_str();

        launcher = val;
        rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
        if (!launcher.empty()) {
          launcher += " ";
        }
      }

      std::string shellCommand = this->MaybeConvertWatcomShellCommand(cmd);
      if (shellCommand.empty()) {
        shellCommand =
          this->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
      }
      cmd = launcher + shellCommand;

      ccg.AppendArguments(c, cmd);
      if (content) {
        // Rule content does not include the launcher.
        *content << (cmd.c_str() + launcher.size());
      }
      if (this->BorlandMakeCurlyHack) {
        // Borland Make has a very strange bug.  If the first curly
        // brace anywhere in the command string is a left curly, it
        // must be written {{} instead of just {.  Otherwise some
        // curly braces are removed.  The hack can be skipped if the
        // first curly brace is the last character.
        std::string::size_type lcurly = cmd.find('{');
        if (lcurly != std::string::npos && lcurly < (cmd.size() - 1)) {
          std::string::size_type rcurly = cmd.find('}');
          if (rcurly == std::string::npos || rcurly > lcurly) {
            // The first curly is a left curly.  Use the hack.
            cmd =
              cmStrCat(cmd.substr(0, lcurly), "{{}", cmd.substr(lcurly + 1));
          }
        }
      }
      if (launcher.empty()) {
        if (useCall) {
          cmd = cmStrCat("call ", cmd);
        } else if (this->IsNMake() && cmd[0] == '"') {
          cmd = cmStrCat("echo >nul && ", cmd);
        }
      }
      commands1.push_back(std::move(cmd));
    }
  }

  // Setup the proper working directory for the commands.
  this->CreateCDCommand(commands1, dir, relative);

  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);

  // Prefix the commands with the jobserver prefix "+"
  if (ccg.GetCC().GetJobserverAware() && gg->IsGNUMakeJobServerAware()) {
    std::transform(commands1.begin(), commands1.end(), commands1.begin(),
                   [](std::string const& cmd) { return cmStrCat('+', cmd); });
  }

  // push back the custom commands
  cm::append(commands, commands1);
}

void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
  std::vector<std::string>& commands, std::set<std::string> const& files,
  cmGeneratorTarget* target, char const* filename)
{
  std::string cleanfile =
    cmStrCat(target->GetSupportDirectory(), "/cmake_clean");
  if (filename) {
    cleanfile += "_";
    cleanfile += filename;
  }
  cleanfile += ".cmake";
  cmsys::ofstream fout(cleanfile.c_str());
  if (!fout) {
    cmSystemTools::Error("Could not create " + cleanfile);
  }
  if (!files.empty()) {
    fout << "file(REMOVE_RECURSE\n";
    for (std::string const& file : files) {
      std::string fc = this->MaybeRelativeToCurBinDir(file);
      fout << "  " << cmScriptGenerator::Quote(fc) << '\n';
    }
    fout << ")\n";
  }
  {
    std::string remove = cmStrCat(
      "$(CMAKE_COMMAND) -P ",
      this->ConvertToOutputFormat(this->MaybeRelativeToCurBinDir(cleanfile),
                                  cmOutputConverter::SHELL));
    commands.push_back(std::move(remove));
  }

  // For the main clean rule add per-language cleaning.
  if (!filename) {
    // Get the set of source languages in the target.
    std::set<std::string> languages;
    target->GetLanguages(
      languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
    auto langFileDir = cmSystemTools::GetFilenamePath(
      this->MaybeRelativeToCurBinDir(cleanfile));
    /* clang-format off */
    fout << "\n"
            "# Per-language clean rules from dependency scanning.\n"
            "foreach(lang " << cmJoin(languages, " ") << ")\n"
            "  include(" << langFileDir
         << "/cmake_clean_${lang}.cmake OPTIONAL)\n"
            "endforeach()\n";
    /* clang-format on */
  }
}

void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
  std::vector<std::string>& commands)
{
  cmList cleanFiles;
  // Look for additional files registered for cleaning in this directory.
  if (cmValue prop_value =
        this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
    cleanFiles.assign(cmGeneratorExpression::Evaluate(
      *prop_value, this,
      this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")));
  }
  if (cleanFiles.empty()) {
    return;
  }

  auto const& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0);
  std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
  std::string cleanfile =
    cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
  // Write clean script
  {
    cmsys::ofstream fout(cleanfile.c_str());
    if (!fout) {
      cmSystemTools::Error("Could not create " + cleanfile);
      return;
    }
    fout << "file(REMOVE_RECURSE\n";
    for (std::string const& cfl : cleanFiles) {
      std::string fc = rootLG->MaybeRelativeToCurBinDir(
        cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
      fout << "  " << cmScriptGenerator::Quote(fc) << '\n';
    }
    fout << ")\n";
  }
  // Create command
  {
    std::string remove = cmStrCat(
      "$(CMAKE_COMMAND) -P ",
      this->ConvertToOutputFormat(rootLG->MaybeRelativeToCurBinDir(cleanfile),
                                  cmOutputConverter::SHELL));
    commands.push_back(std::move(remove));
  }
}

void cmLocalUnixMakefileGenerator3::AppendEcho(
  std::vector<std::string>& commands, std::string const& text, EchoColor color,
  EchoProgress const* progress)
{
  // Choose the color for the text.
  std::string color_name;
  if (this->GlobalGenerator->GetToolSupportsColor() && this->ColorMakefile) {
    // See cmake::ExecuteEchoColor in cmake.cxx for these options.
    // This color set is readable on both black and white backgrounds.
    switch (color) {
      case EchoNormal:
        break;
      case EchoDepend:
        color_name = "--magenta --bold ";
        break;
      case EchoBuild:
        color_name = "--green ";
        break;
      case EchoLink:
        color_name = "--green --bold ";
        break;
      case EchoGenerate:
        color_name = "--blue --bold ";
        break;
      case EchoGlobal:
        color_name = "--cyan ";
        break;
    }
  }

  // Echo one line at a time.
  std::string line;
  line.reserve(200);
  for (char const* c = text.c_str();; ++c) {
    if (*c == '\n' || *c == '\0') {
      // Avoid writing a blank last line on end-of-string.
      if (*c != '\0' || !line.empty()) {
        // Add a command to echo this line.
        std::string cmd;
        if (color_name.empty() && !progress) {
          // Use the native echo command.
          cmd = cmStrCat("@echo ", this->EscapeForShell(line, false, true));
        } else {
          // Use cmake to echo the text in color.
          cmd = cmStrCat(
            "@$(CMAKE_COMMAND) -E cmake_echo_color \"--switch=$(COLOR)\" ",
            color_name);
          if (progress) {
            cmd = cmStrCat(cmd, "--progress-dir=",
                           this->ConvertToOutputFormat(
                             progress->Dir, cmOutputConverter::SHELL),
                           " --progress-num=", progress->Arg, ' ');
          }
          cmd += this->EscapeForShell(line);
        }
        commands.emplace_back(std::move(cmd));
      }

      // Reset the line to empty.
      line.clear();

      // Progress appears only on first line.
      progress = nullptr;

      // Terminate on end-of-string.
      if (*c == '\0') {
        return;
      }
    } else if (*c != '\r') {
      // Append this character to the current line.
      line += *c;
    }
  }
}

std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
  std::string const& s, std::string const& s2)
{
  std::string unmodified = cmStrCat(s, s2);
  // if there is no restriction on the length of make variables
  // and there are no "." characters in the string, then return the
  // unmodified combination.
  if ((!this->MakefileVariableSize &&
       unmodified.find('.') == std::string::npos) &&
      (!this->MakefileVariableSize &&
       unmodified.find('+') == std::string::npos) &&
      (!this->MakefileVariableSize &&
       unmodified.find('-') == std::string::npos)) {
    return unmodified;
  }

  // see if the variable has been defined before and return
  // the modified version of the variable
  auto i = this->MakeVariableMap.find(unmodified);
  if (i != this->MakeVariableMap.end()) {
    return i->second;
  }
  // start with the unmodified variable
  std::string ret = unmodified;
  // if this there is no value for this->MakefileVariableSize then
  // the string must have bad characters in it
  if (!this->MakefileVariableSize) {
    std::replace(ret.begin(), ret.end(), '.', '_');
    cmSystemTools::ReplaceString(ret, "-", "__");
    cmSystemTools::ReplaceString(ret, "+", "___");
    int ni = 0;
    char buffer[12];
    // make sure the _ version is not already used, if
    // it is used then add number to the end of the variable
    while (this->ShortMakeVariableMap.count(ret) && ni < 1000) {
      ++ni;
      snprintf(buffer, sizeof(buffer), "%04d", ni);
      ret = unmodified + buffer;
    }
    this->ShortMakeVariableMap[ret] = "1";
    this->MakeVariableMap[unmodified] = ret;
    return ret;
  }

  // if the string is greater than 32 chars it is an invalid variable name
  // for borland make
  if (static_cast<int>(ret.size()) > this->MakefileVariableSize) {
    int keep = this->MakefileVariableSize - 8;
    int size = keep + 3;
    std::string str1 = s;
    std::string str2 = s2;
    // we must shorten the combined string by 4 characters
    // keep no more than 24 characters from the second string
    if (static_cast<int>(str2.size()) > keep) {
      str2 = str2.substr(0, keep);
    }
    if (static_cast<int>(str1.size()) + static_cast<int>(str2.size()) > size) {
      str1 = str1.substr(0, size - str2.size());
    }
    char buffer[12];
    int ni = 0;
    snprintf(buffer, sizeof(buffer), "%04d", ni);
    ret = str1 + str2 + buffer;
    while (this->ShortMakeVariableMap.count(ret) && ni < 1000) {
      ++ni;
      snprintf(buffer, sizeof(buffer), "%04d", ni);
      ret = str1 + str2 + buffer;
    }
    if (ni == 1000) {
      cmSystemTools::Error("Borland makefile variable length too long");
      return unmodified;
    }
    // once an unused variable is found
    this->ShortMakeVariableMap[ret] = "1";
  }
  // always make an entry into the unmodified to variable map
  this->MakeVariableMap[unmodified] = ret;
  return ret;
}

bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
  std::string const& tgtInfo, std::string const& targetName, bool verbose,
  bool color)
{
  // read in the target info file
  if (!this->Makefile->ReadListFile(tgtInfo) ||
      cmSystemTools::GetErrorOccurredFlag()) {
    cmSystemTools::Error("Target DependInfo.cmake file not found");
  }

  bool status = true;

  // Check if any multiple output pairs have a missing file.
  this->CheckMultipleOutputs(verbose);

  auto echoColor = [color](std::string const& m) {
    cm::StdIo::TermAttrSet attrs;
    if (color) {
      attrs = {
        cm::StdIo::TermAttr::ForegroundMagenta,
        cm::StdIo::TermAttr::ForegroundBold,
      };
    }
    Print(cm::StdIo::Out(), attrs, m);
    std::cout << std::endl;
  };

  std::string const targetDir = cmSystemTools::GetFilenamePath(tgtInfo);
  if (!this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
    // dependencies are managed by CMake itself

    std::string const internalDependFile = targetDir + "/depend.internal";
    std::string const dependFile = targetDir + "/depend.make";

    // If the target DependInfo.cmake file has changed since the last
    // time dependencies were scanned then force rescanning.  This may
    // happen when a new source file is added and CMake regenerates the
    // project but no other sources were touched.
    bool needRescanDependInfo = false;
    cmFileTimeCache* ftc =
      this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
    {
      int result;
      if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
        if (verbose) {
          cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo,
                                         "\" is newer than depender \"",
                                         internalDependFile, "\".\n"));
        }
        needRescanDependInfo = true;
      }
    }

    // If the directory information is newer than depend.internal, include
    // dirs may have changed. In this case discard all old dependencies.
    bool needRescanDirInfo = false;
    {
      std::string dirInfoFile =
        cmStrCat(this->GetCurrentBinaryDirectory(),
                 "/CMakeFiles/CMakeDirectoryInformation.cmake");
      int result;
      if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
          result < 0) {
        if (verbose) {
          cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile,
                                         "\" is newer than depender \"",
                                         internalDependFile, "\".\n"));
        }
        needRescanDirInfo = true;
      }
    }

    // Check the implicit dependencies to see if they are up to date.
    // The build.make file may have explicit dependencies for the object
    // files but these will not affect the scanning process so they need
    // not be considered.
    cmDepends::DependencyMap validDependencies;
    bool needRescanDependencies = false;
    if (!needRescanDirInfo) {
      cmDependsC checker;
      checker.SetVerbose(verbose);
      checker.SetFileTimeCache(ftc);
      // cmDependsC::Check() fills the vector validDependencies() with the
      // dependencies for those files where they are still valid, i.e.
      // neither the files themselves nor any files they depend on have
      // changed. We don't do that if the CMakeDirectoryInformation.cmake
      // file has changed, because then potentially all dependencies have
      // changed. This information is given later on to cmDependsC, which
      // then only rescans the files where it did not get valid dependencies
      // via this dependency vector. This means that in the normal case, when
      // only few or one file have been edited, then also only this one file
      // is actually scanned again, instead of all files for this target.
      needRescanDependencies =
        !checker.Check(dependFile, internalDependFile, validDependencies);
    }

    if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
      // The dependencies must be regenerated.
      if (verbose) {
        std::string message =
          cmStrCat("Scanning dependencies of target ", targetName);
        echoColor(message);
      }

      status = this->ScanDependencies(targetDir, dependFile,
                                      internalDependFile, validDependencies);
    }
  }

  auto depends =
    this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
  if (!depends.empty()) {
    // dependencies are managed by compiler
    cmList depFiles{ depends, cmList::EmptyElements::Yes };
    std::string const internalDepFile =
      targetDir + "/compiler_depend.internal";
    std::string const depFile = targetDir + "/compiler_depend.make";
    cmDepends::DependencyMap dependencies;
    cmDependsCompiler depsManager;
    bool projectOnly = cmIsOn(
      this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_IN_PROJECT_ONLY"));

    depsManager.SetVerbose(verbose);
    depsManager.SetLocalGenerator(this);

    if (!depsManager.CheckDependencies(
          internalDepFile, depFiles, dependencies,
          projectOnly ? NotInProjectDir(this->GetSourceDirectory(),
                                        this->GetBinaryDirectory())
                      : std::function<bool(std::string const&)>())) {
      // regenerate dependencies files
      if (verbose) {
        auto message =
          cmStrCat("Consolidate compiler generated dependencies of target ",
                   targetName);
        echoColor(message);
      }

      // Open the make depends file.  This should be copy-if-different
      // because the make tool may try to reload it needlessly otherwise.
      cmGeneratedFileStream ruleFileStream(
        depFile, false, this->GlobalGenerator->GetMakefileEncoding());
      ruleFileStream.SetCopyIfDifferent(true);
      if (!ruleFileStream) {
        return false;
      }

      // Open the cmake dependency tracking file.  This should not be
      // copy-if-different because dependencies are re-scanned when it is
      // older than the DependInfo.cmake.
      cmGeneratedFileStream internalRuleFileStream(
        internalDepFile, false, this->GlobalGenerator->GetMakefileEncoding());
      if (!internalRuleFileStream) {
        return false;
      }

      this->WriteDisclaimer(ruleFileStream);
      this->WriteDisclaimer(internalRuleFileStream);

      depsManager.WriteDependencies(dependencies, ruleFileStream,
                                    internalRuleFileStream);
    }
  }

  // The dependencies are already up-to-date.
  return status;
}

bool cmLocalUnixMakefileGenerator3::ScanDependencies(
  std::string const& targetDir, std::string const& dependFile,
  std::string const& internalDependFile, cmDepends::DependencyMap& validDeps)
{
  // Read the directory information file.
  cmMakefile* mf = this->Makefile;
  bool haveDirectoryInfo = false;
  {
    std::string dirInfoFile =
      cmStrCat(this->GetCurrentBinaryDirectory(),
               "/CMakeFiles/CMakeDirectoryInformation.cmake");
    if (mf->ReadListFile(dirInfoFile) &&
        !cmSystemTools::GetErrorOccurredFlag()) {
      haveDirectoryInfo = true;
    }
  }

  // Lookup useful directory information.
  if (haveDirectoryInfo) {
    // Test whether we need to force Unix paths.
    if (cmValue force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) {
      if (!force.IsOff()) {
        cmSystemTools::SetForceUnixPaths(true);
      }
    }

    // Setup relative path top directories.
    cmValue relativePathTopSource =
      mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE");
    cmValue relativePathTopBinary =
      mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY");
    if (relativePathTopSource && relativePathTopBinary) {
      this->SetRelativePathTop(*relativePathTopSource, *relativePathTopBinary);
    }
  } else {
    cmSystemTools::Error("Directory Information file not found");
  }

  // Open the make depends file.  This should be copy-if-different
  // because the make tool may try to reload it needlessly otherwise.
  cmGeneratedFileStream ruleFileStream(
    dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
  ruleFileStream.SetCopyIfDifferent(true);
  if (!ruleFileStream) {
    return false;
  }

  // Open the cmake dependency tracking file.  This should not be
  // copy-if-different because dependencies are re-scanned when it is
  // older than the DependInfo.cmake.
  cmGeneratedFileStream internalRuleFileStream(
    internalDependFile, false, this->GlobalGenerator->GetMakefileEncoding());
  if (!internalRuleFileStream) {
    return false;
  }

  this->WriteDisclaimer(ruleFileStream);
  this->WriteDisclaimer(internalRuleFileStream);

  // for each language we need to scan, scan it
  cmList langs{ mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES") };
  for (std::string const& lang : langs) {
    // construct the checker
    // Create the scanner for this language
    std::unique_ptr<cmDepends> scanner;
    if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" ||
        lang == "OBJC" || lang == "OBJCXX" || lang == "CUDA" ||
        lang == "HIP" || lang == "ISPC") {
      // TODO: Handle RC (resource files) dependencies correctly.
      scanner = cm::make_unique<cmDependsC>(this, targetDir, lang, &validDeps);
    }
#ifndef CMAKE_BOOTSTRAP
    else if (lang == "Fortran") {
      ruleFileStream << "# Note that incremental build could trigger "
                        "a call to cmake_copy_f90_mod on each re-build\n";
      scanner = cm::make_unique<cmDependsFortran>(this);
    } else if (lang == "Java") {
      scanner = cm::make_unique<cmDependsJava>();
    }
#endif

    if (scanner) {
      scanner->SetLocalGenerator(this);
      scanner->SetFileTimeCache(
        this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache());
      scanner->SetLanguage(lang);
      scanner->SetTargetDirectory(targetDir);
      scanner->Write(ruleFileStream, internalRuleFileStream);
    }
  }

  return true;
}

void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
{
  cmMakefile* mf = this->Makefile;

  // Get the string listing the multiple output pairs.
  cmValue pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
  if (!pairs_string) {
    return;
  }

  // Convert the string to a list and preserve empty entries.
  cmList pairs{ *pairs_string, cmList::EmptyElements::Yes };
  for (auto i = pairs.begin(); i != pairs.end() && (i + 1) != pairs.end();) {
    std::string const& depender = *i++;
    std::string const& dependee = *i++;

    // If the depender is missing then delete the dependee to make
    // sure both will be regenerated.
    if (cmSystemTools::FileExists(dependee) &&
        !cmSystemTools::FileExists(depender)) {
      if (verbose) {
        cmSystemTools::Stdout(cmStrCat(
          "Deleting primary custom command output \"", dependee,
          "\" because another output \"", depender, "\" does not exist.\n"));
      }
      cmSystemTools::RemoveFile(dependee);
    }
  }
}

void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
  std::ostream& ruleFileStream)
{
  this->WriteDisclaimer(ruleFileStream);

  // Write the main entry point target.  This must be the VERY first
  // target so that make with no arguments will run it.
  {
    // Just depend on the all target to drive the build.
    std::vector<std::string> depends;
    std::vector<std::string> no_commands;
    depends.emplace_back("all");

    // Write the rule.
    this->WriteMakeRule(ruleFileStream,
                        "Default target executed when no arguments are "
                        "given to make.",
                        "default_target", depends, no_commands, true);

    // Help out users that try "gmake target1 target2 -j".
    cmGlobalUnixMakefileGenerator3* gg =
      static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
    if (gg->AllowNotParallel()) {
      std::vector<std::string> no_depends;
      this->WriteMakeRule(ruleFileStream,
                          "Allow only one \"make -f "
                          "Makefile2\" at a time, but pass "
                          "parallelism.",
                          ".NOTPARALLEL", no_depends, no_commands, false);
    }
  }

  this->WriteSpecialTargetsTop(ruleFileStream);

  // Include the progress variables for the target.
  // Write all global targets
  this->WriteDivider(ruleFileStream);
  ruleFileStream << "# Targets provided globally by CMake.\n"
                    "\n";
  auto const& targets = this->GetGeneratorTargets();
  for (auto const& gt : targets) {
    if (gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
      std::string targetString =
        "Special rule for the target " + gt->GetName();
      std::vector<std::string> commands;
      std::vector<std::string> depends;

      cmValue p = gt->GetProperty("EchoString");
      char const* text = p ? p->c_str() : "Running external command ...";
      depends.reserve(gt->GetUtilities().size());
      for (BT<std::pair<std::string, bool>> const& u : gt->GetUtilities()) {
        depends.push_back(u.Value.first);
      }
      this->AppendEcho(commands, text,
                       cmLocalUnixMakefileGenerator3::EchoGlobal);

      // Global targets store their rules in pre- and post-build commands.
      this->AppendCustomDepends(depends, gt->GetPreBuildCommands());
      this->AppendCustomDepends(depends, gt->GetPostBuildCommands());
      this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt.get(),
                                 this->GetCurrentBinaryDirectory());
      this->AppendCustomCommands(commands, gt->GetPostBuildCommands(),
                                 gt.get(), this->GetCurrentBinaryDirectory());
      std::string targetName = gt->GetName();
      this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName,
                          depends, commands, true);

      // Provide a "/fast" version of the target.
      depends.clear();
      if ((targetName == "install") || (targetName == "install/local") ||
          (targetName == "install/strip")) {
        // Provide a fast install target that does not depend on all
        // but has the same command.
        depends.emplace_back("preinstall/fast");
      } else {
        // Just forward to the real target so at least it will work.
        depends.push_back(targetName);
        commands.clear();
      }
      targetName += "/fast";
      this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName,
                          depends, commands, true);
    }
  }

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

  // Write the all rule.
  std::string recursiveTarget =
    cmStrCat(this->GetCurrentBinaryDirectory(), "/all");

  bool regenerate =
    !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
  if (regenerate) {
    depends.emplace_back("cmake_check_build_system");
  }

  std::string const progressDir = this->ConvertToOutputFormat(
    cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles"),
    cmOutputConverter::SHELL);
  std::string const progressMarks = this->ConvertToOutputFormat(
    this->ConvertToFullPath("/CMakeFiles/progress.marks"),
    cmOutputConverter::SHELL);
  std::string const progressStartCommand =
    cmStrCat("$(CMAKE_COMMAND) -E cmake_progress_start ", progressDir, ' ',
             progressMarks);
  std::string const progressFinishCommand =
    cmStrCat("$(CMAKE_COMMAND) -E cmake_progress_start ", progressDir, " 0");

  commands.emplace_back(progressStartCommand);
  std::string mf2Dir = "CMakeFiles/Makefile2";
  commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
  this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                        this->GetCurrentBinaryDirectory());
  commands.emplace_back(progressFinishCommand);
  this->WriteMakeRule(ruleFileStream, "The main all target", "all", depends,
                      commands, true);

  // Write the codegen rule.
  if (this->GetGlobalGenerator()->CheckCMP0171()) {
    recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/codegen");
    depends.clear();
    commands.clear();
    if (regenerate) {
      depends.emplace_back("cmake_check_build_system");
    }
    commands.emplace_back(progressStartCommand);
    commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
    this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                          this->GetCurrentBinaryDirectory());
    commands.emplace_back(progressFinishCommand);
    this->WriteMakeRule(ruleFileStream, "The main codegen target", "codegen",
                        depends, commands, true);
  }

  // Write the clean rule.
  recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/clean");
  commands.clear();
  depends.clear();
  commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
  this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                        this->GetCurrentBinaryDirectory());
  this->WriteMakeRule(ruleFileStream, "The main clean target", "clean",
                      depends, commands, true);
  commands.clear();
  depends.clear();
  depends.emplace_back("clean");
  this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast",
                      depends, commands, true);

  // Write the preinstall rule.
  recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall");
  commands.clear();
  depends.clear();
  cmValue noall =
    this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
  if (noall.IsOff()) {
    // Drive the build before installing.
    depends.emplace_back("all");
  } else if (regenerate) {
    // At least make sure the build system is up to date.
    depends.emplace_back("cmake_check_build_system");
  }
  commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
  this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                        this->GetCurrentBinaryDirectory());
  this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
                      "preinstall", depends, commands, true);
  depends.clear();
  this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
                      "preinstall/fast", depends, commands, true);

  if (regenerate) {
    // write the depend rule, really a recompute depends rule
    depends.clear();
    commands.clear();
    cmake* cm = this->GlobalGenerator->GetCMakeInstance();
    if (cm->DoWriteGlobVerifyTarget()) {
      std::string rescanRule =
        cmStrCat("$(CMAKE_COMMAND) -P ",
                 this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
                                             cmOutputConverter::SHELL));
      commands.push_back(rescanRule);
    }
    std::string cmakefileName = "CMakeFiles/Makefile.cmake";
    {
      std::string runRule = cmStrCat(
        "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) ",
        cm->GetIgnoreCompileWarningAsError() ? "--compile-no-warning-as-error "
                                             : "",
        cm->GetIgnoreLinkWarningAsError() ? "--link-no-warning-as-error " : "",
        "--check-build-system ",
        this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
        " 1");
      commands.push_back(std::move(runRule));
#ifndef CMAKE_BOOTSTRAP
      // FIXME(#27079): This does not work for MSYS Makefiles.
      if (this->GlobalGenerator->GetName() != "MSYS Makefiles") {
        addInstrumentationCommand(
          this->GetCMakeInstance()->GetInstrumentation(), commands);
      }
#endif
    }
    this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                          this->GetCurrentBinaryDirectory());
    this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
                        commands, true);
  }
}

void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
                                                      bool verbose)
{
  // Get the list of target files to check
  cmValue infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
  if (!infoDef) {
    return;
  }
  cmList files{ *infoDef };

  // Each depend information file corresponds to a target.  Clear the
  // dependencies for that target.
  cmDepends clearer;
  clearer.SetVerbose(verbose);
  for (std::string const& file : files) {
    auto snapshot = mf->GetState()->CreateBaseSnapshot();
    cmMakefile lmf(mf->GetGlobalGenerator(), snapshot);
    lmf.ReadListFile(file);

    if (!lmf.GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
      std::string dir = cmSystemTools::GetFilenamePath(file);

      // Clear the implicit dependency makefile.
      std::string dependFile = dir + "/depend.make";
      clearer.Clear(dependFile);

      // Remove the internal dependency check file to force
      // regeneration.
      std::string internalDependFile = dir + "/depend.internal";
      cmSystemTools::RemoveFile(internalDependFile);
    }

    auto depsFiles = lmf.GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
    if (!depsFiles.empty()) {
      auto dir = cmCMakePath(file).GetParentPath();
      // Clear the implicit dependency makefile.
      auto depFile = cmCMakePath(dir).Append("compiler_depend.make");
      clearer.Clear(depFile.GenericString());

      // Remove the internal dependency check file
      auto internalDepFile =
        cmCMakePath(dir).Append("compiler_depend.internal");
      cmSystemTools::RemoveFile(internalDepFile.GenericString());

      // Touch timestamp file to force dependencies regeneration
      auto DepTimestamp = cmCMakePath(dir).Append("compiler_depend.ts");
      cmSystemTools::Touch(DepTimestamp.GenericString(), true);

      // clear the dependencies files generated by the compiler
      cmList dependencies{ depsFiles, cmList::EmptyElements::Yes };
      cmDependsCompiler depsManager;
      depsManager.SetVerbose(verbose);
      depsManager.ClearDependencies(dependencies);
    }
  }
}

void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
  std::ostream& cmakefileStream, cmGeneratorTarget* target)
{
  // To enable dependencies filtering
  cmakefileStream << "\n"
                     "# Consider dependencies only in project.\n"
                     "set(CMAKE_DEPENDS_IN_PROJECT_ONLY "
                  << (cmIsOn(this->Makefile->GetSafeDefinition(
                        "CMAKE_DEPENDS_IN_PROJECT_ONLY"))
                        ? "ON"
                        : "OFF")
                  << ")\n\n";

  bool requireFortran = false;
  if (target->HaveFortranSources(this->GetConfigName())) {
    requireFortran = true;
  }

  auto const& implicitLangs =
    this->GetImplicitDepends(target, cmDependencyScannerKind::CMake);

  // list the languages
  cmakefileStream << "# The set of languages for which implicit "
                     "dependencies are needed:\n"
                     "set(CMAKE_DEPENDS_LANGUAGES\n";
  for (auto const& implicitLang : implicitLangs) {
    cmakefileStream << "  \"" << implicitLang.first << "\"\n";
    if (requireFortran && implicitLang.first == "Fortran"_s) {
      requireFortran = false;
    }
  }
  if (requireFortran) {
    cmakefileStream << "  \"Fortran\"\n";
  }
  cmakefileStream << "  )\n";

  if (!implicitLangs.empty()) {
    // now list the files for each language
    cmakefileStream
      << "# The set of files for implicit dependencies of each language:\n";
    for (auto const& implicitLang : implicitLangs) {
      auto const& lang = implicitLang.first;

      cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << lang << '\n';
      auto const& implicitPairs = implicitLang.second;

      // for each file pair
      for (auto const& implicitPair : implicitPairs) {
        for (auto const& di : implicitPair.second) {
          cmakefileStream << "  \"" << di << "\" \"" << implicitPair.first
                          << "\"\n";
        }
      }
      cmakefileStream << "  )\n";

      // Tell the dependency scanner what compiler is used.
      std::string cidVar = cmStrCat("CMAKE_", lang, "_COMPILER_ID");
      cmValue cid = this->Makefile->GetDefinition(cidVar);
      if (cmNonempty(cid)) {
        cmakefileStream << "set(CMAKE_" << lang << "_COMPILER_ID \"" << *cid
                        << "\")\n";
      }

      if (lang == "Fortran") {
        std::string smodSep =
          this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
        std::string smodExt =
          this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
        cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
                        << "\")\n"
                           "set(CMAKE_Fortran_SUBMODULE_EXT \""
                        << smodExt << "\")\n";
      }

      // Build a list of preprocessor definitions for the target.
      std::set<std::string> defines;
      this->GetTargetDefines(target, this->GetConfigName(), lang, defines);
      if (!defines.empty()) {
        cmakefileStream << "\n"
                           "# Preprocessor definitions for this target.\n"
                           "set(CMAKE_TARGET_DEFINITIONS_"
                        << lang << '\n';
        for (std::string const& define : defines) {
          cmakefileStream << "  " << cmScriptGenerator::Quote(define) << '\n';
        }
        cmakefileStream << "  )\n";
      }

      // Target-specific include directories:
      cmakefileStream << "\n"
                         "# The include file search paths:\n"
                         "set(CMAKE_"
                      << lang << "_TARGET_INCLUDE_PATH\n";
      std::vector<std::string> includes;

      this->GetIncludeDirectories(includes, target, lang,
                                  this->GetConfigName());
      std::string const& binaryDir = this->GetState()->GetBinaryDirectory();
      if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
        std::string const& sourceDir = this->GetState()->GetSourceDirectory();
        cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
      }
      for (std::string const& include : includes) {
        cmakefileStream << "  \"" << this->MaybeRelativeToTopBinDir(include)
                        << "\"\n";
      }
      cmakefileStream << "  )\n";
    }

    // Store include transform rule properties.  Write the directory
    // rules first because they may be overridden by later target rules.
    cmList transformRules;
    if (cmValue xform =
          this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
      transformRules.assign(*xform);
    }
    if (cmValue xform =
          target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
      transformRules.append(*xform);
    }
    if (!transformRules.empty()) {
      cmakefileStream << "\nset(CMAKE_INCLUDE_TRANSFORMS\n";
      for (std::string const& tr : transformRules) {
        cmakefileStream << "  " << cmScriptGenerator::Quote(tr) << '\n';
      }
      cmakefileStream << "  )\n";
    }
  }

  auto const& compilerLangs =
    this->GetImplicitDepends(target, cmDependencyScannerKind::Compiler);

  // list the dependency files managed by the compiler
  cmakefileStream << "\n# The set of dependency files which are needed:\n"
                     "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
  for (auto const& compilerLang : compilerLangs) {
    auto const& compilerPairs = compilerLang.second;
    if (compilerLang.first == "CUSTOM"_s) {
      for (auto const& compilerPair : compilerPairs) {
        for (auto const& src : compilerPair.second) {
          cmakefileStream << R"(  "" ")"
                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                          << R"(" "custom" ")"
                          << this->MaybeRelativeToTopBinDir(src) << "\"\n";
        }
      }
    } else if (compilerLang.first == "LINK"_s) {
      auto depFormat = this->Makefile->GetDefinition(
        cmStrCat("CMAKE_", target->GetLinkerLanguage(this->GetConfigName()),
                 "_LINKER_DEPFILE_FORMAT"));
      for (auto const& compilerPair : compilerPairs) {
        for (auto const& src : compilerPair.second) {
          cmakefileStream << R"(  "" ")"
                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                          << "\" \"" << depFormat << "\" \""
                          << this->MaybeRelativeToTopBinDir(src) << "\"\n";
        }
      }
    } else {
      auto depFormat = this->Makefile->GetSafeDefinition(
        cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
      for (auto const& compilerPair : compilerPairs) {
        for (auto const& src : compilerPair.second) {
          cmakefileStream << "  \"" << src << "\" \""
                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                          << "\" \"" << depFormat << "\" \""
                          << this->MaybeRelativeToTopBinDir(compilerPair.first)
                          << ".d\"\n";
        }
      }
    }
  }
  cmakefileStream << "  )\n";
}

void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
{
  os << "# CMAKE generated file: DO NOT EDIT!\n"
        "# Generated by \""
     << this->GlobalGenerator->GetName()
     << "\""
        " Generator, CMake Version "
     << cmVersion::GetMajorVersion() << '.' << cmVersion::GetMinorVersion()
     << "\n\n";
}

std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
  std::string const& makefile, std::string const& tgt)
{
  // Call make on the given file.
  std::string cmd = cmStrCat(
    "$(MAKE) $(MAKESILENT) -f ",
    this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL), ' ');

  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  // Pass down verbosity level.
  if (!gg->MakeSilentFlag.empty()) {
    cmd += gg->MakeSilentFlag;
    cmd += " ";
  }

  // Most unix makes will pass the command line flags to make down to
  // sub-invoked makes via an environment variable.  However, some
  // makes do not support that, so you have to pass the flags
  // explicitly.
  if (gg->PassMakeflags) {
    cmd += "-$(MAKEFLAGS) ";
  }

  // Add the target.
  if (!tgt.empty()) {
    // The make target is always relative to the top of the build tree.
    std::string tgt2 = this->MaybeRelativeToTopBinDir(tgt);

    // The target may have been written with windows paths.
    cmSystemTools::ConvertToOutputSlashes(tgt2);

    // Escape one extra time if the make tool requires it.
    if (this->MakeCommandEscapeTargetTwice) {
      tgt2 = this->EscapeForShell(tgt2, true, false);
    }

    // The target name is now a string that should be passed verbatim
    // on the command line.
    cmd += this->EscapeForShell(tgt2, true, false);
  }
  return cmd;
}

void cmLocalUnixMakefileGenerator3::WriteDivider(std::ostream& os)
{
  os << "#======================================"
        "=======================================\n";
}

void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os,
                                                       std::string const& s)
{
  // Write the given string to the stream with escaping to get it back
  // into CMake through the lexical scanner.
  os << '"';
  for (char c : s) {
    if (c == '\\') {
      os << "\\\\";
    } else if (c == '"') {
      os << "\\\"";
    } else {
      os << c;
    }
  }
  os << '"';
}

std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
  std::string const& p, bool useWatcomQuote)
{
  // Split the path into its components.
  std::vector<std::string> components;
  cmSystemTools::SplitPath(p, components);

  // Open the quoted result.
  std::string result;
  if (useWatcomQuote) {
#if defined(_WIN32) && !defined(__CYGWIN__)
    result = "'";
#else
    result = "\"'";
#endif
  } else {
    result = "\"";
  }

  // Return an empty path if there are no components.
  if (!components.empty()) {
    // Choose a slash direction and fix root component.
    char const* slash = "/";
#if defined(_WIN32) && !defined(__CYGWIN__)
    if (!cmSystemTools::GetForceUnixPaths()) {
      slash = "\\";
      for (char& i : components[0]) {
        if (i == '/') {
          i = '\\';
        }
      }
    }
#endif

    // Begin the quoted result with the root component.
    result += components[0];

    if (components.size() > 1) {
      // Now add the rest of the components separated by the proper slash
      // direction for this platform.
      auto compEnd = std::remove(components.begin() + 1, components.end() - 1,
                                 std::string());
      auto compStart = components.begin() + 1;
      result += cmJoin(cmMakeRange(compStart, compEnd), slash);
      // Only the last component can be empty to avoid double slashes.
      result += slash;
      result += components.back();
    }
  }

  // Close the quoted result.
  if (useWatcomQuote) {
#if defined(_WIN32) && !defined(__CYGWIN__)
    result += "'";
#else
    result += "'\"";
#endif
  } else {
    result += "\"";
  }

  return result;
}

cmLocalUnixMakefileGenerator3::ImplicitDependLanguageMap const&
cmLocalUnixMakefileGenerator3::GetImplicitDepends(
  cmGeneratorTarget const* tgt, cmDependencyScannerKind scanner)
{
  return this->ImplicitDepends[tgt->GetName()][scanner];
}

void cmLocalUnixMakefileGenerator3::AddImplicitDepends(
  cmGeneratorTarget const* tgt, std::string const& lang,
  std::string const& obj, std::string const& src,
  cmDependencyScannerKind scanner)
{
  this->ImplicitDepends[tgt->GetName()][scanner][lang][obj].push_back(src);
}

void cmLocalUnixMakefileGenerator3::CreateCDCommand(
  std::vector<std::string>& commands, std::string const& tgtDir,
  std::string const& relDir)
{
  // do we need to cd?
  if (tgtDir == relDir) {
    return;
  }

  // In a Windows shell we must change drive letter too.  The shell
  // used by NMake and Borland make does not support "cd /d" so this
  // feature simply cannot work with them (Borland make does not even
  // support changing the drive letter with just "d:").
  char const* cd_cmd = this->IsMinGWMake() ? "cd /d " : "cd ";

  cmGlobalUnixMakefileGenerator3* gg =
    static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
  if (!gg->UnixCD) {
    // On Windows we must perform each step separately and then change
    // back because the shell keeps the working directory between
    // commands.
    std::string cmd =
      cmStrCat(cd_cmd, this->ConvertToOutputForExisting(tgtDir));
    commands.insert(commands.begin(), cmd);

    // Change back to the starting directory.
    cmd = cmStrCat(cd_cmd, this->ConvertToOutputForExisting(relDir));
    commands.push_back(std::move(cmd));
  } else {
    // On UNIX we must construct a single shell command to change
    // directory and build because make resets the directory between
    // each command.
    std::string outputForExisting = this->ConvertToOutputForExisting(tgtDir);
    std::string prefix = cd_cmd + outputForExisting + " && ";
    std::transform(commands.begin(), commands.end(), commands.begin(),
                   [&prefix](std::string const& s) { return prefix + s; });
  }
}
