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

#include <algorithm>
#include <functional>
#include <sstream>
#include <utility>

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

#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmValue.h"
#include "cmake.h"

cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm)
  : cmGlobalCommonGenerator(cm)
{
  // This type of makefile always requires unix style paths
  this->ForceUnixPaths = true;
  this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
  this->ToolSupportsColor = true;

#if defined(_WIN32) || defined(__VMS)
  this->UseLinkScript = false;
#else
  this->UseLinkScript = true;
#endif

  this->IncludeDirective = "include";
  this->LineContinueDirective = "\\\n";
  this->DefineWindowsNULL = false;
  this->PassMakeflags = false;
  this->UnixCD = true;
}

cmGlobalUnixMakefileGenerator3::~cmGlobalUnixMakefileGenerator3() = default;

void cmGlobalUnixMakefileGenerator3::EnableLanguage(
  std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
{
  this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
  for (std::string const& language : languages) {
    if (language == "NONE") {
      continue;
    }
    this->ResolveLanguageCompiler(language, mf, optional);
  }
}

//! Create a local generator appropriate to this Global Generator
std::unique_ptr<cmLocalGenerator>
cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf)
{
  return std::unique_ptr<cmLocalGenerator>(
    cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf));
}

cmDocumentationEntry cmGlobalUnixMakefileGenerator3::GetDocumentation()
{
  return { cmGlobalUnixMakefileGenerator3::GetActualName(),
           "Generates standard UNIX makefiles." };
}

void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
  cmGeneratorTarget* gt) const
{
  // Compute full path to object file directory for this target.
  std::string dir = cmStrCat(gt->GetSupportDirectory(), '/');
  gt->ObjectDirectory = dir;
}

bool cmGlobalUnixMakefileGenerator3::CanEscapeOctothorpe() const
{
  // Make tools that use UNIX-style '/' paths also support '\' escaping.
  return this->ForceUnixPaths;
}

void cmGlobalUnixMakefileGenerator3::Configure()
{
  // Initialize CMAKE_EDIT_COMMAND cache entry.
  this->GetEditCacheCommand();

  this->cmGlobalGenerator::Configure();
}

void cmGlobalUnixMakefileGenerator3::Generate()
{
  this->ClangTidyExportFixesDirs.clear();
  this->ClangTidyExportFixesFiles.clear();

  // first do superclass method
  this->cmGlobalGenerator::Generate();

  // initialize progress
  unsigned long total = 0;
  for (auto const& pmi : this->ProgressMap) {
    total += pmi.second.NumberOfActions;
  }

  // write each target's progress.make this loop is done twice. Basically the
  // Generate pass counts all the actions, the first loop below determines
  // how many actions have progress updates for each target and writes to
  // correct variable values for everything except the all targets. The
  // second loop actually writes out correct values for the all targets as
  // well. This is because the all targets require more information that is
  // computed in the first loop.
  unsigned long current = 0;
  for (auto& pmi : this->ProgressMap) {
    pmi.second.WriteProgressVariables(total, current);
  }
  for (auto const& lg : this->LocalGenerators) {
    std::string markFileName =
      cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks");
    cmGeneratedFileStream markFile(markFileName);
    markFile << this->CountProgressMarksInAll(*lg) << "\n";
  }

  // write the main makefile
  this->WriteMainMakefile2();
  this->WriteMainCMakefile();

  if (this->CommandDatabase) {
    *this->CommandDatabase << "\n]";
    this->CommandDatabase.reset();
  }

  this->RemoveUnknownClangTidyExportFixesFiles();
}

void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
  std::string const& sourceFile, std::string const& workingDirectory,
  std::string const& compileCommand, std::string const& objPath)
{
  if (!this->CommandDatabase) {
    std::string commandDatabaseName =
      this->GetCMakeInstance()->GetHomeOutputDirectory() +
      "/compile_commands.json";
    this->CommandDatabase =
      cm::make_unique<cmGeneratedFileStream>(commandDatabaseName);
    *this->CommandDatabase << "[\n";
  } else {
    *this->CommandDatabase << ",\n";
  }
  *this->CommandDatabase << "{\n"
                         << R"(  "directory": ")"
                         << cmGlobalGenerator::EscapeJSON(workingDirectory)
                         << "\",\n"
                         << R"(  "command": ")"
                         << cmGlobalGenerator::EscapeJSON(compileCommand)
                         << "\",\n"
                         << R"(  "file": ")"
                         << cmGlobalGenerator::EscapeJSON(sourceFile)
                         << "\",\n"
                         << R"(  "output": ")"
                         << cmGlobalGenerator::EscapeJSON(objPath) << "\"\n}";
}

void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
{
  // Open the output file.  This should not be copy-if-different
  // because the check-build-system step compares the makefile time to
  // see if the build system must be regenerated.
  std::string makefileName =
    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
             "/CMakeFiles/Makefile2");
  cmGeneratedFileStream makefileStream(makefileName, false,
                                       this->GetMakefileEncoding());
  if (!makefileStream) {
    return;
  }

  // The global dependency graph is expressed via the root local generator.
  auto& rootLG = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
    this->LocalGenerators[0]);

  // Write the do not edit header.
  rootLG.WriteDisclaimer(makefileStream);

  // 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.
  rootLG.WriteMakeRule(makefileStream,
                       "Default target executed when no arguments are "
                       "given to make.",
                       "default_target", depends, no_commands, true);

  depends.clear();

  // The all and preinstall rules might never have any dependencies
  // added to them.
  if (!this->EmptyRuleHackDepends.empty()) {
    depends.push_back(this->EmptyRuleHackDepends);
  }

  // Write out the "special" stuff
  rootLG.WriteSpecialTargetsTop(makefileStream);

  // Write the directory level rules.
  for (auto const& it : this->ComputeDirectoryTargets()) {
    this->WriteDirectoryRules2(makefileStream, rootLG, it.second);
  }

  // Write the target convenience rules
  for (auto const& localGen : this->LocalGenerators) {
    this->WriteConvenienceRules2(
      makefileStream, rootLG,
      cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen));
  }

  // Write special bottom targets
  rootLG.WriteSpecialTargetsBottom(makefileStream);
}

void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
  if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
    return;
  }

  // Open the output file.  This should not be copy-if-different
  // because the check-build-system step compares the makefile time to
  // see if the build system must be regenerated.
  std::string cmakefileName =
    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
             "/CMakeFiles/Makefile.cmake");
  cmGeneratedFileStream cmakefileStream(cmakefileName);
  if (!cmakefileStream) {
    return;
  }

  std::string makefileName =
    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile");

  {
    // get a local generator for some useful methods
    auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
      this->LocalGenerators[0]);

    // Write the do not edit header.
    lg.WriteDisclaimer(cmakefileStream);
  }

  // Save the generator name
  cmakefileStream << "# The generator used is:\n"
                  << "set(CMAKE_DEPENDS_GENERATOR \"" << this->GetName()
                  << "\")\n\n";

  // for each cmMakefile get its list of dependencies
  std::vector<std::string> lfiles;
  for (auto const& localGen : this->LocalGenerators) {
    // Get the list of files contributing to this generation step.
    cm::append(lfiles, localGen->GetMakefile()->GetListFiles());
  }

  cmake* cm = this->GetCMakeInstance();
  if (cm->DoWriteGlobVerifyTarget()) {
    lfiles.push_back(cm->GetGlobVerifyScript());
    lfiles.push_back(cm->GetGlobVerifyStamp());
  }

  // Sort the list and remove duplicates.
  std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
#if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
  auto new_end = std::unique(lfiles.begin(), lfiles.end());
  lfiles.erase(new_end, lfiles.end());
#endif

  {
    // reset lg to the first makefile
    auto const& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
      this->LocalGenerators[0]);

    // Save the list to the cmake file.
    cmakefileStream
      << "# The top level Makefile was generated from the following files:\n"
      << "set(CMAKE_MAKEFILE_DEPENDS\n"
      << "  \"CMakeCache.txt\"\n";
    for (std::string const& f : lfiles) {
      cmakefileStream << "  \"" << lg.MaybeRelativeToCurBinDir(f) << "\"\n";
    }
    cmakefileStream << "  )\n\n";

    // Build the path to the cache check file.
    std::string check =
      cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
               "/CMakeFiles/cmake.check_cache");

    // Set the corresponding makefile in the cmake file.
    cmakefileStream << "# The corresponding makefile is:\n"
                    << "set(CMAKE_MAKEFILE_OUTPUTS\n"
                    << "  \"" << lg.MaybeRelativeToCurBinDir(makefileName)
                    << "\"\n"
                    << "  \"" << lg.MaybeRelativeToCurBinDir(check) << "\"\n";
    cmakefileStream << "  )\n\n";

    // CMake must rerun if a byproduct is missing.
    cmakefileStream << "# Byproducts of CMake generate step:\n"
                    << "set(CMAKE_MAKEFILE_PRODUCTS\n";

    // add in any byproducts and all the directory information files
    std::string tmpStr;
    for (auto const& localGen : this->LocalGenerators) {
      for (std::string const& outfile :
           localGen->GetMakefile()->GetOutputFiles()) {
        cmakefileStream << "  \"" << lg.MaybeRelativeToTopBinDir(outfile)
                        << "\"\n";
      }
      tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(),
                        "/CMakeFiles/CMakeDirectoryInformation.cmake");
      cmakefileStream << "  \"" << localGen->MaybeRelativeToTopBinDir(tmpStr)
                      << "\"\n";
    }
    cmakefileStream << "  )\n\n";
  }

  this->WriteMainCMakefileLanguageRules(cmakefileStream,
                                        this->LocalGenerators);
}

void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
  cmGeneratedFileStream& cmakefileStream,
  std::vector<std::unique_ptr<cmLocalGenerator>>& lGenerators)
{
  // now list all the target info files
  cmakefileStream << "# Dependency information for all targets:\n";
  cmakefileStream << "set(CMAKE_DEPEND_INFO_FILES\n";
  for (auto const& lGenerator : lGenerators) {
    auto const& lg =
      cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator);
    // for all of out targets
    for (auto const& tgt : lg.GetGeneratorTargets()) {
      if (tgt->IsInBuildSystem() &&
          tgt->GetType() != cmStateEnums::GLOBAL_TARGET) {
        std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()),
                                     "/DependInfo.cmake");
        cmSystemTools::ConvertToUnixSlashes(tname);
        cmakefileStream << "  \"" << tname << "\"\n";
      }
    }
  }
  cmakefileStream << "  )\n";
}

void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG,
  DirectoryTarget const& dt, char const* pass, bool check_all,
  bool check_relink, std::vector<std::string> const& commands)
{
  auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
  std::string makeTarget =
    cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass);

  // The directory-level rule should depend on the target-level rules
  // for all targets in the directory.
  std::vector<std::string> depends;
  for (DirectoryTarget::Target const& t : dt.Targets) {
    // Add this to the list of depends rules in this directory.
    if ((!check_all || t.ExcludedFromAllInConfigs.empty()) &&
        (!check_relink ||
         t.GT->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
      // The target may be from a different directory; use its local gen.
      auto const* tlg = static_cast<cmLocalUnixMakefileGenerator3 const*>(
        t.GT->GetLocalGenerator());
      std::string tname =
        cmStrCat(tlg->GetRelativeTargetDirectory(t.GT), '/', pass);
      depends.push_back(std::move(tname));
    }
  }

  // The directory-level rule should depend on the directory-level
  // rules of the subdirectories.
  for (DirectoryTarget::Dir const& d : dt.Children) {
    if (check_all && d.ExcludeFromAll) {
      continue;
    }
    std::string subdir = cmStrCat(d.Path, '/', pass);
    depends.push_back(std::move(subdir));
  }

  // Work-around for makes that drop rules that have no dependencies
  // or commands.
  if (depends.empty() && !this->EmptyRuleHackDepends.empty()) {
    depends.push_back(this->EmptyRuleHackDepends);
  }

  // Write the rule.
  std::string doc;
  if (lg->IsRootMakefile()) {
    doc = cmStrCat("The main recursive \"", pass, "\" target.");
  } else {
    doc = cmStrCat("Recursive \"", pass, "\" directory target.");
  }

  rootLG.WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends,
                       commands, true);
}

void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG,
  DirectoryTarget const& dt)
{
  auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
  // Begin the directory-level rules section.
  {
    std::string dir = cmSystemTools::ConvertToOutputPath(
      rootLG.MaybeRelativeToTopBinDir(lg->GetCurrentBinaryDirectory()));
    rootLG.WriteDivider(ruleFileStream);
    if (lg->IsRootMakefile()) {
      ruleFileStream << "# Directory level rules for the build root directory";
    } else {
      ruleFileStream << "# Directory level rules for directory " << dir;
    }
    ruleFileStream << "\n\n";
  }

  // Write directory-level rules for "all".
  this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "all", true, false);

  // Write directory-level rules for "codegen".
  this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "codegen", true,
                            false);

  // Write directory-level rules for "preinstall".
  this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "preinstall", true,
                            true);

  // Write directory-level rules for "clean".
  {
    std::vector<std::string> cmds;
    lg->AppendDirectoryCleanCommand(cmds);
    this->WriteDirectoryRule2(ruleFileStream, rootLG, dt, "clean", false,
                              false, cmds);
  }
}

namespace {
std::string ConvertToMakefilePathForUnix(std::string const& path)
{
  std::string result;
  result.reserve(path.size());
  for (char c : path) {
    switch (c) {
      case '=':
        // We provide 'EQUALS = =' to encode '=' in a non-assignment case.
        result.append("$(EQUALS)");
        break;
      case '$':
        result.append("$$");
        break;
      case '\\':
      case ' ':
      case '#':
        result.push_back('\\');
        CM_FALLTHROUGH;
      default:
        result.push_back(c);
        break;
    }
  }
  return result;
}

#if defined(_WIN32) && !defined(__CYGWIN__)
std::string ConvertToMakefilePathForWindows(std::string const& path)
{
  bool const quote = path.find_first_of(" #") != std::string::npos;
  std::string result;
  result.reserve(path.size() + (quote ? 2 : 0));
  if (quote) {
    result.push_back('"');
  }
  for (char c : path) {
    switch (c) {
      case '=':
        // We provide 'EQUALS = =' to encode '=' in a non-assignment case.
        result.append("$(EQUALS)");
        break;
      case '$':
        result.append("$$");
        break;
      case '/':
        result.push_back('\\');
        break;
      default:
        result.push_back(c);
        break;
    }
  }
  if (quote) {
    result.push_back('"');
  }
  return result;
}
#endif
}

std::string cmGlobalUnixMakefileGenerator3::ConvertToMakefilePath(
  std::string const& path) const
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  if (!this->ForceUnixPaths) {
    return ConvertToMakefilePathForWindows(path);
  }
#endif
  return ConvertToMakefilePathForUnix(path);
}

std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
  std::string const& makeProgram, std::string const& /*projectName*/,
  std::string const& /*projectDir*/,
  std::vector<std::string> const& targetNames, std::string const& /*config*/,
  int jobs, bool verbose, cmBuildOptions const& buildOptions,
  std::vector<std::string> const& makeOptions)
{
  GeneratedMakeCommand makeCommand;

  // Make it possible to set verbosity also from command line
  if (verbose) {
    makeCommand.Add(cmSystemTools::GetCMakeCommand());
    makeCommand.Add("-E");
    makeCommand.Add("env");
    makeCommand.Add("VERBOSE=1");
  }
  makeCommand.Add(this->SelectMakeProgram(makeProgram));

  // Explicitly tell the make tool to use the Makefile written by
  // cmLocalUnixMakefileGenerator3::WriteLocalMakefile
  makeCommand.Add("-f");
  makeCommand.Add("Makefile");

  if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
    if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
      makeCommand.Add("-j");
    } else {
      makeCommand.Add(cmStrCat("-j", jobs));
    }
  }

  makeCommand.Add(makeOptions.begin(), makeOptions.end());
  for (auto tname : targetNames) {
    if (!tname.empty()) {
      if (buildOptions.Fast) {
        tname += "/fast";
      }
      cmSystemTools::ConvertToOutputSlashes(tname);
      makeCommand.Add(std::move(tname));
    }
  }
  return { std::move(makeCommand) };
}

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

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

  // write the target convenience rules
  for (auto const& localGen : this->LocalGenerators) {
    auto& lg =
      cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen);
    // for each target Generate the rule files for each target.
    for (auto const& gtarget : lg.GetGeneratorTargets()) {
      // Don't emit the same rule twice (e.g. two targets with the same
      // simple name)
      std::string name = gtarget->GetName();
      if (!name.empty() && emitted.insert(name).second &&
          // Handle user targets here.  Global targets are handled in
          // the local generator on a per-directory basis.
          (gtarget->IsInBuildSystem() &&
           gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) {
        // Add a rule to build the target by name.
        lg.WriteDivider(ruleFileStream);
        ruleFileStream << "# Target rules for targets named " << name
                       << "\n\n";

        // Write the rule.
        commands.clear();
        std::string tmp = "CMakeFiles/Makefile2";
        commands.push_back(lg.GetRecursiveMakeCall(tmp, name));
        depends.clear();
        if (regenerate) {
          depends.emplace_back("cmake_check_build_system");
        }
        lg.WriteMakeRule(ruleFileStream, "Build rule for target.", name,
                         depends, commands, true);

        // Add a fast rule to build the target
        std::string localName = lg.GetRelativeTargetDirectory(gtarget.get());
        std::string makefileName;
        makefileName = cmStrCat(localName, "/build.make");
        depends.clear();
        commands.clear();
        std::string makeTargetName = cmStrCat(localName, "/build");
        localName = cmStrCat(name, "/fast");
        commands.push_back(
          lg.GetRecursiveMakeCall(makefileName, makeTargetName));
        lg.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 (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) {
          makeTargetName = cmStrCat(
            lg.GetRelativeTargetDirectory(gtarget.get()), "/preinstall");
          localName = cmStrCat(name, "/preinstall");
          depends.clear();
          commands.clear();
          commands.push_back(
            lg.GetRecursiveMakeCall(makefileName, makeTargetName));
          lg.WriteMakeRule(ruleFileStream,
                           "Manual pre-install relink rule for target.",
                           localName, depends, commands, true);
        }
      }
    }
  }
}

void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& rootLG,
  cmLocalUnixMakefileGenerator3& lg)
{
  std::vector<std::string> depends;
  std::vector<std::string> commands;
  std::string localName;
  std::string makeTargetName;

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

  // for each target Generate the rule files for each target.
  for (auto const& gtarget : lg.GetGeneratorTargets()) {
    std::string name = gtarget->GetName();
    if (!name.empty() &&
        (gtarget->IsInBuildSystem() &&
         gtarget->GetType() != cmStateEnums::GLOBAL_TARGET)) {
      std::string makefileName;
      // Add a rule to build the target by name.
      localName = lg.GetRelativeTargetDirectory(gtarget.get());
      makefileName = cmStrCat(localName, "/build.make");

      lg.WriteDivider(ruleFileStream);
      ruleFileStream << "# Target rules for target " << localName << "\n\n";

      commands.clear();
      makeTargetName = cmStrCat(localName, "/depend");
      commands.push_back(
        lg.GetRecursiveMakeCall(makefileName, makeTargetName));

      makeTargetName = cmStrCat(localName, "/build");
      commands.push_back(
        lg.GetRecursiveMakeCall(makefileName, makeTargetName));

      // Write the rule.
      localName += "/all";
      depends.clear();

      cmLocalUnixMakefileGenerator3::EchoProgress progress;
      progress.Dir = cmStrCat(lg.GetBinaryDirectory(), "/CMakeFiles");
      {
        progress.Arg = cmJoin(this->ProgressMap[gtarget.get()].Marks, ",");
      }

      bool targetMessages = true;
      if (cmValue tgtMsg =
            this->GetCMakeInstance()->GetState()->GetGlobalProperty(
              "TARGET_MESSAGES")) {
        targetMessages = tgtMsg.IsOn();
      }

      if (targetMessages) {
        lg.AppendEcho(commands, "Built target " + name,
                      cmLocalUnixMakefileGenerator3::EchoNormal, &progress);
      }

      this->AppendGlobalTargetDepends(depends, gtarget.get());
      rootLG.WriteMakeRule(ruleFileStream, "All Build rule for target.",
                           localName, depends, commands, true);

      // Write the rule.
      commands.clear();

      {
        // TODO: Convert the total progress count to a make variable.
        std::ostringstream progCmd;
        progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
        // # in target
        progCmd << lg.ConvertToOutputFormat(progress.Dir,
                                            cmOutputConverter::SHELL);
        //
        std::set<cmGeneratorTarget const*> emitted;
        progCmd << " "
                << this->CountProgressMarksInTarget(gtarget.get(), emitted);
        commands.push_back(progCmd.str());
      }
      std::string tmp = "CMakeFiles/Makefile2";
      commands.push_back(lg.GetRecursiveMakeCall(tmp, localName));
      {
        std::ostringstream progCmd;
        progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
        progCmd << lg.ConvertToOutputFormat(progress.Dir,
                                            cmOutputConverter::SHELL);
        progCmd << " 0";
        commands.push_back(progCmd.str());
      }
      depends.clear();
      if (regenerate) {
        depends.emplace_back("cmake_check_build_system");
      }
      localName =
        cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), "/rule");
      rootLG.WriteMakeRule(ruleFileStream,
                           "Build rule for subdir invocation for target.",
                           localName, depends, commands, true);

      // Add a target with the canonical name (no prefix, suffix or path).
      commands.clear();
      depends.clear();
      depends.push_back(localName);
      rootLG.WriteMakeRule(ruleFileStream, "Convenience name for target.",
                           name, depends, commands, true);

      // Add rules to prepare the target for installation.
      if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) {
        localName = cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()),
                             "/preinstall");
        depends.clear();
        commands.clear();
        commands.push_back(lg.GetRecursiveMakeCall(makefileName, localName));
        rootLG.WriteMakeRule(ruleFileStream,
                             "Pre-install relink rule for target.", localName,
                             depends, commands, true);
      }

      // add the codegen rule
      localName = lg.GetRelativeTargetDirectory(gtarget.get());
      depends.clear();
      commands.clear();
      makeTargetName = cmStrCat(localName, "/codegen");
      commands.push_back(
        lg.GetRecursiveMakeCall(makefileName, makeTargetName));
      if (targetMessages) {
        lg.AppendEcho(commands, "Finished codegen for target " + name,
                      cmLocalUnixMakefileGenerator3::EchoNormal, &progress);
      }
      this->AppendCodegenTargetDepends(depends, gtarget.get());
      rootLG.WriteMakeRule(ruleFileStream, "codegen rule for target.",
                           makeTargetName, depends, commands, true);

      // add the clean rule
      localName = lg.GetRelativeTargetDirectory(gtarget.get());
      makeTargetName = cmStrCat(localName, "/clean");
      depends.clear();
      commands.clear();
      commands.push_back(
        lg.GetRecursiveMakeCall(makefileName, makeTargetName));
      rootLG.WriteMakeRule(ruleFileStream, "clean rule for target.",
                           makeTargetName, depends, commands, true);
      commands.clear();
    }
  }
}

// Build a map that contains the set of targets used by each local
// generator directory level.
void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
{
  this->DirectoryTargetsMap.clear();
  // Loop over all targets in all local generators.
  for (auto const& lg : this->LocalGenerators) {
    for (auto const& gt : lg->GetGeneratorTargets()) {
      if (!gt->IsInBuildSystem() || this->IsExcluded(lg.get(), gt.get())) {
        continue;
      }

      cmStateSnapshot csnp = lg->GetStateSnapshot();

      // Consider the directory containing the target and all its parents.
      // An excluded directory may contains non-excluded targets.
      for (; csnp.IsValid(); csnp = csnp.GetBuildsystemDirectoryParent()) {
        // This local generator includes the target.
        std::set<cmGeneratorTarget const*>& targetSet =
          this->DirectoryTargetsMap[csnp];
        targetSet.insert(gt.get());

        // Add dependencies of the included target.  An excluded
        // target may still be included if it is a dependency of a
        // non-excluded target.
        for (cmTargetDepend const& tgtdep :
             this->GetTargetDirectDepends(gt.get())) {
          targetSet.insert(tgtdep);
        }
      }
    }
  }
}

size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget(
  cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& emitted)
{
  size_t count = 0;
  if (emitted.insert(target).second) {
    count = this->ProgressMap[target].Marks.size();
    for (cmTargetDepend const& depend : this->GetTargetDirectDepends(target)) {
      if (!depend->IsInBuildSystem()) {
        continue;
      }
      count += this->CountProgressMarksInTarget(depend, emitted);
    }
  }
  return count;
}

size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll(
  cmLocalGenerator const& lg)
{
  size_t count = 0;
  std::set<cmGeneratorTarget const*> emitted;
  for (cmGeneratorTarget const* target :
       this->DirectoryTargetsMap[lg.GetStateSnapshot()]) {
    if (!this->IsExcluded(&lg, target)) {
      count += this->CountProgressMarksInTarget(target, emitted);
    }
  }
  return count;
}

void cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
  cmMakefileTargetGenerator* tg)
{
  TargetProgress& tp = this->ProgressMap[tg->GetGeneratorTarget()];
  tp.NumberOfActions = tg->GetNumberOfProgressActions();
  tp.VariableFile = tg->GetProgressFileNameFull();
}

void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables(
  unsigned long total, unsigned long& current)
{
  cmGeneratedFileStream fout(this->VariableFile);
  for (unsigned long i = 1; i <= this->NumberOfActions; ++i) {
    fout << "CMAKE_PROGRESS_" << i << " = ";
    if (total <= 100) {
      unsigned long num = i + current;
      fout << num;
      this->Marks.push_back(num);
    } else if (((i + current) * 100) / total >
               ((i - 1 + current) * 100) / total) {
      unsigned long num = ((i + current) * 100) / total;
      fout << num;
      this->Marks.push_back(num);
    }
    fout << "\n";
  }
  fout << "\n";
  current += this->NumberOfActions;
}

void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends(
  std::vector<std::string>& depends, cmGeneratorTarget* target)
{
  for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) {
    // Create the target-level dependency.
    cmGeneratorTarget const* dep = i;
    if (!dep->IsInBuildSystem()) {
      continue;
    }
    cmLocalUnixMakefileGenerator3* lg3 =
      static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
    std::string tgtName = cmStrCat(
      lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
      "/all");
    depends.push_back(tgtName);
  }
}

void cmGlobalUnixMakefileGenerator3::AppendCodegenTargetDepends(
  std::vector<std::string>& depends, cmGeneratorTarget* target)
{
  std::set<std::string> const& codegen_depends =
    target->Target->GetCodegenDeps();

  for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) {
    // Create the target-level dependency.
    cmGeneratorTarget const* dep = i;
    if (!dep->IsInBuildSystem()) {
      continue;
    }
    if (codegen_depends.find(dep->GetName()) != codegen_depends.end()) {
      cmLocalUnixMakefileGenerator3* lg3 =
        static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
      std::string tgtName = cmStrCat(
        lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
        "/all");
      depends.push_back(tgtName);
    }
  }
}

void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
  std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
{
  // add the help target
  std::string path;
  std::vector<std::string> no_depends;
  std::vector<std::string> commands;
  lg->AppendEcho(commands,
                 "The following are some of the valid targets "
                 "for this Makefile:");
  lg->AppendEcho(commands, "... all (the default if no target is provided)");
  lg->AppendEcho(commands, "... clean");
  if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
    lg->AppendEcho(commands, "... depend");
  }
  if (this->CheckCMP0171()) {
    lg->AppendEcho(commands, "... codegen");
  }

  // Keep track of targets already listed.
  std::set<std::string> emittedTargets;
  std::set<std::string> utility_targets;
  std::set<std::string> globals_targets;
  std::set<std::string> project_targets;

  // for each local generator
  for (auto const& localGen : this->LocalGenerators) {
    auto const& lg2 =
      cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen);
    // for the passed in makefile or if this is the top Makefile wripte out
    // the targets
    if (&lg2 == lg || lg->IsRootMakefile()) {
      // for each target Generate the rule files for each target.
      for (auto const& target : lg2.GetGeneratorTargets()) {
        cmStateEnums::TargetType type = target->GetType();
        if ((type == cmStateEnums::EXECUTABLE) ||
            (type == cmStateEnums::STATIC_LIBRARY) ||
            (type == cmStateEnums::SHARED_LIBRARY) ||
            (type == cmStateEnums::MODULE_LIBRARY) ||
            (type == cmStateEnums::OBJECT_LIBRARY) ||
            (type == cmStateEnums::INTERFACE_LIBRARY &&
             target->IsInBuildSystem())) {
          project_targets.insert(target->GetName());
        } else if (type == cmStateEnums::GLOBAL_TARGET) {
          globals_targets.insert(target->GetName());
        } else if (type == cmStateEnums::UTILITY) {
          utility_targets.insert(target->GetName());
        }
      }
    }
  }

  for (std::string const& name : globals_targets) {
    path = cmStrCat("... ", name);
    lg->AppendEcho(commands, path);
  }
  for (std::string const& name : utility_targets) {
    path = cmStrCat("... ", name);
    lg->AppendEcho(commands, path);
  }
  for (std::string const& name : project_targets) {
    path = cmStrCat("... ", name);
    lg->AppendEcho(commands, path);
  }

  for (std::string const& o : lg->GetLocalHelp()) {
    path = cmStrCat("... ", o);
    lg->AppendEcho(commands, path);
  }
  lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends,
                    commands, true);
  ruleFileStream << "\n\n";
}
