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

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <iterator>
#include <sstream>

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

#include "cmsys/FStream.hxx"

#include "cm_jsoncpp_reader.h"
#include "cm_jsoncpp_value.h"
#include "cm_jsoncpp_writer.h"

#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmVersion.h"
#include "cmake.h"

const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
const char* cmGlobalNinjaGenerator::INDENT = "  ";
#ifdef _WIN32
std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd .";
#else
std::string const cmGlobalNinjaGenerator::SHELL_NOOP = ":";
#endif

void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
{
  for (int i = 0; i < count; ++i) {
    os << cmGlobalNinjaGenerator::INDENT;
  }
}

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

void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
                                          const std::string& comment)
{
  if (comment.empty()) {
    return;
  }

  std::string::size_type lpos = 0;
  std::string::size_type rpos;
  os << "\n#############################################\n";
  while ((rpos = comment.find('\n', lpos)) != std::string::npos) {
    os << "# " << comment.substr(lpos, rpos - lpos) << "\n";
    lpos = rpos + 1;
  }
  os << "# " << comment.substr(lpos) << "\n\n";
}

std::unique_ptr<cmLinkLineComputer>
cmGlobalNinjaGenerator::CreateLinkLineComputer(
  cmOutputConverter* outputConverter,
  cmStateDirectory const& /* stateDir */) const
{
  return std::unique_ptr<cmLinkLineComputer>(
    cm::make_unique<cmNinjaLinkLineComputer>(
      outputConverter,
      this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this));
}

std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
{
  // Ninja rule names must match "[a-zA-Z0-9_.-]+".  Use ".xx" to encode
  // "." and all invalid characters as hexadecimal.
  std::string encoded;
  for (char i : name) {
    if (isalnum(i) || i == '_' || i == '-') {
      encoded += i;
    } else {
      char buf[16];
      sprintf(buf, ".%02x", static_cast<unsigned int>(i));
      encoded += buf;
    }
  }
  return encoded;
}

std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
  std::string result = lit;
  cmSystemTools::ReplaceString(result, "$", "$$");
  cmSystemTools::ReplaceString(result, "\n", "$\n");
  if (this->IsMultiConfig()) {
    cmSystemTools::ReplaceString(result,
                                 cmStrCat('$', this->GetCMakeCFGIntDir()),
                                 this->GetCMakeCFGIntDir());
  }
  return result;
}

std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
{
  std::string result = path;
#ifdef _WIN32
  if (this->IsGCCOnWindows())
    std::replace(result.begin(), result.end(), '\\', '/');
  else
    std::replace(result.begin(), result.end(), '/', '\\');
#endif
  result = EncodeLiteral(result);
  cmSystemTools::ReplaceString(result, " ", "$ ");
  cmSystemTools::ReplaceString(result, ":", "$:");
  return result;
}

void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
                                        cmNinjaBuild const& build,
                                        int cmdLineLimit,
                                        bool* usedResponseFile)
{
  // Make sure there is a rule.
  if (build.Rule.empty()) {
    cmSystemTools::Error("No rule for WriteBuild! called with comment: " +
                         build.Comment);
    return;
  }

  // Make sure there is at least one output file.
  if (build.Outputs.empty()) {
    cmSystemTools::Error(
      "No output files for WriteBuild! called with comment: " + build.Comment);
    return;
  }

  cmGlobalNinjaGenerator::WriteComment(os, build.Comment);

  // Write output files.
  std::string buildStr("build");
  {
    // Write explicit outputs
    for (std::string const& output : build.Outputs) {
      buildStr += " " + EncodePath(output);
      if (this->ComputingUnknownDependencies) {
        this->CombinedBuildOutputs.insert(output);
      }
    }
    // Write implicit outputs
    if (!build.ImplicitOuts.empty()) {
      buildStr += " |";
      for (std::string const& implicitOut : build.ImplicitOuts) {
        buildStr += " " + EncodePath(implicitOut);
      }
    }
    buildStr += ":";

    // Write the rule.
    buildStr += " ";
    buildStr += build.Rule;
  }

  std::string arguments;
  {
    // TODO: Better formatting for when there are multiple input/output files.

    // Write explicit dependencies.
    for (std::string const& explicitDep : build.ExplicitDeps) {
      arguments += " " + EncodePath(explicitDep);
    }

    // Write implicit dependencies.
    if (!build.ImplicitDeps.empty()) {
      arguments += " |";
      for (std::string const& implicitDep : build.ImplicitDeps) {
        arguments += " " + EncodePath(implicitDep);
      }
    }

    // Write order-only dependencies.
    if (!build.OrderOnlyDeps.empty()) {
      arguments += " ||";
      for (std::string const& orderOnlyDep : build.OrderOnlyDeps) {
        arguments += " " + EncodePath(orderOnlyDep);
      }
    }

    arguments += "\n";
  }

  // Write the variables bound to this build statement.
  std::string assignments;
  {
    std::ostringstream variable_assignments;
    for (auto const& variable : build.Variables) {
      cmGlobalNinjaGenerator::WriteVariable(
        variable_assignments, variable.first, variable.second, "", 1);
    }

    // check if a response file rule should be used
    assignments = variable_assignments.str();
    bool useResponseFile = false;
    if (cmdLineLimit < 0 ||
        (cmdLineLimit > 0 &&
         (arguments.size() + buildStr.size() + assignments.size() + 1000) >
           static_cast<size_t>(cmdLineLimit))) {
      variable_assignments.str(std::string());
      cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE",
                                            build.RspFile, "", 1);
      assignments += variable_assignments.str();
      useResponseFile = true;
    }
    if (usedResponseFile) {
      *usedResponseFile = useResponseFile;
    }
  }

  os << buildStr << arguments << assignments << "\n";
}

void cmGlobalNinjaGenerator::AddCustomCommandRule()
{
  cmNinjaRule rule("CUSTOM_COMMAND");
  rule.Command = "$COMMAND";
  rule.Description = "$DESC";
  rule.Comment = "Rule for running custom commands.";
  this->AddRule(rule);
}

void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
  const std::string& command, const std::string& description,
  const std::string& comment, const std::string& depfile,
  const std::string& job_pool, bool uses_terminal, bool restat,
  const cmNinjaDeps& outputs, const std::string& config,
  const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps)
{
  this->AddCustomCommandRule();

  {
    cmNinjaBuild build("CUSTOM_COMMAND");
    build.Comment = comment;
    build.Outputs = outputs;
    build.ExplicitDeps = explicitDeps;
    build.OrderOnlyDeps = orderOnlyDeps;

    cmNinjaVars& vars = build.Variables;
    {
      std::string cmd = command; // NOLINT(*)
#ifdef _WIN32
      if (cmd.empty())
        // TODO Shouldn't an empty command be handled by ninja?
        cmd = "cmd.exe /c";
#endif
      vars["COMMAND"] = std::move(cmd);
    }
    vars["DESC"] = EncodeLiteral(description);
    if (restat) {
      vars["restat"] = "1";
    }
    if (uses_terminal && SupportsConsolePool()) {
      vars["pool"] = "console";
    } else if (!job_pool.empty()) {
      vars["pool"] = job_pool;
    }
    if (!depfile.empty()) {
      vars["depfile"] = depfile;
    }
    if (config.empty()) {
      this->WriteBuild(*this->GetCommonFileStream(), build);
    } else {
      this->WriteBuild(*this->GetImplFileStream(config), build);
    }
  }

  if (this->ComputingUnknownDependencies) {
    // we need to track every dependency that comes in, since we are trying
    // to find dependencies that are side effects of build commands
    for (std::string const& dep : explicitDeps) {
      this->CombinedCustomCommandExplicitDependencies.insert(dep);
    }
  }
}

void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
  cmNinjaRule rule("COPY_OSX_CONTENT");
  rule.Command = CMakeCmd() + " -E copy $in $out";
  rule.Description = "Copying OS X Content $out";
  rule.Comment = "Rule for copying OS X bundle content file.";
  this->AddRule(rule);
}

void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(std::string input,
                                                     std::string output,
                                                     const std::string& config)
{
  this->AddMacOSXContentRule();
  {
    cmNinjaBuild build("COPY_OSX_CONTENT");
    build.Outputs.push_back(std::move(output));
    build.ExplicitDeps.push_back(std::move(input));
    this->WriteBuild(*this->GetImplFileStream(config), build);
  }
}

void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
                                       cmNinjaRule const& rule)
{
  // -- Parameter checks
  // Make sure the rule has a name.
  if (rule.Name.empty()) {
    cmSystemTools::Error("No name given for WriteRule! called with comment: " +
                         rule.Comment);
    return;
  }

  // Make sure a command is given.
  if (rule.Command.empty()) {
    cmSystemTools::Error(
      "No command given for WriteRule! called with comment: " + rule.Comment);
    return;
  }

  // Make sure response file content is given
  if (!rule.RspFile.empty() && rule.RspContent.empty()) {
    cmSystemTools::Error("rspfile but no rspfile_content given for WriteRule! "
                         "called with comment: " +
                         rule.Comment);
    return;
  }

  // -- Write rule
  // Write rule intro
  cmGlobalNinjaGenerator::WriteComment(os, rule.Comment);
  os << "rule " << rule.Name << '\n';

  // Write rule key/value pairs
  auto writeKV = [&os](const char* key, std::string const& value) {
    if (!value.empty()) {
      cmGlobalNinjaGenerator::Indent(os, 1);
      os << key << " = " << value << '\n';
    }
  };

  writeKV("depfile", rule.DepFile);
  writeKV("deps", rule.DepType);
  writeKV("command", rule.Command);
  writeKV("description", rule.Description);
  if (!rule.RspFile.empty()) {
    writeKV("rspfile", rule.RspFile);
    writeKV("rspfile_content", rule.RspContent);
  }
  writeKV("restat", rule.Restat);
  if (rule.Generator) {
    writeKV("generator", "1");
  }

  // Finish rule
  os << '\n';
}

void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
                                           const std::string& name,
                                           const std::string& value,
                                           const std::string& comment,
                                           int indent)
{
  // Make sure we have a name.
  if (name.empty()) {
    cmSystemTools::Error("No name given for WriteVariable! called "
                         "with comment: " +
                         comment);
    return;
  }

  // Do not add a variable if the value is empty.
  std::string val = cmTrimWhitespace(value);
  if (val.empty()) {
    return;
  }

  cmGlobalNinjaGenerator::WriteComment(os, comment);
  cmGlobalNinjaGenerator::Indent(os, indent);
  os << name << " = " << val << "\n";
}

void cmGlobalNinjaGenerator::WriteInclude(std::ostream& os,
                                          const std::string& filename,
                                          const std::string& comment)
{
  cmGlobalNinjaGenerator::WriteComment(os, comment);
  os << "include " << filename << "\n";
}

void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os,
                                          const cmNinjaDeps& targets,
                                          const std::string& comment)
{
  cmGlobalNinjaGenerator::WriteComment(os, comment);
  os << "default";
  for (std::string const& target : targets) {
    os << " " << target;
  }
  os << "\n";
}

cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm)
  : cmGlobalCommonGenerator(cm)
{
#ifdef _WIN32
  cm->GetState()->SetWindowsShell(true);
#endif
  // // Ninja is not ported to non-Unix OS yet.
  // this->ForceUnixPaths = true;
  this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
}

// Virtual public methods.

std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator(
  cmMakefile* mf)
{
  return std::unique_ptr<cmLocalGenerator>(
    cm::make_unique<cmLocalNinjaGenerator>(this, mf));
}

codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
{
#ifdef _WIN32
  // Ninja on Windows does not support non-ANSI characters.
  // https://github.com/ninja-build/ninja/issues/1195
  return codecvt::ANSI;
#else
  // No encoding conversion needed on other platforms.
  return codecvt::None;
#endif
}

void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
{
  entry.Name = cmGlobalNinjaGenerator::GetActualName();
  entry.Brief = "Generates build.ninja files.";
}

// Implemented in all cmGlobaleGenerator sub-classes.
// Used in:
//   Source/cmLocalGenerator.cxx
//   Source/cmake.cxx
void cmGlobalNinjaGenerator::Generate()
{
  // Check minimum Ninja version.
  if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
                                    this->NinjaVersion.c_str(),
                                    RequiredNinjaVersion().c_str())) {
    std::ostringstream msg;
    msg << "The detected version of Ninja (" << this->NinjaVersion;
    msg << ") is less than the version of Ninja required by CMake (";
    msg << cmGlobalNinjaGenerator::RequiredNinjaVersion() << ").";
    this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
                                           msg.str());
    return;
  }
  if (!this->OpenBuildFileStreams()) {
    return;
  }
  if (!this->OpenRulesFileStream()) {
    return;
  }

  for (auto& it : this->Configs) {
    it.second.TargetDependsClosures.clear();
  }

  this->InitOutputPathPrefix();
  this->TargetAll = this->NinjaOutputPath("all");
  this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");

  this->PolicyCMP0058 =
    this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
      cmPolicies::CMP0058);
  this->ComputingUnknownDependencies =
    (this->PolicyCMP0058 == cmPolicies::OLD ||
     this->PolicyCMP0058 == cmPolicies::WARN);

  this->cmGlobalGenerator::Generate();

  this->WriteAssumedSourceDependencies();
  this->WriteTargetAliases(*this->GetCommonFileStream());
  this->WriteFolderTargets(*this->GetCommonFileStream());
  this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream());
  this->WriteBuiltinTargets(*this->GetCommonFileStream());

  if (cmSystemTools::GetErrorOccuredFlag()) {
    this->RulesFileStream->setstate(std::ios::failbit);
    for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
      this->GetImplFileStream(config)->setstate(std::ios::failbit);
      this->GetConfigFileStream(config)->setstate(std::ios::failbit);
    }
    this->GetCommonFileStream()->setstate(std::ios::failbit);
  }

  this->CloseCompileCommandsStream();
  this->CloseRulesFileStream();
  this->CloseBuildFileStreams();

  auto run_ninja_tool = [this](std::vector<char const*> const& args) {
    std::vector<std::string> command;
    command.push_back(this->NinjaCommand);
    command.emplace_back("-t");
    for (auto const& arg : args) {
      command.emplace_back(arg);
    }
    std::string error;
    if (!cmSystemTools::RunSingleCommand(command, nullptr, &error, nullptr,
                                         nullptr,
                                         cmSystemTools::OUTPUT_NONE)) {
      this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
                                             "Running\n '" +
                                               cmJoin(command, "' '") +
                                               "'\n"
                                               "failed with:\n " +
                                               error);
      cmSystemTools::SetFatalErrorOccured();
    }
  };

  // The `cleandead` tool needs to know about all outputs in the build we just
  // wrote out. Ninja-Multi doesn't have a single `build.ninja` we can use that
  // is the union of all generated configurations, so we can't run it reliably
  // in that case.
  if (this->NinjaSupportsCleanDeadTool && !this->IsMultiConfig()) {
    run_ninja_tool({ "cleandead" });
  }
  // The `recompact` tool loads the manifest. As above, we don't have a single
  // `build.ninja` to load for this in Ninja-Multi. This may be relaxed in the
  // future pending further investigation into how Ninja works upstream
  // (ninja#1721).
  if (this->NinjaSupportsUnconditionalRecompactTool &&
      !this->IsMultiConfig()) {
    run_ninja_tool({ "recompact" });
  }
  if (this->NinjaSupportsRestatTool) {
    // XXX(ninja): We only list `build.ninja` entry files here because CMake
    // *always* rewrites these files on a reconfigure. If CMake ever gets
    // smarter about this, all CMake-time created/edited files listed as
    // outputs for the reconfigure build statement will need to be listed here.
    cmNinjaDeps outputs;
    this->AddRebuildManifestOutputs(outputs);
    std::vector<const char*> args;
    args.reserve(outputs.size() + 1);
    args.push_back("restat");
    for (auto const& output : outputs) {
      args.push_back(output.c_str());
    }
    run_ninja_tool(args);
  }
}

bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
{
  if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
    return false;
  }
  if (const char* ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
    this->NinjaCommand = ninjaCommand;
    std::vector<std::string> command;
    command.push_back(this->NinjaCommand);
    command.emplace_back("--version");
    std::string version;
    std::string error;
    if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr,
                                         nullptr,
                                         cmSystemTools::OUTPUT_NONE)) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       "Running\n '" + cmJoin(command, "' '") +
                         "'\n"
                         "failed with:\n " +
                         error);
      cmSystemTools::SetFatalErrorOccured();
      return false;
    }
    this->NinjaVersion = cmTrimWhitespace(version);
    this->CheckNinjaFeatures();
  }
  return true;
}

void cmGlobalNinjaGenerator::CheckNinjaFeatures()
{
  this->NinjaSupportsConsolePool = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForConsolePool().c_str());
  this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts().c_str());
  this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForManifestRestat().c_str());
  this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForMultilineDepfile().c_str());
  this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForDyndeps().c_str());
  if (!this->NinjaSupportsDyndeps) {
    // The ninja version number is not new enough to have upstream support.
    // Our ninja branch adds ".dyndep-#" to its version number,
    // where '#' is a feature-specific version number.  Extract it.
    static std::string const k_DYNDEP_ = ".dyndep-";
    std::string::size_type pos = this->NinjaVersion.find(k_DYNDEP_);
    if (pos != std::string::npos) {
      const char* fv = &this->NinjaVersion[pos + k_DYNDEP_.size()];
      unsigned long dyndep = 0;
      cmStrToULong(fv, &dyndep);
      if (dyndep == 1) {
        this->NinjaSupportsDyndeps = true;
      }
    }
  }
  this->NinjaSupportsCleanDeadTool = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForCleanDeadTool().c_str());
  this->NinjaSupportsUnconditionalRecompactTool =
    !cmSystemTools::VersionCompare(
      cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
      RequiredNinjaVersionForUnconditionalRecompactTool().c_str());
  this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
    RequiredNinjaVersionForRestatTool().c_str());
}

bool cmGlobalNinjaGenerator::CheckLanguages(
  std::vector<std::string> const& languages, cmMakefile* mf) const
{
  if (cmContains(languages, "Fortran")) {
    return this->CheckFortran(mf);
  }
  return true;
}

bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
{
  if (this->NinjaSupportsDyndeps) {
    return true;
  }

  std::ostringstream e;
  /* clang-format off */
  e <<
    "The Ninja generator does not support Fortran using Ninja version\n"
    "  " + this->NinjaVersion + "\n"
    "due to lack of required features.  "
    "Kitware has implemented the required features and they have been "
    "merged to upstream ninja for inclusion in Ninja 1.10 and higher.  "
    "As of this version of CMake, Ninja 1.10 has not been released.  "
    "Meanwhile, Kitware maintains a branch of Ninja at:\n"
    "  https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n"
    "with the required features.  "
    "One may build ninja from that branch to get support for Fortran."
    ;
  /* clang-format on */
  mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
  cmSystemTools::SetFatalErrorOccured();
  return false;
}

void cmGlobalNinjaGenerator::EnableLanguage(
  std::vector<std::string> const& langs, cmMakefile* mf, bool optional)
{
  if (this->IsMultiConfig()) {
    if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
      mf->AddCacheDefinition(
        "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
        "Semicolon separated list of supported configuration types, only "
        "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything "
        "else will be ignored",
        cmStateEnums::STRING);
    }
  }

  this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
  for (std::string const& l : langs) {
    if (l == "NONE") {
      continue;
    }
    this->ResolveLanguageCompiler(l, mf, optional);
  }
#ifdef _WIN32
  const bool clangGnuMode =
    ((mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") &&
     (mf->GetSafeDefinition("CMAKE_C_COMPILER_FRONTEND_VARIANT") == "GNU")) ||
    ((mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") &&
     (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_FRONTEND_VARIANT") == "GNU"));

  if (clangGnuMode ||
      ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") &&
       (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") &&
       (mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
        (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") ||
        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") ||
        (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") ||
        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") ||
        (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") ||
        (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) {
    this->UsingGCCOnWindows = true;
  }
#endif
}

// Implemented by:
//   cmGlobalUnixMakefileGenerator3
//   cmGlobalGhsMultiGenerator
//   cmGlobalVisualStudio10Generator
//   cmGlobalVisualStudio7Generator
//   cmGlobalXCodeGenerator
// Called by:
//   cmGlobalGenerator::Build()
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalNinjaGenerator::GenerateBuildCommand(
  const std::string& makeProgram, const std::string& /*projectName*/,
  const std::string& /*projectDir*/,
  std::vector<std::string> const& targetNames, const std::string& config,
  bool /*fast*/, int jobs, bool verbose,
  std::vector<std::string> const& makeOptions)
{
  GeneratedMakeCommand makeCommand;
  makeCommand.Add(this->SelectMakeProgram(makeProgram));

  if (verbose) {
    makeCommand.Add("-v");
  }

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

  this->AppendNinjaFileArgument(makeCommand,
                                config.empty() ? "Debug" : config);

  makeCommand.Add(makeOptions.begin(), makeOptions.end());
  for (const auto& tname : targetNames) {
    if (!tname.empty()) {
      makeCommand.Add(tname);
    }
  }
  return { std::move(makeCommand) };
}

// Non-virtual public methods.

void cmGlobalNinjaGenerator::AddRule(cmNinjaRule const& rule)
{
  // Do not add the same rule twice.
  if (!this->Rules.insert(rule.Name).second) {
    return;
  }
  // Store command length
  this->RuleCmdLength[rule.Name] = static_cast<int>(rule.Command.size());
  // Write rule
  cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, rule);
}

bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
{
  return (this->Rules.find(name) != this->Rules.end());
}

// Private virtual overrides

std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const
{
  // Ninja by design does not run interactive tools in the terminal,
  // so our only choice is cmake-gui.
  return cmSystemTools::GetCMakeGUICommand();
}

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

// Private methods

bool cmGlobalNinjaGenerator::OpenBuildFileStreams()
{
  if (!this->OpenFileStream(this->BuildFileStream,
                            cmGlobalNinjaGenerator::NINJA_BUILD_FILE)) {
    return false;
  }

  // Write a comment about this file.
  *this->BuildFileStream
    << "# This file contains all the build statements describing the\n"
    << "# compilation DAG.\n\n";

  return true;
}

bool cmGlobalNinjaGenerator::OpenFileStream(
  std::unique_ptr<cmGeneratedFileStream>& stream, const std::string& name)
{
  // Get a stream where to generate things.
  if (!stream) {
    // Compute Ninja's build file path.
    std::string path =
      cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', name);
    stream = cm::make_unique<cmGeneratedFileStream>(
      path, false, this->GetMakefileEncoding());
    if (!(*stream)) {
      // An error message is generated by the constructor if it cannot
      // open the file.
      return false;
    }

    // Write the do not edit header.
    this->WriteDisclaimer(*stream);
  }

  return true;
}

void cmGlobalNinjaGenerator::CloseBuildFileStreams()
{
  if (this->BuildFileStream) {
    this->BuildFileStream.reset();
  } else {
    cmSystemTools::Error("Build file stream was not open.");
  }
}

bool cmGlobalNinjaGenerator::OpenRulesFileStream()
{
  if (!this->OpenFileStream(this->RulesFileStream,
                            cmGlobalNinjaGenerator::NINJA_RULES_FILE)) {
    return false;
  }

  // Write comment about this file.
  /* clang-format off */
  *this->RulesFileStream
    << "# This file contains all the rules used to get the outputs files\n"
    << "# built from the input files.\n"
    << "# It is included in the main '" << NINJA_BUILD_FILE << "'.\n\n"
    ;
  /* clang-format on */
  return true;
}

void cmGlobalNinjaGenerator::CloseRulesFileStream()
{
  if (this->RulesFileStream) {
    this->RulesFileStream.reset();
  } else {
    cmSystemTools::Error("Rules file stream was not open.");
  }
}

static void EnsureTrailingSlash(std::string& path)
{
  if (path.empty()) {
    return;
  }
  std::string::value_type last = path.back();
#ifdef _WIN32
  if (last != '\\') {
    path += '\\';
  }
#else
  if (last != '/') {
    path += '/';
  }
#endif
}

std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
  const std::string& path) const
{
  auto const f = ConvertToNinjaPathCache.find(path);
  if (f != ConvertToNinjaPathCache.end()) {
    return f->second;
  }

  const auto& ng =
    cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]);
  std::string const& bin_dir = ng.GetState()->GetBinaryDirectory();
  std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path);
  convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
  std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
  return ConvertToNinjaPathCache.emplace(path, std::move(convPath))
    .first->second;
}

void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName,
                                                    const std::string& config)
{
  this->Configs[config].AdditionalCleanFiles.emplace(std::move(fileName));
}

void cmGlobalNinjaGenerator::AddCXXCompileCommand(
  const std::string& commandLine, const std::string& sourceFile)
{
  // Compute Ninja's build file path.
  std::string buildFileDir =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  if (!this->CompileCommandsStream) {
    std::string buildFilePath = buildFileDir + "/compile_commands.json";
    if (this->ComputingUnknownDependencies) {
      this->CombinedBuildOutputs.insert(
        this->NinjaOutputPath("compile_commands.json"));
    }

    // Get a stream where to generate things.
    this->CompileCommandsStream =
      cm::make_unique<cmGeneratedFileStream>(buildFilePath);
    *this->CompileCommandsStream << "[";
  } else {
    *this->CompileCommandsStream << "," << std::endl;
  }

  std::string sourceFileName = sourceFile;
  if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
    sourceFileName = cmSystemTools::CollapseFullPath(
      sourceFileName, this->GetCMakeInstance()->GetHomeOutputDirectory());
  }

  /* clang-format off */
  *this->CompileCommandsStream << "\n{\n"
     << R"(  "directory": ")"
     << cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
     << R"(  "command": ")"
     << cmGlobalGenerator::EscapeJSON(commandLine) << "\",\n"
     << R"(  "file": ")"
     << cmGlobalGenerator::EscapeJSON(sourceFileName) << "\"\n"
     << "}";
  /* clang-format on */
}

void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
{
  if (this->CompileCommandsStream) {
    *this->CompileCommandsStream << "\n]";
    this->CompileCommandsStream.reset();
  }
}

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

void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
  for (auto const& asd : this->AssumedSourceDependencies) {
    cmNinjaDeps orderOnlyDeps;
    std::copy(asd.second.begin(), asd.second.end(),
              std::back_inserter(orderOnlyDeps));
    WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
                            "Assume dependencies for generated source file.",
                            /*depfile*/ "", /*job_pool*/ "",
                            /*uses_terminal*/ false,
                            /*restat*/ true, cmNinjaDeps(1, asd.first), "",
                            cmNinjaDeps(), orderOnlyDeps);
  }
}

std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget(
  cmGeneratorTarget const* target, const std::string& config)
{
  return "cmake_object_order_depends_target_" + target->GetName() + "_" +
    config;
}

void cmGlobalNinjaGenerator::AppendTargetOutputs(
  cmGeneratorTarget const* target, cmNinjaDeps& outputs,
  const std::string& config, cmNinjaTargetDepends depends)
{
  // for frameworks, we want the real name, not smple name
  // frameworks always appear versioned, and the build.ninja
  // will always attempt to manage symbolic links instead
  // of letting cmOSXBundleGenerator do it.
  bool realname = target->IsFrameworkOnApple();

  switch (target->GetType()) {
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY: {
      if (depends == DependOnTargetOrdering) {
        outputs.push_back(OrderDependsTargetForTarget(target, config));
        break;
      }
    }
    // FALLTHROUGH
    case cmStateEnums::EXECUTABLE: {
      outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
        config, cmStateEnums::RuntimeBinaryArtifact, realname)));
      break;
    }
    case cmStateEnums::OBJECT_LIBRARY: {
      if (depends == DependOnTargetOrdering) {
        outputs.push_back(OrderDependsTargetForTarget(target, config));
        break;
      }
    }
    // FALLTHROUGH
    case cmStateEnums::GLOBAL_TARGET:
    case cmStateEnums::UTILITY: {
      std::string path =
        target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
        std::string("/") + target->GetName();
      std::string output = this->ConvertToNinjaPath(path);
      if (target->Target->IsPerConfig()) {
        output = this->BuildAlias(output, config);
      }
      outputs.push_back(output);
      break;
    }

    default:
      return;
  }
}

void cmGlobalNinjaGenerator::AppendTargetDepends(
  cmGeneratorTarget const* target, cmNinjaDeps& outputs,
  const std::string& config, const std::string& fileConfig,
  cmNinjaTargetDepends depends)
{
  if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
    // These depend only on other CMake-provided targets, e.g. "all".
    for (BT<std::string> const& util : target->GetUtilities()) {
      std::string d =
        target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" +
        util.Value;
      outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config));
    }
  } else {
    cmNinjaDeps outs;
    for (cmTargetDepend const& targetDep :
         this->GetTargetDirectDepends(target)) {
      if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
        continue;
      }
      // For some reason, object libraries show up as "utility" dependencies
      // even though they're used for linking. Treat them as link dependencies.
      if (targetDep.IsUtil() &&
          targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) {
        this->AppendTargetOutputs(targetDep, outs, fileConfig, depends);
      } else {
        this->AppendTargetOutputs(targetDep, outs, config, depends);
      }
    }
    std::sort(outs.begin(), outs.end());
    cm::append(outputs, outs);
  }
}

void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
  cmGeneratorTarget const* target, cmNinjaDeps& outputs,
  const std::string& config)
{
  cmNinjaOuts outs;
  this->AppendTargetDependsClosure(target, outs, config, true);
  cm::append(outputs, outs);
}

void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
  cmGeneratorTarget const* target, cmNinjaOuts& outputs,
  const std::string& config, bool omit_self)
{

  // try to locate the target in the cache
  auto find = this->Configs[config].TargetDependsClosures.lower_bound(target);

  if (find == this->Configs[config].TargetDependsClosures.end() ||
      find->first != target) {
    // We now calculate the closure outputs by inspecting the dependent
    // targets recursively.
    // For that we have to distinguish between a local result set that is only
    // relevant for filling the cache entries properly isolated and a global
    // result set that is relevant for the result of the top level call to
    // AppendTargetDependsClosure.
    cmNinjaOuts this_outs; // this will be the new cache entry

    for (auto const& dep_target : this->GetTargetDirectDepends(target)) {
      if (dep_target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
        continue;
      }

      // Collect the dependent targets for _this_ target
      this->AppendTargetDependsClosure(dep_target, this_outs, config, false);
    }
    find = this->Configs[config].TargetDependsClosures.emplace_hint(
      find, target, std::move(this_outs));
  }

  // now fill the outputs of the final result from the newly generated cache
  // entry
  outputs.insert(find->second.begin(), find->second.end());

  // finally generate the outputs of the target itself, if applicable
  cmNinjaDeps outs;
  if (!omit_self) {
    this->AppendTargetOutputs(target, outs, config);
  }
  outputs.insert(outs.begin(), outs.end());
}

void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
                                            cmGeneratorTarget* target,
                                            const std::string& config)
{
  std::string outputPath = this->NinjaOutputPath(alias);
  std::string buildAlias = this->BuildAlias(outputPath, config);
  cmNinjaDeps outputs;
  this->AppendTargetOutputs(target, outputs, config);
  // Mark the target's outputs as ambiguous to ensure that no other target
  // uses the output as an alias.
  for (std::string const& output : outputs) {
    this->TargetAliases[output].GeneratorTarget = nullptr;
    for (const std::string& config2 :
         this->Makefiles.front()->GetGeneratorConfigs()) {
      this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr;
    }
  }

  // Insert the alias into the map.  If the alias was already present in the
  // map and referred to another target, mark it as ambiguous.
  TargetAlias ta;
  ta.GeneratorTarget = target;
  ta.Config = config;
  std::pair<TargetAliasMap::iterator, bool> newAliasGlobal =
    this->TargetAliases.insert(std::make_pair(buildAlias, ta));
  if (newAliasGlobal.second &&
      newAliasGlobal.first->second.GeneratorTarget != target) {
    newAliasGlobal.first->second.GeneratorTarget = nullptr;
  }
  std::pair<TargetAliasMap::iterator, bool> newAliasConfig =
    this->Configs[config].TargetAliases.insert(std::make_pair(outputPath, ta));
  if (newAliasConfig.second &&
      newAliasConfig.first->second.GeneratorTarget != target) {
    newAliasConfig.first->second.GeneratorTarget = nullptr;
  }
}

void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Target aliases.\n\n";

  cmNinjaBuild build("phony");
  build.Outputs.emplace_back();
  for (auto const& ta : this->TargetAliases) {
    // Don't write ambiguous aliases.
    if (!ta.second.GeneratorTarget) {
      continue;
    }

    // Don't write alias if there is a already a custom command with
    // matching output
    if (this->HasCustomCommandOutput(ta.first)) {
      continue;
    }

    build.Outputs.front() = ta.first;
    build.ExplicitDeps.clear();
    if (ta.second.Config == "all") {
      for (auto const& config :
           ta.second.GeneratorTarget->Makefile->GetGeneratorConfigs()) {
        this->AppendTargetOutputs(ta.second.GeneratorTarget,
                                  build.ExplicitDeps, config);
      }
    } else {
      this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps,
                                ta.second.Config);
    }
    this->WriteBuild(this->EnableCrossConfigBuild()
                       ? os
                       : *this->GetImplFileStream(ta.second.Config),
                     build);
  }

  if (this->IsMultiConfig()) {
    for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) {
      for (auto const& ta : this->Configs[config].TargetAliases) {
        // Don't write ambiguous aliases.
        if (!ta.second.GeneratorTarget) {
          continue;
        }

        // Don't write alias if there is a already a custom command with
        // matching output
        if (this->HasCustomCommandOutput(ta.first)) {
          continue;
        }

        build.Outputs.front() = ta.first;
        build.ExplicitDeps.clear();
        this->AppendTargetOutputs(ta.second.GeneratorTarget,
                                  build.ExplicitDeps, config);
        this->WriteBuild(*this->GetConfigFileStream(config), build);
      }
    }

    auto const* defaultConfig = this->GetDefaultBuildAlias();
    if (defaultConfig) {
      std::string config = defaultConfig;
      for (auto const& ta : this->Configs[config].TargetAliases) {
        // Don't write ambiguous aliases.
        if (!ta.second.GeneratorTarget) {
          continue;
        }

        // Don't write alias if there is a already a custom command with
        // matching output
        if (this->HasCustomCommandOutput(ta.first)) {
          continue;
        }

        build.Outputs.front() = ta.first;
        build.ExplicitDeps.clear();
        if (config == "all") {
          for (auto const& config2 :
               this->Makefiles.front()->GetGeneratorConfigs()) {
            this->AppendTargetOutputs(ta.second.GeneratorTarget,
                                      build.ExplicitDeps, config2);
          }
        } else {
          this->AppendTargetOutputs(ta.second.GeneratorTarget,
                                    build.ExplicitDeps, config);
        }
        this->WriteBuild(*this->GetDefaultFileStream(), build);
      }
    }
  }
}

void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Folder targets.\n\n";

  std::map<std::string, DirectoryTarget> dirTargets =
    this->ComputeDirectoryTargets();

  for (auto const& it : dirTargets) {
    cmNinjaBuild build("phony");
    cmGlobalNinjaGenerator::WriteDivider(os);
    std::string const& currentBinaryDir = it.first;
    DirectoryTarget const& dt = it.second;
    std::vector<std::string> configs;
    dt.LG->GetMakefile()->GetConfigurations(configs, true);
    if (configs.empty()) {
      configs.emplace_back();
    }

    // Setup target
    cmNinjaDeps configDeps;
    build.Comment = "Folder: " + currentBinaryDir;
    build.Outputs.emplace_back();
    for (auto const& config : configs) {
      build.ExplicitDeps.clear();
      build.Outputs.front() = this->BuildAlias(
        this->ConvertToNinjaPath(currentBinaryDir + "/all"), config);
      configDeps.emplace_back(build.Outputs.front());
      for (DirectoryTarget::Target const& t : dt.Targets) {
        if (!t.ExcludeFromAll) {
          this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config);
        }
      }
      for (DirectoryTarget::Dir const& d : dt.Children) {
        if (!d.ExcludeFromAll) {
          build.ExplicitDeps.emplace_back(this->BuildAlias(
            this->ConvertToNinjaPath(d.Path + "/all"), config));
        }
      }
      // Write target
      this->WriteBuild(
        this->EnableCrossConfigBuild() ? os : *this->GetImplFileStream(config),
        build);
    }

    // Add shortcut target
    if (this->IsMultiConfig()) {
      for (auto const& config : configs) {
        build.ExplicitDeps = { this->BuildAlias(
          this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) };
        build.Outputs.front() =
          this->ConvertToNinjaPath(currentBinaryDir + "/all");
        this->WriteBuild(*this->GetConfigFileStream(config), build);
      }

      auto const* defaultConfig = this->GetDefaultBuildAlias();
      if (defaultConfig) {
        std::string config = defaultConfig;
        build.ExplicitDeps = { this->BuildAlias(
          this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) };
        build.Outputs.front() =
          this->ConvertToNinjaPath(currentBinaryDir + "/all");
        this->WriteBuild(*this->GetDefaultFileStream(), build);
      }
    }

    // Add target for all configs
    if (this->EnableCrossConfigBuild()) {
      build.ExplicitDeps.clear();
      for (auto const& config : configs) {
        build.ExplicitDeps.push_back(this->BuildAlias(
          this->ConvertToNinjaPath(currentBinaryDir + "/all"), config));
      }
      build.Outputs.front() = this->BuildAlias(
        this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all");
      this->WriteBuild(os, build);
    }
  }
}

void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
{
  if (!this->ComputingUnknownDependencies) {
    return;
  }

  // We need to collect the set of known build outputs.
  // Start with those generated by WriteBuild calls.
  // No other method needs this so we can take ownership
  // of the set locally and throw it out when we are done.
  std::set<std::string> knownDependencies;
  knownDependencies.swap(this->CombinedBuildOutputs);

  // now write out the unknown explicit dependencies.

  // union the configured files, evaluations files and the
  // CombinedBuildOutputs,
  // and then difference with CombinedExplicitDependencies to find the explicit
  // dependencies that we have no rule for

  cmGlobalNinjaGenerator::WriteDivider(os);
  /* clang-format off */
  os << "# Unknown Build Time Dependencies.\n"
     << "# Tell Ninja that they may appear as side effects of build rules\n"
     << "# otherwise ordered by order-only dependencies.\n\n";
  /* clang-format on */

  // get the list of files that cmake itself has generated as a
  // product of configuration.

  for (const auto& lg : this->LocalGenerators) {
    // get the vector of files created by this makefile and convert them
    // to ninja paths, which are all relative in respect to the build directory
    for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) {
      knownDependencies.insert(this->ConvertToNinjaPath(file));
    }
    if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
      // get list files which are implicit dependencies as well and will be
      // phony for rebuild manifest
      for (std::string const& j : lg->GetMakefile()->GetListFiles()) {
        knownDependencies.insert(this->ConvertToNinjaPath(j));
      }
    }
    for (const auto& li : lg->GetMakefile()->GetEvaluationFiles()) {
      // get all the files created by generator expressions and convert them
      // to ninja paths
      for (std::string const& evaluationFile : li->GetFiles()) {
        knownDependencies.insert(this->ConvertToNinjaPath(evaluationFile));
      }
    }
  }
  knownDependencies.insert(this->CMakeCacheFile);

  for (auto const& ta : this->TargetAliases) {
    knownDependencies.insert(this->ConvertToNinjaPath(ta.first));
  }

  // remove all source files we know will exist.
  for (auto const& i : this->AssumedSourceDependencies) {
    knownDependencies.insert(this->ConvertToNinjaPath(i.first));
  }

  // now we difference with CombinedCustomCommandExplicitDependencies to find
  // the list of items we know nothing about.
  // We have encoded all the paths in CombinedCustomCommandExplicitDependencies
  // and knownDependencies so no matter if unix or windows paths they
  // should all match now.

  std::vector<std::string> unknownExplicitDepends;
  this->CombinedCustomCommandExplicitDependencies.erase(this->TargetAll);

  std::set_difference(this->CombinedCustomCommandExplicitDependencies.begin(),
                      this->CombinedCustomCommandExplicitDependencies.end(),
                      knownDependencies.begin(), knownDependencies.end(),
                      std::back_inserter(unknownExplicitDepends));

  std::vector<std::string> warnExplicitDepends;
  if (!unknownExplicitDepends.empty()) {
    cmake* cmk = this->GetCMakeInstance();
    std::string const& buildRoot = cmk->GetHomeOutputDirectory();
    bool const inSource = (buildRoot == cmk->GetHomeDirectory());
    bool const warn = (!inSource && (this->PolicyCMP0058 == cmPolicies::WARN));
    cmNinjaBuild build("phony");
    build.Outputs.emplace_back("");
    for (std::string const& ued : unknownExplicitDepends) {
      // verify the file is in the build directory
      std::string const absDepPath =
        cmSystemTools::CollapseFullPath(ued, buildRoot);
      if (cmSystemTools::IsSubDirectory(absDepPath, buildRoot)) {
        // Generate phony build statement
        build.Outputs[0] = ued;
        this->WriteBuild(os, build);
        // Add to warning on demand
        if (warn && warnExplicitDepends.size() < 10) {
          warnExplicitDepends.push_back(ued);
        }
      }
    }
  }

  if (!warnExplicitDepends.empty()) {
    std::ostringstream w;
    /* clang-format off */
    w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0058) << "\n"
      "This project specifies custom command DEPENDS on files "
      "in the build tree that are not specified as the OUTPUT or "
      "BYPRODUCTS of any add_custom_command or add_custom_target:\n"
      " " << cmJoin(warnExplicitDepends, "\n ") <<
      "\n"
      "For compatibility with versions of CMake that did not have "
      "the BYPRODUCTS option, CMake is generating phony rules for "
      "such files to convince 'ninja' to build."
      "\n"
      "Project authors should add the missing BYPRODUCTS or OUTPUT "
      "options to the custom commands that produce these files."
      ;
    /* clang-format on */
    this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
                                           w.str());
  }
}

void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
{
  // Write headers.
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Built-in targets\n\n";

  this->WriteTargetRebuildManifest(os);
  this->WriteTargetClean(os);
  this->WriteTargetHelp(os);

  for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
    this->WriteTargetDefault(*this->GetConfigFileStream(config));
  }

  if (this->GetDefaultBuildType()) {
    this->WriteTargetDefault(*this->GetDefaultFileStream());
  }
}

void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os)
{
  if (!this->HasOutputPathPrefix()) {
    cmNinjaDeps all;
    all.push_back(this->TargetAll);
    cmGlobalNinjaGenerator::WriteDefault(os, all,
                                         "Make the all target the default.");
  }
}

void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
  if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
    return;
  }
  const auto& lg = this->LocalGenerators[0];

  {
    cmNinjaRule rule("RERUN_CMAKE");
    rule.Command =
      cmStrCat(CMakeCmd(), " -S",
               lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
                                         cmOutputConverter::SHELL),
               " -B",
               lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
                                         cmOutputConverter::SHELL));
    rule.Description = "Re-running CMake...";
    rule.Comment = "Rule for re-running cmake.";
    rule.Generator = true;
    WriteRule(*this->RulesFileStream, rule);
  }

  cmNinjaBuild reBuild("RERUN_CMAKE");
  reBuild.Comment = "Re-run CMake if any of its inputs changed.";
  this->AddRebuildManifestOutputs(reBuild.Outputs);

  for (const auto& localGen : this->LocalGenerators) {
    for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) {
      reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
    }
  }
  reBuild.ImplicitDeps.push_back(this->CMakeCacheFile);

  // Use 'console' pool to get non buffered output of the CMake re-run call
  // Available since Ninja 1.5
  if (SupportsConsolePool()) {
    reBuild.Variables["pool"] = "console";
  }

  cmake* cm = this->GetCMakeInstance();
  if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) {
    {
      cmNinjaRule rule("VERIFY_GLOBS");
      rule.Command =
        cmStrCat(CMakeCmd(), " -P ",
                 lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
                                           cmOutputConverter::SHELL));
      rule.Description = "Re-checking globbed directories...";
      rule.Comment = "Rule for re-checking globbed directories.";
      rule.Generator = true;
      this->WriteRule(*this->RulesFileStream, rule);
    }

    cmNinjaBuild phonyBuild("phony");
    phonyBuild.Comment = "Phony target to force glob verification run.";
    phonyBuild.Outputs.push_back(cm->GetGlobVerifyScript() + "_force");
    this->WriteBuild(os, phonyBuild);

    reBuild.Variables["restat"] = "1";
    std::string const verifyScriptFile =
      this->NinjaOutputPath(cm->GetGlobVerifyScript());
    std::string const verifyStampFile =
      this->NinjaOutputPath(cm->GetGlobVerifyStamp());
    {
      cmNinjaBuild vgBuild("VERIFY_GLOBS");
      vgBuild.Comment =
        "Re-run CMake to check if globbed directories changed.";
      vgBuild.Outputs.push_back(verifyStampFile);
      vgBuild.ImplicitDeps = phonyBuild.Outputs;
      vgBuild.Variables = reBuild.Variables;
      this->WriteBuild(os, vgBuild);
    }
    reBuild.Variables.erase("restat");
    reBuild.ImplicitDeps.push_back(verifyScriptFile);
    reBuild.ExplicitDeps.push_back(verifyStampFile);
  } else if (!this->SupportsManifestRestat() &&
             cm->DoWriteGlobVerifyTarget()) {
    std::ostringstream msg;
    msg << "The detected version of Ninja:\n"
        << "  " << this->NinjaVersion << "\n"
        << "is less than the version of Ninja required by CMake for adding "
           "restat dependencies to the build.ninja manifest regeneration "
           "target:\n"
        << "  "
        << cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat()
        << "\n";
    msg << "Any pre-check scripts, such as those generated for file(GLOB "
           "CONFIGURE_DEPENDS), will not be run by Ninja.";
    this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
                                           msg.str());
  }

  std::sort(reBuild.ImplicitDeps.begin(), reBuild.ImplicitDeps.end());
  reBuild.ImplicitDeps.erase(
    std::unique(reBuild.ImplicitDeps.begin(), reBuild.ImplicitDeps.end()),
    reBuild.ImplicitDeps.end());

  this->WriteBuild(os, reBuild);

  {
    cmNinjaBuild build("phony");
    build.Comment = "A missing CMake input file is not an error.";
    std::set_difference(std::make_move_iterator(reBuild.ImplicitDeps.begin()),
                        std::make_move_iterator(reBuild.ImplicitDeps.end()),
                        CustomCommandOutputs.begin(),
                        CustomCommandOutputs.end(),
                        std::back_inserter(build.Outputs));
    this->WriteBuild(os, build);
  }
}

std::string cmGlobalNinjaGenerator::CMakeCmd() const
{
  const auto& lgen = this->LocalGenerators.at(0);
  return lgen->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
                                     cmOutputConverter::SHELL);
}

std::string cmGlobalNinjaGenerator::NinjaCmd() const
{
  const auto& lgen = this->LocalGenerators[0];
  if (lgen != nullptr) {
    return lgen->ConvertToOutputFormat(this->NinjaCommand,
                                       cmOutputConverter::SHELL);
  }
  return "ninja";
}

bool cmGlobalNinjaGenerator::SupportsConsolePool() const
{
  return this->NinjaSupportsConsolePool;
}

bool cmGlobalNinjaGenerator::SupportsImplicitOuts() const
{
  return this->NinjaSupportsImplicitOuts;
}

bool cmGlobalNinjaGenerator::SupportsManifestRestat() const
{
  return this->NinjaSupportsManifestRestat;
}

bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const
{
  return this->NinjaSupportsMultilineDepfile;
}

bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
{
  const auto& lgr = this->LocalGenerators.at(0);
  std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
  std::string cleanScriptAbs =
    cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
  std::vector<std::string> configs;
  this->Makefiles[0]->GetConfigurations(configs, true);
  if (configs.empty()) {
    configs.emplace_back();
  }

  // Check if there are additional files to clean
  bool empty = true;
  for (auto const& config : configs) {
    auto const it = this->Configs.find(config);
    if (it != this->Configs.end() &&
        !it->second.AdditionalCleanFiles.empty()) {
      empty = false;
      break;
    }
  }
  if (empty) {
    // Remove cmake clean script file if it exists
    cmSystemTools::RemoveFile(cleanScriptAbs);
    return false;
  }

  // Write cmake clean script file
  {
    cmGeneratedFileStream fout(cleanScriptAbs);
    if (!fout) {
      return false;
    }
    fout << "# Additional clean files\ncmake_minimum_required(VERSION 3.16)\n";
    for (auto const& config : configs) {
      auto const it = this->Configs.find(config);
      if (it != this->Configs.end() &&
          !it->second.AdditionalCleanFiles.empty()) {
        fout << "\nif(\"${CONFIG}\" STREQUAL \"\" OR \"${CONFIG}\" STREQUAL \""
             << config << "\")\n";
        fout << "  file(REMOVE_RECURSE\n";
        for (std::string const& acf : it->second.AdditionalCleanFiles) {
          fout << "  "
               << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf))
               << '\n';
        }
        fout << "  )\n";
        fout << "endif()\n";
      }
    }
  }
  // Register clean script file
  lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs);

  // Write rule
  {
    cmNinjaRule rule("CLEAN_ADDITIONAL");
    rule.Command = cmStrCat(
      CMakeCmd(), " -DCONFIG=$CONFIG -P ",
      lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
                                 cmOutputConverter::SHELL));
    rule.Description = "Cleaning additional files...";
    rule.Comment = "Rule for cleaning additional files.";
    WriteRule(*this->RulesFileStream, rule);
  }

  // Write build
  {
    cmNinjaBuild build("CLEAN_ADDITIONAL");
    build.Comment = "Clean additional files.";
    build.Outputs.emplace_back();
    for (auto const& config : configs) {
      build.Outputs.front() = this->BuildAlias(
        this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config);
      build.Variables["CONFIG"] = config;
      WriteBuild(os, build);
    }
    if (this->IsMultiConfig()) {
      build.Outputs.front() =
        this->NinjaOutputPath(this->GetAdditionalCleanTargetName());
      build.Variables["CONFIG"] = "";
      WriteBuild(os, build);
    }
  }
  // Return success
  return true;
}

void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
  // -- Additional clean target
  bool additionalFiles = WriteTargetCleanAdditional(os);

  // -- Default clean target
  // Write rule
  {
    cmNinjaRule rule("CLEAN");
    rule.Command = NinjaCmd() + " $FILE_ARG -t clean $TARGETS";
    rule.Description = "Cleaning all built files...";
    rule.Comment = "Rule for cleaning all built files.";
    WriteRule(*this->RulesFileStream, rule);
  }

  auto const configs = this->Makefiles.front()->GetGeneratorConfigs();

  // Write build
  {
    cmNinjaBuild build("CLEAN");
    build.Comment = "Clean all the built files.";
    build.Outputs.emplace_back();

    for (auto const& config : configs) {
      build.Outputs.front() = this->BuildAlias(
        this->NinjaOutputPath(this->GetCleanTargetName()), config);
      if (this->IsMultiConfig()) {
        build.Variables["TARGETS"] =
          cmStrCat(this->BuildAlias(GetByproductsForCleanTargetName(), config),
                   " ", GetByproductsForCleanTargetName());
      }
      build.ExplicitDeps.clear();
      if (additionalFiles) {
        build.ExplicitDeps.push_back(this->BuildAlias(
          this->NinjaOutputPath(this->GetAdditionalCleanTargetName()),
          config));
      }
      for (auto const& fileConfig : configs) {
        if (fileConfig != config && !this->EnableCrossConfigBuild()) {
          continue;
        }
        if (this->IsMultiConfig()) {
          build.Variables["FILE_ARG"] = cmStrCat(
            "-f ",
            cmGlobalNinjaMultiGenerator::GetNinjaImplFilename(fileConfig));
        }
        this->WriteBuild(*this->GetImplFileStream(fileConfig), build);
      }
    }

    if (this->EnableCrossConfigBuild()) {
      build.Outputs.front() = this->BuildAlias(
        this->NinjaOutputPath(this->GetCleanTargetName()), "all");
      build.ExplicitDeps.clear();

      if (additionalFiles) {
        build.ExplicitDeps.push_back(
          this->NinjaOutputPath(this->GetAdditionalCleanTargetName()));
      }

      build.Variables["TARGETS"] = "";

      for (auto const& fileConfig : configs) {
        build.Variables["FILE_ARG"] = cmStrCat(
          "-f ",
          cmGlobalNinjaMultiGenerator::GetNinjaImplFilename(fileConfig));
        this->WriteBuild(*this->GetImplFileStream(fileConfig), build);
      }
    }
  }

  if (this->IsMultiConfig()) {
    cmNinjaBuild build("phony");
    build.Outputs.emplace_back(
      this->NinjaOutputPath(this->GetCleanTargetName()));
    build.ExplicitDeps.emplace_back();

    for (auto const& config : configs) {
      build.ExplicitDeps.front() = this->BuildAlias(
        this->NinjaOutputPath(this->GetCleanTargetName()), config);
      this->WriteBuild(*this->GetConfigFileStream(config), build);
    }

    auto const* defaultConfig = this->GetDefaultBuildAlias();
    if (defaultConfig) {
      std::string config = defaultConfig;
      build.ExplicitDeps.front() = this->BuildAlias(
        this->NinjaOutputPath(this->GetCleanTargetName()), config);
      this->WriteBuild(*this->GetDefaultFileStream(), build);
    }
  }

  // Write byproducts
  if (this->IsMultiConfig()) {
    cmNinjaBuild build("phony");
    build.Comment = "Clean byproducts.";
    build.Outputs.emplace_back(
      this->ConvertToNinjaPath(GetByproductsForCleanTargetName()));
    build.ExplicitDeps = this->ByproductsForCleanTarget;
    WriteBuild(os, build);

    for (auto const& config : configs) {
      build.Outputs.front() = this->BuildAlias(
        this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config);
      build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget;
      WriteBuild(os, build);
    }
  }
}

void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
  {
    cmNinjaRule rule("HELP");
    rule.Command = NinjaCmd() + " -t targets";
    rule.Description = "All primary targets available:";
    rule.Comment = "Rule for printing all primary targets available.";
    WriteRule(*this->RulesFileStream, rule);
  }
  {
    cmNinjaBuild build("HELP");
    build.Comment = "Print all primary targets available.";
    build.Outputs.push_back(this->NinjaOutputPath("help"));
    WriteBuild(os, build);
  }
}

void cmGlobalNinjaGenerator::InitOutputPathPrefix()
{
  this->OutputPathPrefix =
    this->LocalGenerators[0]->GetMakefile()->GetSafeDefinition(
      "CMAKE_NINJA_OUTPUT_PATH_PREFIX");
  EnsureTrailingSlash(this->OutputPathPrefix);
}

std::string cmGlobalNinjaGenerator::NinjaOutputPath(
  std::string const& path) const
{
  if (!this->HasOutputPathPrefix() || cmSystemTools::FileIsFullPath(path)) {
    return path;
  }
  return this->OutputPathPrefix + path;
}

void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix(
  std::string& path)
{
  if (path.empty()) {
    return;
  }
  EnsureTrailingSlash(path);
  cmStripSuffixIfExists(path, this->OutputPathPrefix);
}

/*

We use the following approach to support Fortran.  Each target already
has a <target>.dir/ directory used to hold intermediate files for CMake.
For each target, a FortranDependInfo.json file is generated by CMake with
information about include directories, module directories, and the locations
the per-target directories for target dependencies.

Compilation of source files within a target is split into the following steps:

1. Preprocess all sources, scan preprocessed output for module dependencies.
   This step is done with independent build statements for each source,
   and can therefore be done in parallel.

    rule Fortran_PREPROCESS
      depfile = $DEP_FILE
      command = gfortran -cpp $DEFINES $INCLUDES $FLAGS -E $in -o $out &&
                cmake -E cmake_ninja_depends \
                  --tdi=FortranDependInfo.json --pp=$out --dep=$DEP_FILE \
                  --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE \
                  --lang=Fortran

    build src.f90-pp.f90 | src.f90.o.ddi: Fortran_PREPROCESS src.f90
      OBJ_FILE = src.f90.o
      DEP_FILE = src.f90.o.d
      DYNDEP_INTERMEDIATE_FILE = src.f90.o.ddi

   The ``cmake -E cmake_ninja_depends`` tool reads the preprocessed output
   and generates the ninja depfile for preprocessor dependencies.  It also
   generates a "ddi" file (in a format private to CMake) that lists the
   object file that compilation will produce along with the module names
   it provides and/or requires.  The "ddi" file is an implicit output
   because it should not appear in "$out" but is generated by the rule.

2. Consolidate the per-source module dependencies saved in the "ddi"
   files from all sources to produce a ninja "dyndep" file, ``Fortran.dd``.

    rule Fortran_DYNDEP
      command = cmake -E cmake_ninja_dyndep \
                  --tdi=FortranDependInfo.json --lang=Fortran --dd=$out $in

    build Fortran.dd: Fortran_DYNDEP src1.f90.o.ddi src2.f90.o.ddi

   The ``cmake -E cmake_ninja_dyndep`` tool reads the "ddi" files from all
   sources in the target and the ``FortranModules.json`` files from targets
   on which the target depends.  It computes dependency edges on compilations
   that require modules to those that provide the modules.  This information
   is placed in the ``Fortran.dd`` file for ninja to load later.  It also
   writes the expected location of modules provided by this target into
   ``FortranModules.json`` for use by dependent targets.

3. Compile all sources after loading dynamically discovered dependencies
   of the compilation build statements from their ``dyndep`` bindings.

    rule Fortran_COMPILE
      command = gfortran $INCLUDES $FLAGS -c $in -o $out

    build src1.f90.o: Fortran_COMPILE src1.f90-pp.f90 || Fortran.dd
      dyndep = Fortran.dd

   The "dyndep" binding tells ninja to load dynamically discovered
   dependency information from ``Fortran.dd``.  This adds information
   such as:

    build src1.f90.o | mod1.mod: dyndep
      restat = 1

   This tells ninja that ``mod1.mod`` is an implicit output of compiling
   the object file ``src1.f90.o``.  The ``restat`` binding tells it that
   the timestamp of the output may not always change.  Additionally:

    build src2.f90.o: dyndep | mod1.mod

   This tells ninja that ``mod1.mod`` is a dependency of compiling the
   object file ``src2.f90.o``.  This ensures that ``src1.f90.o`` and
   ``mod1.mod`` will always be up to date before ``src2.f90.o`` is built
   (because the latter consumes the module).
*/

struct cmSourceInfo
{
  // Set of provided and required modules.
  std::set<std::string> Provides;
  std::set<std::string> Requires;

  // Set of files included in the translation unit.
  std::set<std::string> Includes;
};

static std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
  std::string const& arg_tdi, std::string const& arg_pp);

int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
                              std::vector<std::string>::const_iterator argEnd)
{
  std::string arg_tdi;
  std::string arg_pp;
  std::string arg_dep;
  std::string arg_obj;
  std::string arg_ddi;
  std::string arg_lang;
  for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
    if (cmHasLiteralPrefix(arg, "--tdi=")) {
      arg_tdi = arg.substr(6);
    } else if (cmHasLiteralPrefix(arg, "--pp=")) {
      arg_pp = arg.substr(5);
    } else if (cmHasLiteralPrefix(arg, "--dep=")) {
      arg_dep = arg.substr(6);
    } else if (cmHasLiteralPrefix(arg, "--obj=")) {
      arg_obj = arg.substr(6);
    } else if (cmHasLiteralPrefix(arg, "--ddi=")) {
      arg_ddi = arg.substr(6);
    } else if (cmHasLiteralPrefix(arg, "--lang=")) {
      arg_lang = arg.substr(7);
    } else {
      cmSystemTools::Error("-E cmake_ninja_depends unknown argument: " + arg);
      return 1;
    }
  }
  if (arg_tdi.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --tdi=");
    return 1;
  }
  if (arg_pp.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --pp=");
    return 1;
  }
  if (arg_dep.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --dep=");
    return 1;
  }
  if (arg_obj.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --obj=");
    return 1;
  }
  if (arg_ddi.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --ddi=");
    return 1;
  }
  if (arg_lang.empty()) {
    cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang=");
    return 1;
  }

  std::unique_ptr<cmSourceInfo> info;
  if (arg_lang == "Fortran") {
    info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp);
  } else {
    cmSystemTools::Error(
      cmStrCat("-E cmake_ninja_depends does not understand the ", arg_lang,
               " language"));
    return 1;
  }

  if (!info) {
    // The error message is already expected to have been output.
    return 1;
  }

  {
    cmGeneratedFileStream depfile(arg_dep);
    depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
    for (std::string const& include : info->Includes) {
      depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
    }
    depfile << "\n";
  }

  Json::Value ddi(Json::objectValue);
  ddi["object"] = arg_obj;

  Json::Value& ddi_provides = ddi["provides"] = Json::arrayValue;
  for (std::string const& provide : info->Provides) {
    ddi_provides.append(provide);
  }
  Json::Value& ddi_requires = ddi["requires"] = Json::arrayValue;
  for (std::string const& r : info->Requires) {
    // Require modules not provided in the same source.
    if (!info->Provides.count(r)) {
      ddi_requires.append(r);
    }
  }

  cmGeneratedFileStream ddif(arg_ddi);
  ddif << ddi;
  if (!ddif) {
    cmSystemTools::Error("-E cmake_ninja_depends failed to write " + arg_ddi);
    return 1;
  }
  return 0;
}

std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
  std::string const& arg_tdi, std::string const& arg_pp)
{
  cmFortranCompiler fc;
  std::vector<std::string> includes;
  {
    Json::Value tdio;
    Json::Value const& tdi = tdio;
    {
      cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
      Json::Reader reader;
      if (!reader.parse(tdif, tdio, false)) {
        cmSystemTools::Error(
          cmStrCat("-E cmake_ninja_depends failed to parse ", arg_tdi,
                   reader.getFormattedErrorMessages()));
        return nullptr;
      }
    }

    Json::Value const& tdi_include_dirs = tdi["include-dirs"];
    if (tdi_include_dirs.isArray()) {
      for (auto const& tdi_include_dir : tdi_include_dirs) {
        includes.push_back(tdi_include_dir.asString());
      }
    }

    Json::Value const& tdi_compiler_id = tdi["compiler-id"];
    fc.Id = tdi_compiler_id.asString();

    Json::Value const& tdi_submodule_sep = tdi["submodule-sep"];
    fc.SModSep = tdi_submodule_sep.asString();

    Json::Value const& tdi_submodule_ext = tdi["submodule-ext"];
    fc.SModExt = tdi_submodule_ext.asString();
  }

  cmFortranSourceInfo finfo;
  std::set<std::string> defines;
  cmFortranParser parser(fc, includes, defines, finfo);
  if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) {
    cmSystemTools::Error("-E cmake_ninja_depends failed to open " + arg_pp);
    return nullptr;
  }
  if (cmFortran_yyparse(parser.Scanner) != 0) {
    // Failed to parse the file.
    return nullptr;
  }

  auto info = cm::make_unique<cmSourceInfo>();
  info->Provides = finfo.Provides;
  info->Requires = finfo.Requires;
  info->Includes = finfo.Includes;
  return info;
}

struct cmDyndepObjectInfo
{
  std::string Object;
  std::vector<std::string> Provides;
  std::vector<std::string> Requires;
};

bool cmGlobalNinjaGenerator::WriteDyndepFile(
  std::string const& dir_top_src, std::string const& dir_top_bld,
  std::string const& dir_cur_src, std::string const& dir_cur_bld,
  std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
  std::string const& module_dir,
  std::vector<std::string> const& linked_target_dirs,
  std::string const& arg_lang)
{
  // Setup path conversions.
  {
    cmStateSnapshot snapshot = this->GetCMakeInstance()->GetCurrentSnapshot();
    snapshot.GetDirectory().SetCurrentSource(dir_cur_src);
    snapshot.GetDirectory().SetCurrentBinary(dir_cur_bld);
    snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str());
    snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str());
    auto mfd = cm::make_unique<cmMakefile>(this, snapshot);
    auto lgd = this->CreateLocalGenerator(mfd.get());
    this->Makefiles.push_back(std::move(mfd));
    this->LocalGenerators.push_back(std::move(lgd));
  }

  std::vector<cmDyndepObjectInfo> objects;
  for (std::string const& arg_ddi : arg_ddis) {
    // Load the ddi file and compute the module file paths it provides.
    Json::Value ddio;
    Json::Value const& ddi = ddio;
    cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary);
    Json::Reader reader;
    if (!reader.parse(ddif, ddio, false)) {
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                    arg_ddi,
                                    reader.getFormattedErrorMessages()));
      return false;
    }

    cmDyndepObjectInfo info;
    info.Object = ddi["object"].asString();
    Json::Value const& ddi_provides = ddi["provides"];
    if (ddi_provides.isArray()) {
      for (auto const& ddi_provide : ddi_provides) {
        info.Provides.push_back(ddi_provide.asString());
      }
    }
    Json::Value const& ddi_requires = ddi["requires"];
    if (ddi_requires.isArray()) {
      for (auto const& ddi_require : ddi_requires) {
        info.Requires.push_back(ddi_require.asString());
      }
    }
    objects.push_back(std::move(info));
  }

  // Map from module name to module file path, if known.
  std::map<std::string, std::string> mod_files;

  // Populate the module map with those provided by linked targets first.
  for (std::string const& linked_target_dir : linked_target_dirs) {
    std::string const ltmn =
      cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json");
    Json::Value ltm;
    cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
    Json::Reader reader;
    if (ltmf && !reader.parse(ltmf, ltm, false)) {
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                    linked_target_dir,
                                    reader.getFormattedErrorMessages()));
      return false;
    }
    if (ltm.isObject()) {
      for (Json::Value::iterator i = ltm.begin(); i != ltm.end(); ++i) {
        mod_files[i.key().asString()] = i->asString();
      }
    }
  }

  // Extend the module map with those provided by this target.
  // We do this after loading the modules provided by linked targets
  // in case we have one of the same name that must be preferred.
  Json::Value tm = Json::objectValue;
  for (cmDyndepObjectInfo const& object : objects) {
    for (std::string const& p : object.Provides) {
      std::string const mod = module_dir + p;
      mod_files[p] = mod;
      tm[p] = mod;
    }
  }

  cmGeneratedFileStream ddf(arg_dd);
  ddf << "ninja_dyndep_version = 1.0\n";

  {
    cmNinjaBuild build("dyndep");
    build.Outputs.emplace_back("");
    for (cmDyndepObjectInfo const& object : objects) {
      build.Outputs[0] = object.Object;
      build.ImplicitOuts.clear();
      for (std::string const& p : object.Provides) {
        build.ImplicitOuts.push_back(this->ConvertToNinjaPath(mod_files[p]));
      }
      build.ImplicitDeps.clear();
      for (std::string const& r : object.Requires) {
        auto mit = mod_files.find(r);
        if (mit != mod_files.end()) {
          build.ImplicitDeps.push_back(this->ConvertToNinjaPath(mit->second));
        }
      }
      build.Variables.clear();
      if (!object.Provides.empty()) {
        build.Variables.emplace("restat", "1");
      }

      this->WriteBuild(ddf, build);
    }
  }

  // Store the map of modules provided by this target in a file for
  // use by dependents that reference this target in linked-target-dirs.
  std::string const target_mods_file =
    cmSystemTools::GetFilenamePath(arg_dd) + "/" + arg_lang + "Modules.json";
  cmGeneratedFileStream tmf(target_mods_file);
  tmf << tm;

  return true;
}

bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
{
  return this->IsMultiConfig() &&
    this->Makefiles.front()->IsOn("CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE");
}

int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
                             std::vector<std::string>::const_iterator argEnd)
{
  std::vector<std::string> arg_full =
    cmSystemTools::HandleResponseFile(argBeg, argEnd);

  std::string arg_dd;
  std::string arg_lang;
  std::string arg_tdi;
  std::vector<std::string> arg_ddis;
  for (std::string const& arg : arg_full) {
    if (cmHasLiteralPrefix(arg, "--tdi=")) {
      arg_tdi = arg.substr(6);
    } else if (cmHasLiteralPrefix(arg, "--lang=")) {
      arg_lang = arg.substr(7);
    } else if (cmHasLiteralPrefix(arg, "--dd=")) {
      arg_dd = arg.substr(5);
    } else if (!cmHasLiteralPrefix(arg, "--") &&
               cmHasLiteralSuffix(arg, ".ddi")) {
      arg_ddis.push_back(arg);
    } else {
      cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: " + arg);
      return 1;
    }
  }
  if (arg_tdi.empty()) {
    cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --tdi=");
    return 1;
  }
  if (arg_lang.empty()) {
    cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --lang=");
    return 1;
  }
  if (arg_dd.empty()) {
    cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --dd=");
    return 1;
  }

  Json::Value tdio;
  Json::Value const& tdi = tdio;
  {
    cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
    Json::Reader reader;
    if (!reader.parse(tdif, tdio, false)) {
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                    arg_tdi,
                                    reader.getFormattedErrorMessages()));
      return 1;
    }
  }

  std::string const dir_cur_bld = tdi["dir-cur-bld"].asString();
  std::string const dir_cur_src = tdi["dir-cur-src"].asString();
  std::string const dir_top_bld = tdi["dir-top-bld"].asString();
  std::string const dir_top_src = tdi["dir-top-src"].asString();
  std::string module_dir = tdi["module-dir"].asString();
  if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) {
    module_dir += "/";
  }
  std::vector<std::string> linked_target_dirs;
  Json::Value const& tdi_linked_target_dirs = tdi["linked-target-dirs"];
  if (tdi_linked_target_dirs.isArray()) {
    for (auto const& tdi_linked_target_dir : tdi_linked_target_dirs) {
      linked_target_dirs.push_back(tdi_linked_target_dir.asString());
    }
  }

  cmake cm(cmake::RoleInternal, cmState::Unknown);
  cm.SetHomeDirectory(dir_top_src);
  cm.SetHomeOutputDirectory(dir_top_bld);
  auto ggd = cm.CreateGlobalGenerator("Ninja");
  if (!ggd ||
      !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile(
        dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis,
        module_dir, linked_target_dirs, arg_lang)) {
    return 1;
  }
  return 0;
}

void cmGlobalNinjaGenerator::AppendDirectoryForConfig(
  const std::string& prefix, const std::string& config,
  const std::string& suffix, std::string& dir)
{
  if (!config.empty() && this->IsMultiConfig()) {
    dir += prefix;
    dir += config;
    dir += suffix;
  }
}

const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE =
  "CMakeFiles/common.ninja";
const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja";

cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm)
  : cmGlobalNinjaGenerator(cm)
{
  cm->GetState()->SetIsGeneratorMultiConfig(true);
  cm->GetState()->SetNinjaMulti(true);
}

void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
{
  entry.Name = cmGlobalNinjaMultiGenerator::GetActualName();
  entry.Brief = "Generates build-<Config>.ninja files.";
}

std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir(
  const std::string& str, const std::string& config) const
{
  std::string result = str;
  cmSystemTools::ReplaceString(result, this->GetCMakeCFGIntDir(), config);
  return result;
}

bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams()
{
  if (!this->OpenFileStream(this->CommonFileStream,
                            cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE)) {
    return false;
  }

  auto const* defaultConfig = this->GetDefaultBuildType();
  if (defaultConfig) {
    if (!this->OpenFileStream(this->DefaultFileStream, NINJA_BUILD_FILE)) {
      return false;
    }
    *this->DefaultFileStream
      << "# This file is a convenience file generated by\n"
      << "# CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.\n\n"
      << "include " << GetNinjaImplFilename(defaultConfig) << "\n\n";
  }

  // Write a comment about this file.
  *this->CommonFileStream
    << "# This file contains build statements common to all "
       "configurations.\n\n";

  for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
    // Open impl file.
    if (!this->OpenFileStream(this->ImplFileStreams[config],
                              GetNinjaImplFilename(config))) {
      return false;
    }

    // Write a comment about this file.
    *this->ImplFileStreams[config]
      << "# This file contains build statements specific to the \"" << config
      << "\"\n# configuration.\n\n";

    // Open config file.
    if (!this->OpenFileStream(this->ConfigFileStreams[config],
                              GetNinjaConfigFilename(config))) {
      return false;
    }

    // Write a comment about this file.
    *this->ConfigFileStreams[config]
      << "# This file contains aliases specific to the \"" << config
      << "\"\n# configuration.\n\n"
      << "include " << GetNinjaImplFilename(config) << "\n\n";
  }

  return true;
}

void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams()
{
  if (this->CommonFileStream) {
    this->CommonFileStream.reset();
  } else {
    cmSystemTools::Error("Common file stream was not open.");
  }

  if (this->DefaultFileStream) {
    this->DefaultFileStream.reset();
  } // No error if it wasn't open

  for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) {
    if (this->ImplFileStreams[config]) {
      this->ImplFileStreams[config].reset();
    } else {
      cmSystemTools::Error(
        cmStrCat("Impl file stream for \"", config, "\" was not open."));
    }
    if (this->ConfigFileStreams[config]) {
      this->ConfigFileStreams[config].reset();
    } else {
      cmSystemTools::Error(
        cmStrCat("Config file stream for \"", config, "\" was not open."));
    }
  }
}

void cmGlobalNinjaMultiGenerator::AppendNinjaFileArgument(
  GeneratedMakeCommand& command, const std::string& config) const
{
  command.Add("-f");
  command.Add(GetNinjaConfigFilename(config));
}

std::string cmGlobalNinjaMultiGenerator::GetNinjaImplFilename(
  const std::string& config)
{
  return cmStrCat("CMakeFiles/impl-", config,
                  cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION);
}

std::string cmGlobalNinjaMultiGenerator::GetNinjaConfigFilename(
  const std::string& config)
{
  return cmStrCat("build-", config,
                  cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION);
}

void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs(
  cmNinjaDeps& outputs) const
{
  for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) {
    outputs.push_back(this->NinjaOutputPath(GetNinjaImplFilename(config)));
    outputs.push_back(this->NinjaOutputPath(GetNinjaConfigFilename(config)));
  }
  if (this->Makefiles.front()->GetDefinition(
        "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE")) {
    outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
  }
}

void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs(
  std::vector<std::string>& configs) const
{
  auto const oldSize = configs.size();
  this->Makefiles.front()->GetConfigurations(configs);
  if (configs.size() == oldSize) {
    configs.emplace_back();
  }
}

const char* cmGlobalNinjaMultiGenerator::GetDefaultBuildType() const
{
  return this->Makefiles.front()->GetDefinition(
    "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE");
}

const char* cmGlobalNinjaMultiGenerator::GetDefaultBuildAlias() const
{
  if (this->EnableCrossConfigBuild()) {
    auto const* alias = this->Makefiles.front()->GetDefinition(
      "CMAKE_NINJA_MULTI_DEFAULT_BUILD_ALIAS");
    if (alias) {
      return alias;
    }
  }

  return this->GetDefaultBuildType();
}
