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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iterator>
#include <memory>
#include <sstream>
#include <utility>

#include <cmext/string_view>

#include "cmsys/FStream.hxx"

#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmNinjaTargetGenerator.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"

cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
                                             cmMakefile* mf)
  : cmLocalCommonGenerator(gg, mf, WorkDir::TopBin)
{
}

// Virtual public methods.

cmRulePlaceholderExpander*
cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
{
  cmRulePlaceholderExpander* ret =
    this->cmLocalGenerator::CreateRulePlaceholderExpander();
  ret->SetTargetImpLib("$TARGET_IMPLIB");
  return ret;
}

cmLocalNinjaGenerator::~cmLocalNinjaGenerator() = default;

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

  if (this->GetGlobalGenerator()->IsMultiConfig()) {
    for (auto const& config : this->GetConfigNames()) {
      this->WriteProcessedMakefile(this->GetImplFileStream(config));
    }
  }
  this->WriteProcessedMakefile(this->GetCommonFileStream());
#ifdef NINJA_GEN_VERBOSE_FILES
  this->WriteProcessedMakefile(this->GetRulesFileStream());
#endif

  // We do that only once for the top CMakeLists.txt file.
  if (this->IsRootMakefile()) {
    this->WriteBuildFileTop();

    this->WritePools(this->GetRulesFileStream());

    const std::string& showIncludesPrefix =
      this->GetMakefile()->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
    if (!showIncludesPrefix.empty()) {
      cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(),
                                           "localized /showIncludes string");
      this->GetRulesFileStream() << "msvc_deps_prefix = ";
#ifdef WIN32
      // Ninja uses the ANSI Windows APIs, so strings in the rules file
      // typically need to be ANSI encoded. However, in this case the compiler
      // is being invoked using the UTF-8 codepage so the /showIncludes prefix
      // will be UTF-8 encoded on stdout. Ninja can't successfully compare this
      // UTF-8 encoded prefix to the ANSI encoded msvc_deps_prefix if it
      // contains any non-ASCII characters and dependency checking will fail.
      // As a workaround, leave the msvc_deps_prefix UTF-8 encoded even though
      // the rest of the file is ANSI encoded.
      if (GetConsoleOutputCP() == CP_UTF8 && GetACP() != CP_UTF8 &&
          this->GetGlobalGenerator()->GetMakefileEncoding() != codecvt::None) {
        this->GetRulesFileStream().WriteRaw(showIncludesPrefix);
      } else {
        // Ninja 1.11 and above uses the UTF-8 code page if it's supported, so
        // in that case we can write it normally without using raw bytes.
        this->GetRulesFileStream() << showIncludesPrefix;
      }
#else
      // It's safe to use the standard encoding on other platforms.
      this->GetRulesFileStream() << showIncludesPrefix;
#endif
      this->GetRulesFileStream() << "\n\n";
    }
  }

  for (const auto& target : this->GetGeneratorTargets()) {
    if (!target->IsInBuildSystem()) {
      continue;
    }
    auto tg = cmNinjaTargetGenerator::New(target.get());
    if (tg) {
      if (target->Target->IsPerConfig()) {
        for (auto const& config : this->GetConfigNames()) {
          tg->Generate(config);
          if (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
              this->GetGlobalGenerator()->IsMultiConfig()) {
            cmNinjaBuild phonyAlias("phony");
            this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
              target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact);
            this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
              target.get(), phonyAlias.ExplicitDeps, config,
              DependOnTargetArtifact);
            this->GetGlobalNinjaGenerator()->WriteBuild(
              *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config),
              phonyAlias);
          }
        }
        if (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
            this->GetGlobalGenerator()->IsMultiConfig()) {
          if (!this->GetGlobalNinjaGenerator()->GetDefaultConfigs().empty()) {
            cmNinjaBuild phonyAlias("phony");
            this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
              target.get(), phonyAlias.Outputs, "", DependOnTargetArtifact);
            for (auto const& config :
                 this->GetGlobalNinjaGenerator()->GetDefaultConfigs()) {
              this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
                target.get(), phonyAlias.ExplicitDeps, config,
                DependOnTargetArtifact);
            }
            this->GetGlobalNinjaGenerator()->WriteBuild(
              *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(),
              phonyAlias);
          }
          cmNinjaBuild phonyAlias("phony");
          this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
            target.get(), phonyAlias.Outputs, "all", DependOnTargetArtifact);
          for (auto const& config : this->GetConfigNames()) {
            this->GetGlobalNinjaGenerator()->AppendTargetOutputs(
              target.get(), phonyAlias.ExplicitDeps, config,
              DependOnTargetArtifact);
          }
          this->GetGlobalNinjaGenerator()->WriteBuild(
            *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(),
            phonyAlias);
        }
      } else {
        tg->Generate("");
      }
    }
  }

  for (auto const& config : this->GetConfigNames()) {
    this->WriteCustomCommandBuildStatements(config);
    this->AdditionalCleanFiles(config);
  }
}

// TODO: Picked up from cmLocalUnixMakefileGenerator3.  Refactor it.
std::string cmLocalNinjaGenerator::GetTargetDirectory(
  cmGeneratorTarget const* target) const
{
  std::string dir = cmStrCat("CMakeFiles/", target->GetName());
#if defined(__VMS)
  dir += "_dir";
#else
  dir += ".dir";
#endif
  return dir;
}

// Non-virtual public methods.

const cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
  const
{
  return static_cast<const cmGlobalNinjaGenerator*>(
    this->GetGlobalGenerator());
}

cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
{
  return static_cast<cmGlobalNinjaGenerator*>(this->GetGlobalGenerator());
}

// Virtual protected methods.

std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
  std::string const& path, IncludePathStyle pathStyle,
  cmOutputConverter::OutputFormat format)
{
  // FIXME: Remove IncludePathStyle infrastructure.  It is no longer used.
  static_cast<void>(pathStyle);
  return this->ConvertToOutputFormat(path, format);
}

// Private methods.

cmGeneratedFileStream& cmLocalNinjaGenerator::GetImplFileStream(
  const std::string& config) const
{
  return *this->GetGlobalNinjaGenerator()->GetImplFileStream(config);
}

cmGeneratedFileStream& cmLocalNinjaGenerator::GetCommonFileStream() const
{
  return *this->GetGlobalNinjaGenerator()->GetCommonFileStream();
}

cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const
{
  return *this->GetGlobalNinjaGenerator()->GetRulesFileStream();
}

const cmake* cmLocalNinjaGenerator::GetCMakeInstance() const
{
  return this->GetGlobalGenerator()->GetCMakeInstance();
}

cmake* cmLocalNinjaGenerator::GetCMakeInstance()
{
  return this->GetGlobalGenerator()->GetCMakeInstance();
}

void cmLocalNinjaGenerator::WriteBuildFileTop()
{
  this->WriteProjectHeader(this->GetCommonFileStream());

  if (this->GetGlobalGenerator()->IsMultiConfig()) {
    for (auto const& config : this->GetConfigNames()) {
      auto& stream = this->GetImplFileStream(config);
      this->WriteProjectHeader(stream);
      this->WriteNinjaRequiredVersion(stream);
      this->WriteNinjaConfigurationVariable(stream, config);
      this->WriteNinjaFilesInclusionConfig(stream);
    }
  } else {
    this->WriteNinjaRequiredVersion(this->GetCommonFileStream());
    this->WriteNinjaConfigurationVariable(this->GetCommonFileStream(),
                                          this->GetConfigNames().front());
  }
  this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream());
  this->WriteNinjaWorkDir(this->GetCommonFileStream());

  // For the rule file.
  this->WriteProjectHeader(this->GetRulesFileStream());
}

void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Project: " << this->GetProjectName() << '\n'
     << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") << '\n';
  cmGlobalNinjaGenerator::WriteDivider(os);
}

void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
{
  // Default required version
  std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion();

  // Ninja generator uses the 'console' pool if available (>= 1.5)
  if (this->GetGlobalNinjaGenerator()->SupportsDirectConsole()) {
    requiredVersion =
      cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool();
  }

  // The Ninja generator writes rules which require support for restat
  // when rebuilding build.ninja manifest (>= 1.8)
  if (this->GetGlobalNinjaGenerator()->SupportsManifestRestat() &&
      this->GetCMakeInstance()->DoWriteGlobVerifyTarget() &&
      !this->GetGlobalNinjaGenerator()->GlobalSettingIsOn(
        "CMAKE_SUPPRESS_REGENERATION")) {
    requiredVersion =
      cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat();
  }

  cmGlobalNinjaGenerator::WriteComment(
    os, "Minimal version of Ninja required by this file");
  os << "ninja_required_version = " << requiredVersion << "\n\n";
}

void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable(
  std::ostream& os, const std::string& config)
{
  cmGlobalNinjaGenerator::WriteVariable(
    os, "CONFIGURATION", config,
    "Set configuration variable for custom commands.");
}

void cmLocalNinjaGenerator::WritePools(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);

  cmProp jobpools =
    this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS");
  if (!jobpools) {
    jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS");
  }
  if (jobpools) {
    cmGlobalNinjaGenerator::WriteComment(
      os, "Pools defined by global property JOB_POOLS");
    std::vector<std::string> pools = cmExpandedList(*jobpools);
    for (std::string const& pool : pools) {
      const std::string::size_type eq = pool.find('=');
      unsigned int jobs;
      if (eq != std::string::npos &&
          sscanf(pool.c_str() + eq, "=%u", &jobs) == 1) {
        os << "pool " << pool.substr(0, eq) << "\n  depth = " << jobs
           << "\n\n";
      } else {
        cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': " +
                             pool);
      }
    }
  }
}

void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Include auxiliary files.\n\n";
  cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
  std::string const ninjaCommonFile =
    ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE);
  std::string const commonFilePath = ng->EncodePath(ninjaCommonFile);
  cmGlobalNinjaGenerator::WriteInclude(os, commonFilePath,
                                       "Include common file.");
  os << "\n";
}

void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Include auxiliary files.\n\n";
  cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
  std::string const ninjaRulesFile =
    ng->NinjaOutputPath(cmGlobalNinjaGenerator::NINJA_RULES_FILE);
  std::string const rulesFilePath = ng->EncodePath(ninjaRulesFile);
  cmGlobalNinjaGenerator::WriteInclude(os, rulesFilePath,
                                       "Include rules file.");
  os << "\n";
}

void cmLocalNinjaGenerator::WriteNinjaWorkDir(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  cmGlobalNinjaGenerator::WriteComment(
    os, "Logical path to working directory; prefix for absolute paths.");
  cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
  std::string ninja_workdir = this->GetBinaryDirectory();
  ng->StripNinjaOutputPathPrefixAsSuffix(ninja_workdir); // Also appends '/'.
  os << "cmake_ninja_workdir = " << ng->EncodePath(ninja_workdir) << "\n";
}

void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
{
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << "# Write statements declared in CMakeLists.txt:\n"
     << "# " << this->Makefile->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE")
     << '\n';
  if (this->IsRootMakefile()) {
    os << "# Which is the root file.\n";
  }
  cmGlobalNinjaGenerator::WriteDivider(os);
  os << '\n';
}

void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target,
                                                cmNinjaDeps& outputs,
                                                const std::string& config)
{
  this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, config,
                                                       DependOnTargetArtifact);
}

void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
                                                cmNinjaDeps& outputs,
                                                const std::string& config,
                                                const std::string& fileConfig,
                                                cmNinjaTargetDepends depends)
{
  this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config,
                                                       fileConfig, depends);
}

void cmLocalNinjaGenerator::AppendCustomCommandDeps(
  cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps,
  const std::string& config)
{
  for (std::string const& i : ccg.GetDepends()) {
    std::string dep;
    if (this->GetRealDependency(i, config, dep)) {
      ninjaDeps.push_back(
        this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep));
    }
  }
}

std::string cmLocalNinjaGenerator::WriteCommandScript(
  std::vector<std::string> const& cmdLines, std::string const& outputConfig,
  std::string const& commandConfig, std::string const& customStep,
  cmGeneratorTarget const* target) const
{
  std::string scriptPath;
  if (target) {
    scriptPath = target->GetSupportDirectory();
  } else {
    scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
  }
  scriptPath += this->GetGlobalNinjaGenerator()->ConfigDirectory(outputConfig);
  cmSystemTools::MakeDirectory(scriptPath);
  scriptPath += '/';
  scriptPath += customStep;
  if (this->GlobalGenerator->IsMultiConfig()) {
    scriptPath += cmStrCat('-', commandConfig);
  }
#ifdef _WIN32
  scriptPath += ".bat";
#else
  scriptPath += ".sh";
#endif

  cmsys::ofstream script(scriptPath.c_str());

#ifdef _WIN32
  script << "@echo off\n";
  int line = 1;
#else
  script << "set -e\n\n";
#endif

  for (auto const& i : cmdLines) {
    std::string cmd = i;
    // The command line was built assuming it would be written to
    // the build.ninja file, so it uses '$$' for '$'.  Remove this
    // for the raw shell script.
    cmSystemTools::ReplaceString(cmd, "$$", "$");
#ifdef _WIN32
    script << cmd << " || (set FAIL_LINE=" << ++line << "& goto :ABORT)"
           << '\n';
#else
    script << cmd << '\n';
#endif
  }

#ifdef _WIN32
  script << "goto :EOF\n\n"
            ":ABORT\n"
            "set ERROR_CODE=%ERRORLEVEL%\n"
            "echo Batch file failed at line %FAIL_LINE% "
            "with errorcode %ERRORLEVEL%\n"
            "exit /b %ERROR_CODE%";
#endif

  return scriptPath;
}

std::string cmLocalNinjaGenerator::BuildCommandLine(
  std::vector<std::string> const& cmdLines, std::string const& outputConfig,
  std::string const& commandConfig, std::string const& customStep,
  cmGeneratorTarget const* target) const
{
  // If we have no commands but we need to build a command anyway, use noop.
  // This happens when building a POST_BUILD value for link targets that
  // don't use POST_BUILD.
  if (cmdLines.empty()) {
    return cmGlobalNinjaGenerator::SHELL_NOOP;
  }

  // If this is a custom step then we will have no '$VAR' ninja placeholders.
  // This means we can deal with long command sequences by writing to a script.
  // Do this if the command lines are on the scale of the OS limit.
  if (!customStep.empty()) {
    size_t cmdLinesTotal = 0;
    for (std::string const& cmd : cmdLines) {
      cmdLinesTotal += cmd.length() + 6;
    }
    if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
      std::string const scriptPath = this->WriteCommandScript(
        cmdLines, outputConfig, commandConfig, customStep, target);
      std::string cmd
#ifndef _WIN32
        = "/bin/sh "
#endif
        ;
      cmd += this->ConvertToOutputFormat(
        this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
        cmOutputConverter::SHELL);

      // Add an unused argument based on script content so that Ninja
      // knows when the command lines change.
      cmd += " ";
      cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
      cmd += hash.HashFile(scriptPath).substr(0, 16);
      return cmd;
    }
  }

  std::ostringstream cmd;
  for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li)
#ifdef _WIN32
  {
    if (li != cmdLines.begin()) {
      cmd << " && ";
    } else if (cmdLines.size() > 1) {
      cmd << "cmd.exe /C \"";
    }
    // Put current cmdLine in brackets if it contains "||" because it has
    // higher precedence than "&&" in cmd.exe
    if (li->find("||") != std::string::npos) {
      cmd << "( " << *li << " )";
    } else {
      cmd << *li;
    }
  }
  if (cmdLines.size() > 1) {
    cmd << "\"";
  }
#else
  {
    if (li != cmdLines.begin()) {
      cmd << " && ";
    }
    cmd << *li;
  }
#endif
  return cmd.str();
}

void cmLocalNinjaGenerator::AppendCustomCommandLines(
  cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines)
{
  auto* gg = this->GetGlobalNinjaGenerator();

  if (ccg.GetNumberOfCommands() > 0) {
    std::string wd = ccg.GetWorkingDirectory();
    if (wd.empty()) {
      wd = this->GetCurrentBinaryDirectory();
    }

    std::ostringstream cdCmd;
#ifdef _WIN32
    std::string cdStr = "cd /D ";
#else
    std::string cdStr = "cd ";
#endif
    cdCmd << cdStr
          << this->ConvertToOutputFormat(wd, cmOutputConverter::SHELL);
    cmdLines.push_back(cdCmd.str());
  }

  std::string launcher = this->MakeCustomLauncher(ccg);

  for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
    std::string c = ccg.GetCommand(i);
    if (c.empty()) {
      continue;
    }
    cmdLines.push_back(launcher +
                       this->ConvertToOutputFormat(
                         c,
                         gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI
                                             : cmOutputConverter::SHELL));

    std::string& cmd = cmdLines.back();
    ccg.AppendArguments(i, cmd);
  }
}

void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
  cmCustomCommand const* cc, const std::set<cmGeneratorTarget*>& targets,
  const std::string& fileConfig)
{
  cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
  if (gg->SeenCustomCommand(cc, fileConfig)) {
    return;
  }

  auto ccgs = this->MakeCustomCommandGenerators(*cc, fileConfig);
  for (cmCustomCommandGenerator const& ccg : ccgs) {
    if (ccg.GetOutputs().empty() && ccg.GetByproducts().empty()) {
      // Generator expressions evaluate to no output for this config.
      continue;
    }

    cmNinjaDeps orderOnlyDeps;

    // A custom command may appear on multiple targets.  However, some build
    // systems exist where the target dependencies on some of the targets are
    // overspecified, leading to a dependency cycle.  If we assume all target
    // dependencies are a superset of the true target dependencies for this
    // custom command, we can take the set intersection of all target
    // dependencies to obtain a correct dependency list.
    //
    // FIXME: This won't work in certain obscure scenarios involving indirect
    // dependencies.
    auto j = targets.begin();
    assert(j != targets.end());
    this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
      *j, orderOnlyDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1);
    std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
    ++j;

    for (; j != targets.end(); ++j) {
      std::vector<std::string> jDeps;
      std::vector<std::string> depsIntersection;
      this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(
        *j, jDeps, ccg.GetOutputConfig(), fileConfig, ccgs.size() > 1);
      std::sort(jDeps.begin(), jDeps.end());
      std::set_intersection(orderOnlyDeps.begin(), orderOnlyDeps.end(),
                            jDeps.begin(), jDeps.end(),
                            std::back_inserter(depsIntersection));
      orderOnlyDeps = depsIntersection;
    }

    const std::vector<std::string>& outputs = ccg.GetOutputs();
    const std::vector<std::string>& byproducts = ccg.GetByproducts();

    bool symbolic = false;
    for (std::string const& output : outputs) {
      if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
        if (sf->GetPropertyAsBool("SYMBOLIC")) {
          symbolic = true;
          break;
        }
      }
    }

    cmGlobalNinjaGenerator::CCOutputs ccOutputs(gg);
    ccOutputs.Add(outputs);
    ccOutputs.Add(byproducts);

    std::string mainOutput = ccOutputs.ExplicitOuts[0];

    cmNinjaDeps ninjaDeps;
    this->AppendCustomCommandDeps(ccg, ninjaDeps, fileConfig);

    std::vector<std::string> cmdLines;
    this->AppendCustomCommandLines(ccg, cmdLines);

    if (cmdLines.empty()) {
      cmNinjaBuild build("phony");
      build.Comment = cmStrCat("Phony custom command for ", mainOutput);
      build.Outputs = std::move(ccOutputs.ExplicitOuts);
      build.WorkDirOuts = std::move(ccOutputs.WorkDirOuts);
      build.ExplicitDeps = std::move(ninjaDeps);
      build.OrderOnlyDeps = orderOnlyDeps;
      gg->WriteBuild(this->GetImplFileStream(fileConfig), build);
    } else {
      std::string customStep = cmSystemTools::GetFilenameName(mainOutput);
      if (this->GlobalGenerator->IsMultiConfig()) {
        customStep += '-';
        customStep += fileConfig;
        customStep += '-';
        customStep += ccg.GetOutputConfig();
      }
      // Hash full path to make unique.
      customStep += '-';
      cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
      customStep += hash.HashString(mainOutput).substr(0, 7);

      std::string depfile = ccg.GetDepfile();
      if (!depfile.empty()) {
        switch (cc->GetCMP0116Status()) {
          case cmPolicies::WARN:
            if (this->GetCurrentBinaryDirectory() !=
                  this->GetBinaryDirectory() ||
                this->Makefile->PolicyOptionalWarningEnabled(
                  "CMAKE_POLICY_WARNING_CMP0116")) {
              this->GetCMakeInstance()->IssueMessage(
                MessageType::AUTHOR_WARNING,
                cmPolicies::GetPolicyWarning(cmPolicies::CMP0116),
                cc->GetBacktrace());
            }
            CM_FALLTHROUGH;
          case cmPolicies::OLD:
            break;
          case cmPolicies::REQUIRED_IF_USED:
          case cmPolicies::REQUIRED_ALWAYS:
          case cmPolicies::NEW:
            depfile = ccg.GetInternalDepfile();
            break;
        }
      }

      std::string comment = cmStrCat("Custom command for ", mainOutput);
      gg->WriteCustomCommandBuild(
        this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig,
                               customStep),
        this->ConstructComment(ccg), comment, depfile, cc->GetJobPool(),
        cc->GetUsesTerminal(),
        /*restat*/ !symbolic || !byproducts.empty(), fileConfig,
        std::move(ccOutputs), std::move(ninjaDeps), std::move(orderOnlyDeps));
    }
  }
}

bool cmLocalNinjaGenerator::HasUniqueByproducts(
  std::vector<std::string> const& byproducts, cmListFileBacktrace const& bt)
{
  std::vector<std::string> configs =
    this->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
  cmGeneratorExpression ge(bt);
  for (std::string const& p : byproducts) {
    if (cmGeneratorExpression::Find(p) == std::string::npos) {
      return false;
    }
    std::set<std::string> seen;
    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(p);
    for (std::string const& config : configs) {
      for (std::string const& b :
           this->ExpandCustomCommandOutputPaths(*cge, config)) {
        if (!seen.insert(b).second) {
          return false;
        }
      }
    }
  }
  return true;
}

namespace {
bool HasUniqueOutputs(std::vector<cmCustomCommandGenerator> const& ccgs)
{
  std::set<std::string> allOutputs;
  std::set<std::string> allByproducts;
  for (cmCustomCommandGenerator const& ccg : ccgs) {
    for (std::string const& output : ccg.GetOutputs()) {
      if (!allOutputs.insert(output).second) {
        return false;
      }
    }
    for (std::string const& byproduct : ccg.GetByproducts()) {
      if (!allByproducts.insert(byproduct).second) {
        return false;
      }
    }
  }
  return true;
}
}

std::string cmLocalNinjaGenerator::CreateUtilityOutput(
  std::string const& targetName, std::vector<std::string> const& byproducts,
  cmListFileBacktrace const& bt)
{
  // In Ninja Multi-Config, we can only produce cross-config utility
  // commands if all byproducts are per-config.
  if (!this->GetGlobalGenerator()->IsMultiConfig() ||
      !this->HasUniqueByproducts(byproducts, bt)) {
    return this->cmLocalGenerator::CreateUtilityOutput(targetName, byproducts,
                                                       bt);
  }

  std::string const base = cmStrCat(this->GetCurrentBinaryDirectory(),
                                    "/CMakeFiles/", targetName, '-');
  // The output is not actually created so mark it symbolic.
  for (std::string const& config :
       this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
    std::string const force = cmStrCat(base, config);
    if (cmSourceFile* sf = this->Makefile->GetOrCreateGeneratedSource(force)) {
      sf->SetProperty("SYMBOLIC", "1");
    } else {
      cmSystemTools::Error("Could not get source file entry for " + force);
    }
  }
  this->GetGlobalNinjaGenerator()->AddPerConfigUtilityTarget(targetName);
  return cmStrCat(base, "$<CONFIG>"_s);
}

std::vector<cmCustomCommandGenerator>
cmLocalNinjaGenerator::MakeCustomCommandGenerators(
  cmCustomCommand const& cc, std::string const& fileConfig)
{
  cmGlobalNinjaGenerator const* gg = this->GetGlobalNinjaGenerator();

  bool transformDepfile = false;
  switch (cc.GetCMP0116Status()) {
    case cmPolicies::OLD:
    case cmPolicies::WARN:
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::NEW:
      transformDepfile = true;
      break;
  }

  // Start with the build graph's configuration.
  std::vector<cmCustomCommandGenerator> ccgs;
  ccgs.emplace_back(cc, fileConfig, this, transformDepfile);

  // Consider adding cross configurations.
  if (!gg->EnableCrossConfigBuild()) {
    return ccgs;
  }

  // Outputs and byproducts must be expressed using generator expressions.
  for (std::string const& output : cc.GetOutputs()) {
    if (cmGeneratorExpression::Find(output) == std::string::npos) {
      return ccgs;
    }
  }
  for (std::string const& byproduct : cc.GetByproducts()) {
    if (cmGeneratorExpression::Find(byproduct) == std::string::npos) {
      return ccgs;
    }
  }

  // Tentatively add the other cross configurations.
  for (std::string const& config : gg->GetCrossConfigs(fileConfig)) {
    if (fileConfig != config) {
      ccgs.emplace_back(cc, fileConfig, this, transformDepfile, config);
    }
  }

  // If outputs and byproducts are not unique to each configuration,
  // drop the cross configurations.
  if (!HasUniqueOutputs(ccgs)) {
    ccgs.erase(ccgs.begin() + 1, ccgs.end());
  }

  return ccgs;
}

void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
                                                   cmGeneratorTarget* target)
{
  CustomCommandTargetMap::value_type v(cc, std::set<cmGeneratorTarget*>());
  std::pair<CustomCommandTargetMap::iterator, bool> ins =
    this->CustomCommandTargets.insert(v);
  if (ins.second) {
    this->CustomCommands.push_back(cc);
  }
  ins.first->second.insert(target);
}

void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements(
  const std::string& fileConfig)
{
  for (cmCustomCommand const* customCommand : this->CustomCommands) {
    auto i = this->CustomCommandTargets.find(customCommand);
    assert(i != this->CustomCommandTargets.end());

    this->WriteCustomCommandBuildStatement(i->first, i->second, fileConfig);
  }
}

std::string cmLocalNinjaGenerator::MakeCustomLauncher(
  cmCustomCommandGenerator const& ccg)
{
  cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");

  if (!cmNonempty(property_value)) {
    return std::string();
  }

  // Expand rule variables referenced in the given launcher command.
  cmRulePlaceholderExpander::RuleVariables vars;

  std::string output;
  const std::vector<std::string>& outputs = ccg.GetOutputs();
  if (!outputs.empty()) {
    output = outputs[0];
    if (ccg.GetWorkingDirectory().empty()) {
      output = this->MaybeRelativeToCurBinDir(output);
    }
    output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
  }
  vars.Output = output.c_str();

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

  std::string launcher = *property_value;
  rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
  if (!launcher.empty()) {
    launcher += " ";
  }

  return launcher;
}

void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config)
{
  if (cmProp prop_value =
        this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
    std::vector<std::string> cleanFiles;
    {
      cmExpandList(cmGeneratorExpression::Evaluate(*prop_value, this, config),
                   cleanFiles);
    }
    std::string const& binaryDir = this->GetCurrentBinaryDirectory();
    cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
    for (std::string const& cleanFile : cleanFiles) {
      // Support relative paths
      gg->AddAdditionalCleanFile(
        cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config);
    }
  }
}
