/*============================================================================
  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 "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmVersion.h"

#include <algorithm>

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

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;
    cmOStringStream 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(UsingMinGW)
    cmSystemTools::ReplaceString(result, "\\", "/");
  else
    cmSystemTools::ReplaceString(result, "/", "\\");
#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)
{
  // 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);

  cmOStringStream 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);

    //we need to track every dependency that comes in, since we are trying
    //to find dependencies that are side effects of build commands
    //
    this->CombinedBuildExplicitDependencies.insert( EncodePath(*i) );
    }

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

  cmOStringStream build;

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

  // Write the rule.
  build << " " << rule;

  // Write the variables bound to this build statement.
  cmOStringStream 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.str();
  std::string assignments = variable_assignments.str();
  const std::string args = arguments.str();
  if (cmdLineLimit > 0
      && args.size() + buildstr.size() + assignments.size()
                                                    > (size_t) cmdLineLimit) {
    buildstr += "_RSP_FILE";
    variable_assignments.clear();
    cmGlobalNinjaGenerator::WriteVariable(variable_assignments,
                                          "RSP_FILE", rspfile, "", 1);
    assignments += variable_assignments.str();
  }

  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*/ true,
                /*generator*/ false);
}

void
cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
                                                const std::string& description,
                                                const std::string& comment,
                                                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);

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

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

  cmOStringStream cmd;
  cmd << lg->ConvertToOutputFormat(
           mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
           cmLocalGenerator::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*/ false,
                /*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,
                                       bool 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)
    {
    cmGlobalNinjaGenerator::Indent(os, 1);
    os << "restat = 1\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()
  : cmGlobalGenerator()
  , BuildFileStream(0)
  , RulesFileStream(0)
  , CompileCommandsStream(0)
  , Rules()
  , AllDependencies()
{
  // // Ninja is not ported to non-Unix OS yet.
  // this->ForceUnixPaths = true;
  this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
}


//----------------------------------------------------------------------------
// Virtual public methods.

cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator()
{
  cmLocalGenerator* lg = new cmLocalNinjaGenerator;
  lg->SetGlobalGenerator(this);
  return lg;
}

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

// Implemented in all cmGlobaleGenerator sub-classes.
// Used in:
//   Source/cmLocalGenerator.cxx
//   Source/cmake.cxx
void cmGlobalNinjaGenerator::Generate()
{
  this->OpenBuildFileStream();
  this->OpenRulesFileStream();

  this->cmGlobalGenerator::Generate();

  this->WriteAssumedSourceDependencies();
  this->WriteTargetAliases(*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();
}

// Implemented in all cmGlobaleGenerator sub-classes.
// Used in:
//   Source/cmMakefile.cxx:
void cmGlobalNinjaGenerator
::EnableLanguage(std::vector<std::string>const& langs,
                 cmMakefile* makefile,
                 bool optional)
{
  if (makefile->IsOn("CMAKE_COMPILER_IS_MINGW"))
    {
    UsingMinGW = true;
    this->EnableMinGWLanguage(makefile);
    }
  if (std::find(langs.begin(), langs.end(), "Fortran") != langs.end())
    {
    cmSystemTools::Error("The Ninja generator does not support Fortran yet.");
    }
  this->cmGlobalGenerator::EnableLanguage(langs, makefile, optional);
}

bool cmGlobalNinjaGenerator::UsingMinGW = false;

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

  makeCommand.insert(makeCommand.end(),
                     makeOptions.begin(), makeOptions.end());
  if(targetName && *targetName)
    {
    if(strcmp(targetName, "clean") == 0)
      {
      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,
                                     bool 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();
}

// TODO: Refactor to combine with cmGlobalUnixMakefileGenerator3 impl.
void cmGlobalNinjaGenerator::ComputeTargetObjects(cmGeneratorTarget* gt) const
{
  cmTarget* target = gt->Target;

  // Compute full path to object file directory for this target.
  std::string dir_max;
  dir_max += gt->Makefile->GetCurrentOutputDirectory();
  dir_max += "/";
  dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
  dir_max += "/";
  gt->ObjectDirectory = dir_max;

  std::vector<cmSourceFile*> objectSources;
  gt->GetObjectSources(objectSources);
  // Compute the name of each object file.
  for(std::vector<cmSourceFile*>::iterator
        si = objectSources.begin();
      si != objectSources.end(); ++si)
    {
    cmSourceFile* sf = *si;
    std::string objectName = gt->LocalGenerator
      ->GetObjectFileNameWithoutTarget(*sf, dir_max);
    gt->AddObject(sf, objectName);
    }
}

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

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

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.c_str(),
      this->GetCMakeInstance()->GetHomeOutputDirectory());
    }


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

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(cmTarget* 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.",
                            cmNinjaDeps(1, i->first), deps);
  }
}

void
cmGlobalNinjaGenerator
::AppendTargetOutputs(cmTarget const* target, cmNinjaDeps& outputs)
{
  const char* configName =
    target->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE");
  cmLocalNinjaGenerator *ng =
    static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);

  // 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 cmTarget::EXECUTABLE:
  case cmTarget::SHARED_LIBRARY:
  case cmTarget::STATIC_LIBRARY:
  case cmTarget::MODULE_LIBRARY:
    outputs.push_back(ng->ConvertToNinjaPath(
      target->GetFullPath(configName, false, realname).c_str()));
    break;

  case cmTarget::OBJECT_LIBRARY:
  case cmTarget::UTILITY: {
    std::string path = ng->ConvertToNinjaPath(
      target->GetMakefile()->GetStartOutputDirectory());
    if (path.empty() || path == ".")
      outputs.push_back(target->GetName());
    else {
      path += "/";
      path += target->GetName();
      outputs.push_back(path);
    }
    break;
  }

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

  default:
    return;
  }
}

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

void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
                                            cmTarget* target) {
  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(alias, 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::WriteUnknownExplicitDependencies(std::ostream& os)
{
  //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);
  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";

  //get the list of files that cmake itself has generated as a
  //product of configuration.
  cmLocalNinjaGenerator *ng =
    static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);

  std::set<std::string> knownDependencies;
  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( ng->ConvertToNinjaPath( j->c_str() ) );
      }
    //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( ng->ConvertToNinjaPath( j->c_str() ) );
      }
    }
  knownDependencies.insert( "CMakeCache.txt" );

  for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
      li = this->EvaluationFiles.begin();
      li != this->EvaluationFiles.end();
      ++li)
    {
    //get all the files created by generator expressions and convert them
    //to ninja paths
    std::vector<std::string> files = (*li)->GetFiles();
    typedef std::vector<std::string>::const_iterator vect_it;
    for(vect_it j = files.begin(); j != files.end(); ++j)
      {
      knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) );
      }
    }

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

  //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( ng->ConvertToNinjaPath(i->first.c_str()) );
    }

  //insert outputs from all WirteBuild commands
  for(std::set<std::string>::iterator i = this->CombinedBuildOutputs.begin();
      i != this->CombinedBuildOutputs.end(); ++i)
    {
    //these paths have already be encoded when added to CombinedBuildOutputs
    knownDependencies.insert(*i);
    }

  //after we have combined the data into knownDependencies we have no need
  //to keep this data around
  this->CombinedBuildOutputs.clear();

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

  std::vector<std::string> unkownExplicitDepends;
  this->CombinedBuildExplicitDependencies.erase("all");

  std::set_difference(this->CombinedBuildExplicitDependencies.begin(),
                      this->CombinedBuildExplicitDependencies.end(),
                      knownDependencies.begin(),
                      knownDependencies.end(),
                      std::back_inserter(unkownExplicitDepends));


  std::string const rootBuildDirectory =
      this->GetCMakeInstance()->GetHomeOutputDirectory();
  for (std::vector<std::string>::const_iterator
       i = unkownExplicitDepends.begin();
       i != unkownExplicitDepends.end();
       ++i)
    {
    //verify the file is in the build directory
    std::string const absDepPath = cmSystemTools::CollapseFullPath(
                                     i->c_str(), rootBuildDirectory.c_str());
    bool const inBuildDir = cmSystemTools::IsSubDirectory(absDepPath.c_str(),
                                                  rootBuildDirectory.c_str());
    if(inBuildDir)
      {
      cmNinjaDeps deps(1,*i);
      this->WritePhonyBuild(os,
                            "",
                            deps,
                            deps);
      }
   }
}

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("all");

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

  cmGlobalNinjaGenerator::WriteDefault(os,
                                       outputs,
                                       "Make the all target the default.");
}

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

  cmOStringStream cmd;
  cmd << lg->ConvertToOutputFormat(
           mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
           cmLocalGenerator::SHELL)
      << " -H"
      << lg->ConvertToOutputFormat(mfRoot->GetHomeDirectory(),
                                   cmLocalGenerator::SHELL)
      << " -B"
      << lg->ConvertToOutputFormat(mfRoot->GetHomeOutputDirectory(),
                                   cmLocalGenerator::SHELL);
  WriteRule(*this->RulesFileStream,
            "RERUN_CMAKE",
            cmd.str(),
            "Re-running CMake...",
            "Rule for re-running cmake.",
            /*depfile=*/ "",
            /*deptype=*/ "",
            /*rspfile=*/ "",
            /*rspcontent*/ "",
            /*restat=*/ false,
            /*generator=*/ true);

  cmLocalNinjaGenerator *ng = static_cast<cmLocalNinjaGenerator *>(lg);

  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(ng->ConvertToNinjaPath(fi->c_str()));
      }
    }
  implicitDeps.push_back("CMakeCache.txt");

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

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

  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(
             lgen->GetMakefile()->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"),
                                    cmLocalGenerator::SHELL);
  }
  return "ninja";
}

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

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