/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
  Copyright 2011 Nicolas Despres <nicolas.despres@gmail.com>

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmGlobalNinjaGenerator.h"

#include "cmAlgorithms.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmVersion.h"

#include <algorithm>
#include <assert.h>
#include <ctype.h>

const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
const char* cmGlobalNinjaGenerator::INDENT = "  ";

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::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 (std::string::const_iterator i = name.begin(); i != name.end(); ++i) {
    if (isalnum(*i) || *i == '_' || *i == '-') {
      encoded += *i;
    } else {
      char buf[16];
      sprintf(buf, ".%02x", static_cast<unsigned int>(*i));
      encoded += buf;
    }
  }
  return encoded;
}

static bool IsIdentChar(char c)
{
  return ('a' <= c && c <= 'z') ||
    ('+' <= c && c <= '9') || // +,-./ and numbers
    ('A' <= c && c <= 'Z') || (c == '_') || (c == '$') || (c == '\\') ||
    (c == ' ') || (c == ':');
}

std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string& ident,
                                                std::ostream& vars)
{
  if (std::find_if(ident.begin(), ident.end(),
                   std::not1(std::ptr_fun(IsIdentChar))) != ident.end()) {
    static unsigned VarNum = 0;
    std::ostringstream names;
    names << "ident" << VarNum++;
    vars << names.str() << " = " << ident << "\n";
    return "$" + names.str();
  } else {
    std::string result = ident;
    cmSystemTools::ReplaceString(result, " ", "$ ");
    cmSystemTools::ReplaceString(result, ":", "$:");
    return result;
  }
}

std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
  std::string result = lit;
  cmSystemTools::ReplaceString(result, "$", "$$");
  cmSystemTools::ReplaceString(result, "\n", "$\n");
  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
  return EncodeLiteral(result);
}

std::string cmGlobalNinjaGenerator::EncodeDepfileSpace(const std::string& path)
{
  std::string result = path;
  cmSystemTools::ReplaceString(result, " ", "\\ ");
  return result;
}

void cmGlobalNinjaGenerator::WriteBuild(
  std::ostream& os, const std::string& comment, const std::string& rule,
  const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps,
  const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps,
  const cmNinjaVars& variables, const std::string& rspfile, int cmdLineLimit,
  bool* usedResponseFile)
{
  // Make sure there is a rule.
  if (rule.empty()) {
    cmSystemTools::Error("No rule for WriteBuildStatement! called "
                         "with comment: ",
                         comment.c_str());
    return;
  }

  // Make sure there is at least one output file.
  if (outputs.empty()) {
    cmSystemTools::Error("No output files for WriteBuildStatement! called "
                         "with comment: ",
                         comment.c_str());
    return;
  }

  cmGlobalNinjaGenerator::WriteComment(os, comment);

  std::string arguments;

  // TODO: Better formatting for when there are multiple input/output files.

  // Write explicit dependencies.
  for (cmNinjaDeps::const_iterator i = explicitDeps.begin();
       i != explicitDeps.end(); ++i) {
    arguments += " " + EncodeIdent(EncodePath(*i), os);
  }

  // Write implicit dependencies.
  if (!implicitDeps.empty()) {
    arguments += " |";
    for (cmNinjaDeps::const_iterator i = implicitDeps.begin();
         i != implicitDeps.end(); ++i)
      arguments += " " + EncodeIdent(EncodePath(*i), os);
  }

  // Write order-only dependencies.
  if (!orderOnlyDeps.empty()) {
    arguments += " ||";
    for (cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
         i != orderOnlyDeps.end(); ++i)
      arguments += " " + EncodeIdent(EncodePath(*i), os);
  }

  arguments += "\n";

  std::string build;

  // Write outputs files.
  build += "build";
  for (cmNinjaDeps::const_iterator i = outputs.begin(); i != outputs.end();
       ++i) {
    build += " " + EncodeIdent(EncodePath(*i), os);
    if (this->ComputingUnknownDependencies) {
      this->CombinedBuildOutputs.insert(EncodePath(*i));
    }
  }
  build += ":";

  // Write the rule.
  build += " " + rule;

  // Write the variables bound to this build statement.
  std::ostringstream variable_assignments;
  for (cmNinjaVars::const_iterator i = variables.begin(); i != variables.end();
       ++i)
    cmGlobalNinjaGenerator::WriteVariable(variable_assignments, i->first,
                                          i->second, "", 1);

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

  os << buildstr << args << assignments;
}

void cmGlobalNinjaGenerator::WritePhonyBuild(
  std::ostream& os, const std::string& comment, const cmNinjaDeps& outputs,
  const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps,
  const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables)
{
  this->WriteBuild(os, comment, "phony", outputs, explicitDeps, implicitDeps,
                   orderOnlyDeps, variables);
}

void cmGlobalNinjaGenerator::AddCustomCommandRule()
{
  this->AddRule("CUSTOM_COMMAND", "$COMMAND", "$DESC",
                "Rule for running custom commands.",
                /*depfile*/ "",
                /*deptype*/ "",
                /*rspfile*/ "",
                /*rspcontent*/ "",
                /*restat*/ "", // bound on each build statement as needed
                /*generator*/ false);
}

void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
  const std::string& command, const std::string& description,
  const std::string& comment, bool uses_terminal, bool restat,
  const cmNinjaDeps& outputs, const cmNinjaDeps& deps,
  const cmNinjaDeps& orderOnly)
{
  std::string cmd = command;
#ifdef _WIN32
  if (cmd.empty())
    // TODO Shouldn't an empty command be handled by ninja?
    cmd = "cmd.exe /c";
#endif

  this->AddCustomCommandRule();

  cmNinjaVars vars;
  vars["COMMAND"] = cmd;
  vars["DESC"] = EncodeLiteral(description);
  if (restat) {
    vars["restat"] = "1";
  }
  if (uses_terminal && SupportsConsolePool()) {
    vars["pool"] = "console";
  }

  this->WriteBuild(*this->BuildFileStream, comment, "CUSTOM_COMMAND", outputs,
                   deps, cmNinjaDeps(), orderOnly, vars);

  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 (cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i) {
      this->CombinedCustomCommandExplicitDependencies.insert(EncodePath(*i));
    }
  }
}

void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
  cmLocalGenerator* lg = this->LocalGenerators[0];

  std::ostringstream cmd;
  cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
                                   cmOutputConverter::SHELL)
      << " -E copy $in $out";

  this->AddRule("COPY_OSX_CONTENT", cmd.str(), "Copying OS X Content $out",
                "Rule for copying OS X bundle content file.",
                /*depfile*/ "",
                /*deptype*/ "",
                /*rspfile*/ "",
                /*rspcontent*/ "",
                /*restat*/ "",
                /*generator*/ false);
}

void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
                                                     const std::string& output)
{
  this->AddMacOSXContentRule();

  cmNinjaDeps outputs;
  outputs.push_back(output);
  cmNinjaDeps deps;
  deps.push_back(input);
  cmNinjaVars vars;

  this->WriteBuild(*this->BuildFileStream, "", "COPY_OSX_CONTENT", outputs,
                   deps, cmNinjaDeps(), cmNinjaDeps(), cmNinjaVars());
}

void cmGlobalNinjaGenerator::WriteRule(
  std::ostream& os, const std::string& name, const std::string& command,
  const std::string& description, const std::string& comment,
  const std::string& depfile, const std::string& deptype,
  const std::string& rspfile, const std::string& rspcontent,
  const std::string& restat, bool generator)
{
  // Make sure the rule has a name.
  if (name.empty()) {
    cmSystemTools::Error("No name given for WriteRuleStatement! called "
                         "with comment: ",
                         comment.c_str());
    return;
  }

  // Make sure a command is given.
  if (command.empty()) {
    cmSystemTools::Error("No command given for WriteRuleStatement! called "
                         "with comment: ",
                         comment.c_str());
    return;
  }

  cmGlobalNinjaGenerator::WriteComment(os, comment);

  // Write the rule.
  os << "rule " << name << "\n";

  // Write the depfile if any.
  if (!depfile.empty()) {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "depfile = " << depfile << "\n";
  }

  // Write the deptype if any.
  if (!deptype.empty()) {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "deps = " << deptype << "\n";
  }

  // Write the command.
  cmGlobalNinjaGenerator::Indent(os, 1);
  os << "command = " << command << "\n";

  // Write the description if any.
  if (!description.empty()) {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "description = " << description << "\n";
  }

  if (!rspfile.empty()) {
    if (rspcontent.empty()) {
      cmSystemTools::Error("No rspfile_content given!", comment.c_str());
      return;
    }
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "rspfile = " << rspfile << "\n";
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "rspfile_content = " << rspcontent << "\n";
  }

  if (!restat.empty()) {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "restat = " << restat << "\n";
  }

  if (generator) {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "generator = 1\n";
  }

  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.c_str());
    return;
  }

  // Do not add a variable if the value is empty.
  std::string val = cmSystemTools::TrimWhitespace(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 (cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end();
       ++i)
    os << " " << *i;
  os << "\n";
}

cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm)
  : cmGlobalCommonGenerator(cm)
  , BuildFileStream(0)
  , RulesFileStream(0)
  , CompileCommandsStream(0)
  , Rules()
  , AllDependencies()
  , UsingGCCOnWindows(false)
  , ComputingUnknownDependencies(false)
  , PolicyCMP0058(cmPolicies::WARN)
{
#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.

cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf)
{
  return new cmLocalNinjaGenerator(this, mf);
}

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 << this->RequiredNinjaVersion() << ").";
    this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str());
    return;
  }
  this->OpenBuildFileStream();
  this->OpenRulesFileStream();

  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->BuildFileStream);
  this->WriteFolderTargets(*this->BuildFileStream);
  this->WriteUnknownExplicitDependencies(*this->BuildFileStream);
  this->WriteBuiltinTargets(*this->BuildFileStream);

  if (cmSystemTools::GetErrorOccuredFlag()) {
    this->RulesFileStream->setstate(std::ios_base::failbit);
    this->BuildFileStream->setstate(std::ios_base::failbit);
  }

  this->CloseCompileCommandsStream();
  this->CloseRulesFileStream();
  this->CloseBuildFileStream();
}

void cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
{
  this->cmGlobalGenerator::FindMakeProgram(mf);
  if (const char* ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
    this->NinjaCommand = ninjaCommand;
    std::vector<std::string> command;
    command.push_back(this->NinjaCommand);
    command.push_back("--version");
    std::string version;
    cmSystemTools::RunSingleCommand(command, &version, 0, 0, 0,
                                    cmSystemTools::OUTPUT_NONE);
    this->NinjaVersion = cmSystemTools::TrimWhitespace(version);
  }
}

void cmGlobalNinjaGenerator::EnableLanguage(
  std::vector<std::string> const& langs, cmMakefile* mf, bool optional)
{
  if (std::find(langs.begin(), langs.end(), "Fortran") != langs.end()) {
    cmSystemTools::Error("The Ninja generator does not support Fortran yet.");
  }
  this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
  for (std::vector<std::string>::const_iterator l = langs.begin();
       l != langs.end(); ++l) {
    if (*l == "NONE") {
      continue;
    }
    this->ResolveLanguageCompiler(*l, mf, optional);
  }
#ifdef _WIN32
  if (mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
      strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 ||
      strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 ||
      strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "GNU") == 0 ||
      strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "GNU") == 0) {
    this->UsingGCCOnWindows = true;
  }
#endif
}

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

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

  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
                     makeOptions.end());
  if (!targetName.empty()) {
    if (targetName == "clean") {
      makeCommand.push_back("-t");
      makeCommand.push_back("clean");
    } else {
      makeCommand.push_back(targetName);
    }
  }
}

// Non-virtual public methods.

void cmGlobalNinjaGenerator::AddRule(
  const std::string& name, const std::string& command,
  const std::string& description, const std::string& comment,
  const std::string& depfile, const std::string& deptype,
  const std::string& rspfile, const std::string& rspcontent,
  const std::string& restat, bool generator)
{
  // Do not add the same rule twice.
  if (this->HasRule(name)) {
    return;
  }

  this->Rules.insert(name);
  cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, name, command,
                                    description, comment, depfile, deptype,
                                    rspfile, rspcontent, restat, generator);

  this->RuleCmdLength[name] = (int)command.size();
}

bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
{
  RulesSetType::const_iterator rule = this->Rules.find(name);
  return (rule != 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;
  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
  dir += "/";
  dir += gt->LocalGenerator->GetTargetDirectory(gt);
  dir += "/";
  gt->ObjectDirectory = dir;
}

// Private methods

void cmGlobalNinjaGenerator::OpenBuildFileStream()
{
  // Compute Ninja's build file path.
  std::string buildFilePath =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  buildFilePath += "/";
  buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;

  // Get a stream where to generate things.
  if (!this->BuildFileStream) {
    this->BuildFileStream = new cmGeneratedFileStream(buildFilePath.c_str());
    if (!this->BuildFileStream) {
      // An error message is generated by the constructor if it cannot
      // open the file.
      return;
    }
  }

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

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

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

void cmGlobalNinjaGenerator::OpenRulesFileStream()
{
  // Compute Ninja's build file path.
  std::string rulesFilePath =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  rulesFilePath += "/";
  rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;

  // Get a stream where to generate things.
  if (!this->RulesFileStream) {
    this->RulesFileStream = new cmGeneratedFileStream(rulesFilePath.c_str());
    if (!this->RulesFileStream) {
      // An error message is generated by the constructor if it cannot
      // open the file.
      return;
    }
  }

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

  // 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 */
}

void cmGlobalNinjaGenerator::CloseRulesFileStream()
{
  if (this->RulesFileStream) {
    delete this->RulesFileStream;
    this->RulesFileStream = 0;
  } 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[path.size() - 1];
#ifdef _WIN32
  if (last != '\\') {
    path += '\\';
  }
#else
  if (last != '/') {
    path += '/';
  }
#endif
}

std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path)
{
  cmLocalNinjaGenerator* ng =
    static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
  std::string convPath = ng->Convert(path, cmOutputConverter::HOME_OUTPUT);
  convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
  std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
  return convPath;
}

std::string cmGlobalNinjaGenerator::ConvertToNinjaFolderRule(
  const std::string& path)
{
  cmLocalNinjaGenerator* ng =
    static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
  std::string convPath = ng->Convert(path + "/all", cmOutputConverter::HOME);
  convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
  std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
  return convPath;
}

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";

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

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

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

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

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::AddDependencyToAll(cmGeneratorTarget* target)
{
  this->AppendTargetOutputs(target, this->AllDependencies);
}

void cmGlobalNinjaGenerator::AddDependencyToAll(const std::string& input)
{
  this->AllDependencies.push_back(input);
}

void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
  for (std::map<std::string, std::set<std::string> >::iterator i =
         this->AssumedSourceDependencies.begin();
       i != this->AssumedSourceDependencies.end(); ++i) {
    cmNinjaDeps deps;
    std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
    WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
                            "Assume dependencies for generated source file.",
                            /*uses_terminal*/ false,
                            /*restat*/ true, cmNinjaDeps(1, i->first), deps);
  }
}

void cmGlobalNinjaGenerator::AppendTargetOutputs(
  cmGeneratorTarget const* target, cmNinjaDeps& outputs)
{
  std::string configName =
    target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");

  // 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 cmState::EXECUTABLE:
    case cmState::SHARED_LIBRARY:
    case cmState::STATIC_LIBRARY:
    case cmState::MODULE_LIBRARY: {
      outputs.push_back(this->ConvertToNinjaPath(
        target->GetFullPath(configName, false, realname)));
      break;
    }
    case cmState::OBJECT_LIBRARY:
    case cmState::UTILITY: {
      std::string path =
        target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
        std::string("/") + target->GetName();
      outputs.push_back(this->ConvertToNinjaPath(path));
      break;
    }

    case cmState::GLOBAL_TARGET:
      // Always use the target in HOME instead of an unused duplicate in a
      // subdirectory.
      outputs.push_back(this->NinjaOutputPath(target->GetName()));
      break;

    default:
      return;
  }
}

void cmGlobalNinjaGenerator::AppendTargetDepends(
  cmGeneratorTarget const* target, cmNinjaDeps& outputs)
{
  if (target->GetType() == cmState::GLOBAL_TARGET) {
    // Global targets only depend on other utilities, which may not appear in
    // the TargetDepends set (e.g. "all").
    std::set<std::string> const& utils = target->GetUtilities();
    std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
  } else {
    cmNinjaDeps outs;
    cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);
    for (cmTargetDependSet::const_iterator i = targetDeps.begin();
         i != targetDeps.end(); ++i) {
      if ((*i)->GetType() == cmState::INTERFACE_LIBRARY) {
        continue;
      }
      this->AppendTargetOutputs(*i, outs);
    }
    std::sort(outs.begin(), outs.end());
    outputs.insert(outputs.end(), outs.begin(), outs.end());
  }
}

void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
                                            cmGeneratorTarget* target)
{
  std::string buildAlias = this->NinjaOutputPath(alias);
  cmNinjaDeps outputs;
  this->AppendTargetOutputs(target, outputs);
  // Mark the target's outputs as ambiguous to ensure that no other target uses
  // the output as an alias.
  for (cmNinjaDeps::iterator i = outputs.begin(); i != outputs.end(); ++i)
    TargetAliases[*i] = 0;

  // Insert the alias into the map.  If the alias was already present in the
  // map and referred to another target, mark it as ambiguous.
  std::pair<TargetAliasMap::iterator, bool> newAlias =
    TargetAliases.insert(std::make_pair(buildAlias, target));
  if (newAlias.second && newAlias.first->second != target)
    newAlias.first->second = 0;
}

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

  for (TargetAliasMap::const_iterator i = TargetAliases.begin();
       i != TargetAliases.end(); ++i) {
    // Don't write ambiguous aliases.
    if (!i->second)
      continue;

    cmNinjaDeps deps;
    this->AppendTargetOutputs(i->second, deps);

    this->WritePhonyBuild(os, "", cmNinjaDeps(1, i->first), deps);
  }
}

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

  std::map<std::string, cmNinjaDeps> targetsPerFolder;
  for (std::vector<cmLocalGenerator*>::const_iterator lgi =
         this->LocalGenerators.begin();
       lgi != this->LocalGenerators.end(); ++lgi) {
    cmLocalGenerator const* lg = *lgi;
    const std::string currentSourceFolder(
      lg->GetStateSnapshot().GetDirectory().GetCurrentSource());
    // The directory-level rule should depend on the target-level rules
    // for all targets in the directory.
    targetsPerFolder[currentSourceFolder] = cmNinjaDeps();
    for (std::vector<cmGeneratorTarget*>::const_iterator ti =
           lg->GetGeneratorTargets().begin();
         ti != lg->GetGeneratorTargets().end(); ++ti) {
      cmGeneratorTarget const* gt = *ti;
      cmState::TargetType const type = gt->GetType();
      if ((type == cmState::EXECUTABLE || type == cmState::STATIC_LIBRARY ||
           type == cmState::SHARED_LIBRARY ||
           type == cmState::MODULE_LIBRARY ||
           type == cmState::OBJECT_LIBRARY || type == cmState::UTILITY) &&
          !gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
        targetsPerFolder[currentSourceFolder].push_back(gt->GetName());
      }
    }

    // The directory-level rule should depend on the directory-level
    // rules of the subdirectories.
    std::vector<cmState::Snapshot> const& children =
      lg->GetStateSnapshot().GetChildren();
    for (std::vector<cmState::Snapshot>::const_iterator stateIt =
           children.begin();
         stateIt != children.end(); ++stateIt) {
      targetsPerFolder[currentSourceFolder].push_back(
        this->ConvertToNinjaFolderRule(
          stateIt->GetDirectory().GetCurrentSource()));
    }
  }

  std::string const rootSourceDir =
    this->LocalGenerators[0]->GetSourceDirectory();
  for (std::map<std::string, cmNinjaDeps>::const_iterator it =
         targetsPerFolder.begin();
       it != targetsPerFolder.end(); ++it) {
    cmGlobalNinjaGenerator::WriteDivider(os);
    std::string const& currentSourceDir = it->first;

    // Do not generate a rule for the root source dir.
    if (rootSourceDir.length() >= currentSourceDir.length()) {
      continue;
    }

    std::string const comment = "Folder: " + currentSourceDir;
    cmNinjaDeps output(1);
    output.push_back(this->ConvertToNinjaFolderRule(currentSourceDir));

    this->WritePhonyBuild(os, comment, output, it->second);
  }
}

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 (std::vector<cmLocalGenerator*>::const_iterator i =
         this->LocalGenerators.begin();
       i != this->LocalGenerators.end(); ++i) {
    // 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
    const std::vector<std::string>& files =
      (*i)->GetMakefile()->GetOutputFiles();
    typedef std::vector<std::string>::const_iterator vect_it;
    for (vect_it j = files.begin(); j != files.end(); ++j) {
      knownDependencies.insert(this->ConvertToNinjaPath(*j));
    }
    // get list files which are implicit dependencies as well and will be phony
    // for rebuild manifest
    std::vector<std::string> const& lf = (*i)->GetMakefile()->GetListFiles();
    typedef std::vector<std::string>::const_iterator vect_it;
    for (vect_it j = lf.begin(); j != lf.end(); ++j) {
      knownDependencies.insert(this->ConvertToNinjaPath(*j));
    }
    std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
      (*i)->GetMakefile()->GetEvaluationFiles();
    for (std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator li =
           ef.begin();
         li != ef.end(); ++li) {
      // get all the files created by generator expressions and convert them
      // to ninja paths
      std::vector<std::string> evaluationFiles = (*li)->GetFiles();
      for (vect_it j = evaluationFiles.begin(); j != evaluationFiles.end();
           ++j) {
        knownDependencies.insert(this->ConvertToNinjaPath(*j));
      }
    }
  }
  knownDependencies.insert(this->CMakeCacheFile);

  for (TargetAliasMap::const_iterator i = this->TargetAliases.begin();
       i != this->TargetAliases.end(); ++i) {
    knownDependencies.insert(this->ConvertToNinjaPath(i->first));
  }

  // remove all source files we know will exist.
  typedef std::map<std::string, std::set<std::string> >::const_iterator map_it;
  for (map_it i = this->AssumedSourceDependencies.begin();
       i != this->AssumedSourceDependencies.end(); ++i) {
    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::string const rootBuildDirectory =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  bool const inSourceBuild =
    (rootBuildDirectory == this->GetCMakeInstance()->GetHomeDirectory());
  std::vector<std::string> warnExplicitDepends;
  for (std::vector<std::string>::const_iterator i =
         unknownExplicitDepends.begin();
       i != unknownExplicitDepends.end(); ++i) {
    // verify the file is in the build directory
    std::string const absDepPath =
      cmSystemTools::CollapseFullPath(*i, rootBuildDirectory.c_str());
    bool const inBuildDir =
      cmSystemTools::IsSubDirectory(absDepPath, rootBuildDirectory);
    if (inBuildDir) {
      cmNinjaDeps deps(1, *i);
      this->WritePhonyBuild(os, "", deps, cmNinjaDeps());
      if (this->PolicyCMP0058 == cmPolicies::WARN && !inSourceBuild &&
          warnExplicitDepends.size() < 10) {
        warnExplicitDepends.push_back(*i);
      }
    }
  }

  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(cmake::AUTHOR_WARNING, w.str());
  }
}

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

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

void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
{
  cmNinjaDeps outputs;
  outputs.push_back(this->TargetAll);

  this->WritePhonyBuild(os, "The main all target.", outputs,
                        this->AllDependencies);

  if (!this->HasOutputPathPrefix()) {
    cmGlobalNinjaGenerator::WriteDefault(os, outputs,
                                         "Make the all target the default.");
  }
}

void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
  cmLocalGenerator* lg = this->LocalGenerators[0];

  std::ostringstream cmd;
  cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
                                   cmOutputConverter::SHELL)
      << " -H"
      << lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
                                   cmOutputConverter::SHELL)
      << " -B"
      << lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
                                   cmOutputConverter::SHELL);
  WriteRule(*this->RulesFileStream, "RERUN_CMAKE", cmd.str(),
            "Re-running CMake...", "Rule for re-running cmake.",
            /*depfile=*/"",
            /*deptype=*/"",
            /*rspfile=*/"",
            /*rspcontent*/ "",
            /*restat=*/"",
            /*generator=*/true);

  cmNinjaDeps implicitDeps;
  for (std::vector<cmLocalGenerator*>::const_iterator i =
         this->LocalGenerators.begin();
       i != this->LocalGenerators.end(); ++i) {
    std::vector<std::string> const& lf = (*i)->GetMakefile()->GetListFiles();
    for (std::vector<std::string>::const_iterator fi = lf.begin();
         fi != lf.end(); ++fi) {
      implicitDeps.push_back(this->ConvertToNinjaPath(*fi));
    }
  }
  implicitDeps.push_back(this->CMakeCacheFile);

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

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

  std::string const ninjaBuildFile = this->NinjaOutputPath(NINJA_BUILD_FILE);
  this->WriteBuild(os, "Re-run CMake if any of its inputs changed.",
                   "RERUN_CMAKE",
                   /*outputs=*/cmNinjaDeps(1, ninjaBuildFile),
                   /*explicitDeps=*/cmNinjaDeps(), implicitDeps,
                   /*orderOnlyDeps=*/cmNinjaDeps(), variables);

  this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
                        implicitDeps, cmNinjaDeps());
}

std::string cmGlobalNinjaGenerator::ninjaCmd() const
{
  cmLocalGenerator* lgen = this->LocalGenerators[0];
  if (lgen) {
    return lgen->ConvertToOutputFormat(this->NinjaCommand,
                                       cmOutputConverter::SHELL);
  }
  return "ninja";
}

bool cmGlobalNinjaGenerator::SupportsConsolePool() const
{
  return cmSystemTools::VersionCompare(
           cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
           RequiredNinjaVersionForConsolePool().c_str()) == false;
}

void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
  WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean",
            "Cleaning all built files...",
            "Rule for cleaning all built files.",
            /*depfile=*/"",
            /*deptype=*/"",
            /*rspfile=*/"",
            /*rspcontent*/ "",
            /*restat=*/"",
            /*generator=*/false);
  WriteBuild(os, "Clean all the built files.", "CLEAN",
             /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("clean")),
             /*explicitDeps=*/cmNinjaDeps(),
             /*implicitDeps=*/cmNinjaDeps(),
             /*orderOnlyDeps=*/cmNinjaDeps(),
             /*variables=*/cmNinjaVars());
}

void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
  WriteRule(*this->RulesFileStream, "HELP", ninjaCmd() + " -t targets",
            "All primary targets available:",
            "Rule for printing all primary targets available.",
            /*depfile=*/"",
            /*deptype=*/"",
            /*rspfile=*/"",
            /*rspcontent*/ "",
            /*restat=*/"",
            /*generator=*/false);
  WriteBuild(os, "Print all primary targets available.", "HELP",
             /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("help")),
             /*explicitDeps=*/cmNinjaDeps(),
             /*implicitDeps=*/cmNinjaDeps(),
             /*orderOnlyDeps=*/cmNinjaDeps(),
             /*variables=*/cmNinjaVars());
}

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)
{
  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);
}
