/* 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." };
}

bool cmGlobalUnixMakefileGenerator3::SupportsShortObjectNames() const
{
  return true;
}

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 buildOptions,
  std::vector<std::string> const& makeOptions,
  BuildTryCompile /*isInTryCompile*/)
{
  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";
}
