[Cmake-commits] CMake branch, next, updated. v2.8.7-2449-g05c0349

Peter Collingbourne peter at pcc.me.uk
Thu Feb 2 18:44:54 EST 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  05c034961a45091e24303cf7f36834361f2b0909 (commit)
       via  e2db5eb7de9e47cb5b50dec3822bc4d771ba35df (commit)
       via  7eb8d9036c73784f14da9d8381023c1e26df1275 (commit)
       via  4468edf12b0b87e32768fcdce7abd30afddcad7b (commit)
       via  2cd36550b073fd4f559f7edc5a5170af534f1068 (commit)
       via  e8584401852a871b6cda57e570b7bb04b6dacf74 (commit)
      from  565d4c34e67f8bdb4b5730b05d835b63a0417e08 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=05c034961a45091e24303cf7f36834361f2b0909
commit 05c034961a45091e24303cf7f36834361f2b0909
Merge: 565d4c3 e2db5eb
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Thu Feb 2 18:44:38 2012 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Feb 2 18:44:38 2012 -0500

    Merge topic 'ninja-generator' into next
    
    e2db5eb Add the Ninja generator
    7eb8d90 Provide dependency file flags to generator
    4468edf Add executable with exports flag support to cmLocalGenerator::GetTargetFlags
    2cd3655 Add cmSystemTools::TrimWhitespace function
    e858440 KWSys Nightly Date Stamp


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2db5eb7de9e47cb5b50dec3822bc4d771ba35df
commit e2db5eb7de9e47cb5b50dec3822bc4d771ba35df
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Fri Nov 11 05:00:49 2011 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Thu Feb 2 23:40:21 2012 +0000

    Add the Ninja generator

diff --git a/Modules/CMakeNinjaFindMake.cmake b/Modules/CMakeNinjaFindMake.cmake
new file mode 100644
index 0000000..f15c3e0
--- /dev/null
+++ b/Modules/CMakeNinjaFindMake.cmake
@@ -0,0 +1,17 @@
+
+#=============================================================================
+# Copyright 2011 Kitware, Inc.
+#
+# 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+FIND_PROGRAM(CMAKE_MAKE_PROGRAM ninja
+  DOC "Program used to build from build.ninja files.")
+MARK_AS_ADVANCED(CMAKE_MAKE_PROGRAM)
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index fb55d3b..b6fe190 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -833,6 +833,12 @@ function(ExternalProject_Add_StepTargets name)
   foreach(step ${steps})
     add_custom_target(${name}-${step}
       DEPENDS ${stamp_dir}${cfgdir}/${name}-${step})
+
+    # Depend on other external projects (target-level).
+    get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
+    foreach(arg IN LISTS deps)
+      add_dependencies(${name}-${step} ${arg})
+    endforeach()
   endforeach()
 endfunction(ExternalProject_Add_StepTargets)
 
@@ -1451,9 +1457,18 @@ function(ExternalProject_Add name)
   # depends on the 'done' mark so that it rebuilds when this project
   # rebuilds.  It is important that 'done' is not the output of any
   # custom command so that CMake does not propagate build rules to
-  # other external project targets.
+  # other external project targets, which may cause problems during
+  # parallel builds.  However, the Ninja generator needs to see the entire
+  # dependency graph, and can cope with custom commands belonging to
+  # multiple targets, so we add the 'done' mark as an output for Ninja only.
+  set(complete_outputs ${cmf_dir}${cfgdir}/${name}-complete)
+  if(${CMAKE_GENERATOR} MATCHES "Ninja")
+    set(complete_outputs
+        ${complete_outputs} ${stamp_dir}${cfgdir}/${name}-done)
+  endif()
+
   add_custom_command(
-    OUTPUT ${cmf_dir}${cfgdir}/${name}-complete
+    OUTPUT ${complete_outputs}
     COMMENT "Completed '${name}'"
     COMMAND ${CMAKE_COMMAND} -E make_directory ${cmf_dir}${cfgdir}
     COMMAND ${CMAKE_COMMAND} -E touch ${cmf_dir}${cfgdir}/${name}-complete
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index b5115b7..7ddabbd 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,6 +353,24 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
+# Ninja only works on UNIX.
+IF(UNIX)
+  SET(SRCS ${SRCS}
+    cmGlobalNinjaGenerator.cxx
+    cmGlobalNinjaGenerator.h
+    cmNinjaTypes.h
+    cmLocalNinjaGenerator.cxx
+    cmLocalNinjaGenerator.h
+    cmNinjaTargetGenerator.cxx
+    cmNinjaTargetGenerator.h
+    cmNinjaNormalTargetGenerator.cxx
+    cmNinjaNormalTargetGenerator.h
+    cmNinjaUtilityTargetGenerator.cxx
+    cmNinjaUtilityTargetGenerator.h
+    )
+  ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
+ENDIF(UNIX)
+
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})
 TARGET_LINK_LIBRARIES(CMakeLib cmsys
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
new file mode 100644
index 0000000..24900c5
--- /dev/null
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -0,0 +1,774 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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 "cmLocalNinjaGenerator.h"
+#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmVersion.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 replace = comment;
+  std::string::size_type lpos = 0;
+  std::string::size_type rpos;
+  while((rpos = replace.find('\n', lpos)) != std::string::npos)
+    {
+    os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
+    lpos = rpos + 1;
+    }
+  os << "# " << replace.substr(lpos) << "\n";
+}
+
+static bool IsIdentChar(char c)
+{
+  return
+    ('a' <= c && c <= 'z') ||
+    ('+' <= c && c <= '9') ||  // +,-./ and numbers
+    ('A' <= c && c <= 'Z') ||
+    (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 {
+    return ident;
+  }
+}
+
+std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
+{
+  std::string result = lit;
+  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)
+{
+  // 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::ostringstream builds;
+
+  // TODO: Better formatting for when there are multiple input/output files.
+
+  // Write outputs files.
+  builds << "build";
+  for(cmNinjaDeps::const_iterator i = outputs.begin();
+      i != outputs.end();
+      ++i)
+    builds << " " << EncodeIdent(*i, os);
+  builds << ":";
+
+  // Write the rule.
+  builds << " " << rule;
+
+  // Write explicit dependencies.
+  for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
+      i != explicitDeps.end();
+      ++i)
+    builds  << " " << EncodeIdent(*i, os);
+
+  // Write implicit dependencies.
+  if(!implicitDeps.empty())
+    {
+    builds << " |";
+    for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
+        i != implicitDeps.end();
+        ++i)
+      builds  << " " << EncodeIdent(*i, os);
+    }
+
+  // Write order-only dependencies.
+  if(!orderOnlyDeps.empty())
+    {
+    builds << " ||";
+    for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
+        i != orderOnlyDeps.end();
+        ++i)
+      builds  << " " << EncodeIdent(*i, os);
+    }
+
+  builds << "\n";
+
+  os << builds.str();
+
+  // Write the variables bound to this build statement.
+  for(cmNinjaVars::const_iterator i = variables.begin();
+      i != variables.end();
+      ++i)
+    cmGlobalNinjaGenerator::WriteVariable(os, i->first, i->second, "", 1);
+}
+
+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)
+{
+  cmGlobalNinjaGenerator::WriteBuild(os,
+                                     comment,
+                                     "phony",
+                                     outputs,
+                                     explicitDeps,
+                                     implicitDeps,
+                                     orderOnlyDeps,
+                                     variables);
+}
+
+void cmGlobalNinjaGenerator::AddCustomCommandRule()
+{
+  this->AddRule("CUSTOM_COMMAND",
+                "$COMMAND",
+                "$DESC",
+                "Rule for running custom commands.",
+                /*depfile*/ "",
+                /*restat*/ true);
+}
+
+void
+cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
+                                                const std::string& description,
+                                                const std::string& comment,
+                                                const cmNinjaDeps& outputs,
+                                                const cmNinjaDeps& deps,
+                                              const cmNinjaDeps& orderOnlyDeps)
+{
+  this->AddCustomCommandRule();
+
+  cmNinjaVars vars;
+  vars["COMMAND"] = command;
+  vars["DESC"] = EncodeLiteral(description);
+
+  cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
+                                     comment,
+                                     "CUSTOM_COMMAND",
+                                     outputs,
+                                     deps,
+                                     cmNinjaDeps(),
+                                     orderOnlyDeps,
+                                     vars);
+}
+
+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,
+                                       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 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(restat)
+    {
+    cmGlobalNinjaGenerator::Indent(os, 1);
+    os << "restat = 1\n";
+    }
+
+  if(generator)
+    {
+    cmGlobalNinjaGenerator::Indent(os, 1);
+    os << "generator = 1\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)
+  , 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) const
+{
+  entry.Name = this->GetName();
+  entry.Brief = "Generates build.ninja files (experimental).";
+  entry.Full =
+    "A build.ninja file is generated into the build tree. Recent "
+    "versions of the ninja program can build the project through the "
+    "\"all\" target.  An \"install\" target is also provided.";
+}
+
+// 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->BuildFileStream);
+  this->WriteTargetAliases(*this->BuildFileStream);
+  this->WriteBuiltinTargets(*this->BuildFileStream);
+
+  this->CloseRulesFileStream();
+  this->CloseBuildFileStream();
+}
+
+// Implemented in all cmGlobaleGenerator sub-classes.
+// Used in:
+//   Source/cmMakefile.cxx:
+void cmGlobalNinjaGenerator
+::EnableLanguage(std::vector<std::string>const& languages,
+                 cmMakefile *mf,
+                 bool optional)
+{
+  this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
+  std::string path;
+  for(std::vector<std::string>::const_iterator l = languages.begin();
+      l != languages.end(); ++l)
+    {
+    if(*l == "NONE")
+      {
+      continue;
+      }
+    if(*l == "Fortran")
+      {
+      std::string message = "The \"";
+      message += this->GetName();
+      message += "\" generator does not support the language \"";
+      message += *l;
+      message += "\" yet.";
+      cmSystemTools::Error(message.c_str());
+      }
+    this->ResolveLanguageCompiler(*l, mf, optional);
+    }
+}
+
+// Implemented by:
+//   cmGlobalUnixMakefileGenerator3
+//   cmGlobalVisualStudio10Generator
+//   cmGlobalVisualStudio6Generator
+//   cmGlobalVisualStudio7Generator
+//   cmGlobalXCodeGenerator
+// Called by:
+//   cmGlobalGenerator::Build()
+std::string cmGlobalNinjaGenerator
+::GenerateBuildCommand(const char* makeProgram,
+                       const char* projectName,
+                       const char* additionalOptions,
+                       const char* targetName,
+                       const char* config,
+                       bool ignoreErrors,
+                       bool fast)
+{
+  // Project name and config are not used yet.
+  (void)projectName;
+  (void)config;
+  // Ninja does not have -i equivalent option yet.
+  (void)ignoreErrors;
+  // We do not handle fast build yet.
+  (void)fast;
+
+  std::string makeCommand =
+    cmSystemTools::ConvertToUnixOutputPath(makeProgram);
+
+  if(additionalOptions)
+    {
+    makeCommand += " ";
+    makeCommand += additionalOptions;
+    }
+  if(targetName)
+    {
+    if(strcmp(targetName, "clean") == 0)
+      {
+      makeCommand += " -t clean";
+      }
+    else
+      {
+      makeCommand += " ";
+      makeCommand += targetName;
+      }
+    }
+
+  return makeCommand;
+}
+
+//----------------------------------------------------------------------------
+// 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,
+                                     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,
+                                    restat,
+                                    generator);
+}
+
+bool cmGlobalNinjaGenerator::HasRule(const std::string &name)
+{
+  RulesSetType::const_iterator rule = this->Rules.find(name);
+  return (rule != this->Rules.end());
+}
+
+//----------------------------------------------------------------------------
+// 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::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::WriteAssumedSourceDependencies(std::ostream& os)
+{
+  for (std::map<std::string, std::set<std::string> >::iterator
+       i = this->AssumedSourceDependencies.begin();
+       i != this->AssumedSourceDependencies.end(); ++i) {
+    WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
+                            "Assume dependencies for generated source file.",
+                            cmNinjaDeps(1, i->first),
+                            cmNinjaDeps(i->second.begin(), i->second.end()));
+  }
+}
+
+void
+cmGlobalNinjaGenerator
+::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+{
+  const char* configName =
+    target->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE");
+  cmLocalNinjaGenerator *ng =
+    static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+
+  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).c_str()));
+    break;
+
+  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* 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();
+    outputs.insert(outputs.end(), utils.begin(), utils.end());
+  } else {
+    cmTargetDependSet const& targetDeps =
+      this->GetTargetDirectDepends(*target);
+    for (cmTargetDependSet::const_iterator i = targetDeps.begin();
+         i != targetDeps.end(); ++i) {
+      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(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::iterator i = TargetAliases.begin();
+       i != TargetAliases.end(); ++i) {
+    // Don't write ambiguous aliases.
+    if (!i->second)
+      continue;
+
+    cmNinjaDeps deps;
+    this->AppendTargetOutputs(i->second, deps);
+
+    cmGlobalNinjaGenerator::WritePhonyBuild(os,
+                                            "",
+                                            cmNinjaDeps(1, i->first),
+                                            deps);
+  }
+}
+
+void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
+{
+  // Write headers.
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os << "# Built-in targets\n\n";
+
+  this->WriteTargetAll(os);
+  this->WriteTargetRebuildManifest(os);
+}
+
+void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
+{
+  cmNinjaDeps outputs;
+  outputs.push_back("all");
+
+  cmGlobalNinjaGenerator::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)
+{
+  cmMakefile* mfRoot = this->LocalGenerators[0]->GetMakefile();
+
+  std::ostringstream cmd;
+  cmd << mfRoot->GetRequiredDefinition("CMAKE_COMMAND")
+      << " -H" << mfRoot->GetHomeDirectory()
+      << " -B" << mfRoot->GetHomeOutputDirectory();
+  WriteRule(*this->RulesFileStream,
+            "RERUN_CMAKE",
+            cmd.str(),
+            "Re-running CMake...",
+            "Rule for re-running cmake.",
+            /*depfile=*/ "",
+            /*restat=*/ false,
+            /*generator=*/ true);
+
+  cmNinjaDeps implicitDeps;
+  for (std::vector<cmLocalGenerator *>::const_iterator i =
+       this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) {
+    const std::vector<std::string>& lf = (*i)->GetMakefile()->GetListFiles();
+    implicitDeps.insert(implicitDeps.end(), lf.begin(), lf.end());
+  }
+  std::sort(implicitDeps.begin(), implicitDeps.end());
+  implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
+                     implicitDeps.end());
+  implicitDeps.push_back("CMakeCache.txt");
+
+  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());
+
+  WritePhonyBuild(os,
+                  "A missing CMake input file is not an error.",
+                  implicitDeps,
+                  cmNinjaDeps(),
+                  cmNinjaDeps(),
+                  cmNinjaDeps(),
+                  cmNinjaVars());
+}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
new file mode 100644
index 0000000..171d14b
--- /dev/null
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -0,0 +1,329 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmGlobalNinjaGenerator_h
+#  define cmGlobalNinjaGenerator_h
+
+#  include "cmGlobalGenerator.h"
+#  include "cmNinjaTypes.h"
+
+class cmLocalGenerator;
+class cmGeneratedFileStream;
+
+/**
+ * \class cmGlobalNinjaGenerator
+ * \brief Write a build.ninja file.
+ *
+ * The main differences between this generator and the UnixMakefile
+ * generator family are:
+ * - We don't care about VERBOSE variable or RULE_MESSAGES property since
+ *   it is handle by Ninja's -v option.
+ * - We don't care about computing any progress status since Ninja manages
+ *   it itself.
+ * - We don't care about generating a clean target since Ninja already have
+ *   a clean tool.
+ * - We generate one build.ninja and one rules.ninja per project.
+ * - We try to minimize the number of generated rules: one per target and
+ *   language.
+ * - We use Ninja special variable $in and $out to produce nice output.
+ * - We extensively use Ninja variable overloading system to minimize the
+ *   number of generated rules.
+ */
+class cmGlobalNinjaGenerator : public cmGlobalGenerator
+{
+public:
+  /// The default name of Ninja's build file. Typically: build.ninja.
+  static const char* NINJA_BUILD_FILE;
+
+  /// The default name of Ninja's rules file. Typically: rules.ninja.
+  /// It is included in the main build.ninja file.
+  static const char* NINJA_RULES_FILE;
+
+  /// The indentation string used when generating Ninja's build file.
+  static const char* INDENT;
+
+  /// Write @a count times INDENT level to output stream @a os.
+  static void Indent(std::ostream& os, int count);
+
+  /// Write a divider in the given output stream @a os.
+  static void WriteDivider(std::ostream& os);
+
+  static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
+  static std::string EncodeLiteral(const std::string &lit);
+
+  /**
+   * Write the given @a comment to the output stream @a os. It
+   * handles new line character properly.
+   */
+  static void WriteComment(std::ostream& os, const std::string& comment);
+
+  /**
+   * Write a build statement to @a os with the @a comment using
+   * the @a rule the list of @a outputs files and inputs.
+   * It also writes the variables bound to this build statement.
+   * @warning no escaping of any kind is done here.
+   */
+  static void 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);
+
+  /**
+   * Helper to write a build statement with the special 'phony' rule.
+   */
+  static void WritePhonyBuild(std::ostream& os,
+                              const std::string& comment,
+                              const cmNinjaDeps& outputs,
+                              const cmNinjaDeps& explicitDeps,
+                              const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
+                              const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
+                              const cmNinjaVars& variables = cmNinjaVars());
+
+  void WriteCustomCommandBuild(const std::string& command,
+                               const std::string& description,
+                               const std::string& comment,
+                               const cmNinjaDeps& outputs,
+                               const cmNinjaDeps& deps = cmNinjaDeps(),
+                             const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+
+  /**
+   * Write a rule statement named @a name to @a os with the @a comment,
+   * the mandatory @a command, the @a depfile and the @a description.
+   * It also writes the variables bound to this rule statement.
+   * @warning no escaping of any kind is done here.
+   */
+  static void WriteRule(std::ostream& os,
+                        const std::string& name,
+                        const std::string& command,
+                        const std::string& description,
+                        const std::string& comment = "",
+                        const std::string& depfile = "",
+                        bool restat = false,
+                        bool generator = false);
+
+  /**
+   * Write a variable named @a name to @a os with value @a value and an
+   * optional @a comment. An @a indent level can be specified.
+   * @warning no escaping of any kind is done here.
+   */
+  static void WriteVariable(std::ostream& os,
+                            const std::string& name,
+                            const std::string& value,
+                            const std::string& comment = "",
+                            int indent = 0);
+
+  /**
+   * Write an include statement including @a filename with an optional
+   * @a comment to the @a os stream.
+   */
+  static void WriteInclude(std::ostream& os,
+                           const std::string& filename,
+                           const std::string& comment = "");
+
+  /**
+   * Write a default target statement specifying @a targets as
+   * the default targets.
+   */
+  static void WriteDefault(std::ostream& os,
+                           const cmNinjaDeps& targets,
+                           const std::string& comment = "");
+
+public:
+  /// Default constructor.
+  cmGlobalNinjaGenerator();
+
+  /// Convenience method for creating an instance of this class.
+  static cmGlobalGenerator* New() {
+    return new cmGlobalNinjaGenerator; }
+
+  /// Destructor.
+  virtual ~cmGlobalNinjaGenerator() { }
+
+  /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
+  virtual cmLocalGenerator* CreateLocalGenerator();
+
+  /// Overloaded methods. @see cmGlobalGenerator::GetName().
+  virtual const char* GetName() const {
+    return cmGlobalNinjaGenerator::GetActualName(); }
+
+  /// @return the name of this generator.
+  static const char* GetActualName() { return "Ninja"; }
+
+  /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
+  virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+
+  /// Overloaded methods. @see cmGlobalGenerator::Generate()
+  virtual void Generate();
+
+  /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
+  virtual void EnableLanguage(std::vector<std::string>const& languages,
+                              cmMakefile* mf,
+                              bool optional);
+
+  /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand()
+  virtual std::string GenerateBuildCommand(const char* makeProgram,
+                                           const char* projectName,
+                                           const char* additionalOptions,
+                                           const char* targetName,
+                                           const char* config,
+                                           bool ignoreErrors,
+                                           bool fast);
+
+  // Setup target names
+  virtual const char* GetAllTargetName()           const { return "all"; }
+  virtual const char* GetInstallTargetName()       const { return "install"; }
+  virtual const char* GetInstallLocalTargetName()  const {
+    return "install/local";
+  }
+  virtual const char* GetInstallStripTargetName()  const {
+    return "install/strip";
+  }
+  virtual const char* GetTestTargetName()          const { return "test"; }
+  virtual const char* GetPackageTargetName()       const { return "package"; }
+  virtual const char* GetPackageSourceTargetName() const {
+    return "package_source";
+  }
+  virtual const char* GetEditCacheTargetName()     const {
+    return "edit_cache";
+  }
+  virtual const char* GetRebuildCacheTargetName()  const {
+    return "rebuild_cache";
+  }
+  virtual const char* GetCleanTargetName()         const { return "clean"; }
+
+public:
+  cmGeneratedFileStream* GetBuildFileStream() const
+  { return this->BuildFileStream; }
+
+  cmGeneratedFileStream* GetRulesFileStream() const
+  { return this->RulesFileStream; }
+
+  /**
+   * Add a rule to the generated build system.
+   * Call WriteRule() behind the scene but perform some check before like:
+   * - Do not add twice the same rule.
+   */
+  void AddRule(const std::string& name,
+               const std::string& command,
+               const std::string& description,
+               const std::string& comment = "",
+               const std::string& depfile = "",
+               bool restat = false,
+               bool generator = false);
+
+  bool HasRule(const std::string& name);
+
+  void AddCustomCommandRule();
+
+protected:
+
+  /// Overloaded methods.
+  /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
+  virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
+
+private:
+  // In order to access the AddDependencyToAll() functions and co.
+  friend class cmLocalNinjaGenerator;
+
+  // In order to access the SeenCustomCommand() function.
+  friend class cmNinjaTargetGenerator;
+  friend class cmNinjaNormalTargetGenerator;
+  friend class cmNinjaUtilityTargetGenerator;
+
+private:
+  void OpenBuildFileStream();
+  void CloseBuildFileStream();
+
+  void OpenRulesFileStream();
+  void CloseRulesFileStream();
+
+  /// Write the common disclaimer text at the top of each build file.
+  void WriteDisclaimer(std::ostream& os);
+
+  void AddDependencyToAll(cmTarget* target);
+
+  void WriteAssumedSourceDependencies(std::ostream& os);
+
+  void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
+  void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
+
+  void AddTargetAlias(const std::string& alias, cmTarget* target);
+  void WriteTargetAliases(std::ostream& os);
+
+  void WriteBuiltinTargets(std::ostream& os);
+  void WriteTargetAll(std::ostream& os);
+  void WriteTargetRebuildManifest(std::ostream& os);
+
+  /// Called when we have seen the given custom command.  Returns true
+  /// if we has seen it before.
+  bool SeenCustomCommand(cmCustomCommand *cc) {
+    return !this->CustomCommands.insert(cc).second;
+  }
+
+  /// Called when we have seen the given custom command output.
+  void SeenCustomCommandOutput(const std::string &output) {
+    this->CustomCommandOutputs.insert(output);
+    // We don't need the assumed dependencies anymore, because we have
+    // an output.
+    this->AssumedSourceDependencies.erase(output);
+  }
+
+  bool HasCustomCommandOutput(const std::string &output) {
+    return this->CustomCommandOutputs.find(output) !=
+           this->CustomCommandOutputs.end();
+  }
+
+  void AddAssumedSourceDependencies(const std::string &source,
+                                    const cmNinjaDeps &deps) {
+    std::set<std::string> &ASD = this->AssumedSourceDependencies[source];
+    // Because we may see the same source file multiple times (same source
+    // specified in multiple targets), compute the union of any assumed
+    // dependencies.
+    ASD.insert(deps.begin(), deps.end());
+  }
+
+private:
+  /// The file containing the build statement. (the relation ship of the
+  /// compilation DAG).
+  cmGeneratedFileStream* BuildFileStream;
+  /// The file containing the rule statements. (The action attached to each
+  /// edge of the compilation DAG).
+  cmGeneratedFileStream* RulesFileStream;
+
+  /// The type used to store the set of rules added to the generated build
+  /// system.
+  typedef std::set<std::string> RulesSetType;
+
+  /// The set of rules added to the generated build system.
+  RulesSetType Rules;
+
+  /// The set of dependencies to add to the "all" target.
+  cmNinjaDeps AllDependencies;
+
+  /// The set of custom commands we have seen.
+  std::set<cmCustomCommand *> CustomCommands;
+
+  /// The set of custom command outputs we have seen.
+  std::set<std::string> CustomCommandOutputs;
+
+  /// The mapping from source file to assumed dependencies.
+  std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
+
+  typedef std::map<std::string, cmTarget*> TargetAliasMap;
+  TargetAliasMap TargetAliases;
+};
+
+#endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
new file mode 100644
index 0000000..6ae5032
--- /dev/null
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -0,0 +1,413 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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 "cmLocalNinjaGenerator.h"
+#include "cmCustomCommandGenerator.h"
+#include "cmMakefile.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmNinjaTargetGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSourceFile.h"
+#include "cmComputeLinkInformation.h"
+#include "cmake.h"
+
+#include <assert.h>
+
+cmLocalNinjaGenerator::cmLocalNinjaGenerator()
+  : cmLocalGenerator()
+  , ConfigName("")
+  , HomeRelativeOutputPath("")
+{
+  this->IsMakefileGenerator = true;
+}
+
+//----------------------------------------------------------------------------
+// Virtual public methods.
+
+cmLocalNinjaGenerator::~cmLocalNinjaGenerator()
+{
+}
+
+void cmLocalNinjaGenerator::Generate()
+{
+  this->SetConfigName();
+
+  this->WriteProcessedMakefile(this->GetBuildFileStream());
+  this->WriteProcessedMakefile(this->GetRulesFileStream());
+
+  this->WriteBuildFileTop();
+
+  cmTargets& targets = this->GetMakefile()->GetTargets();
+  for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
+    {
+    cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(&t->second);
+    if(tg)
+      {
+      tg->Generate();
+      // Add the target to "all" if required.
+      if (!this->GetGlobalNinjaGenerator()->IsExcluded(
+            this->GetGlobalNinjaGenerator()->LocalGenerators[0],
+            t->second))
+        this->GetGlobalNinjaGenerator()->AddDependencyToAll(&t->second);
+      delete tg;
+      }
+    }
+
+  this->WriteCustomCommandBuildStatements();
+}
+
+// Implemented in:
+//   cmLocalUnixMakefileGenerator3.
+// Used in:
+//   Source/cmMakefile.cxx
+//   Source/cmGlobalGenerator.cxx
+void cmLocalNinjaGenerator::Configure()
+{
+  // Compute the path to use when referencing the current output
+  // directory from the top output directory.
+  this->HomeRelativeOutputPath =
+    this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT);
+  if(this->HomeRelativeOutputPath == ".")
+    {
+    this->HomeRelativeOutputPath = "";
+    }
+  this->cmLocalGenerator::Configure();
+
+}
+
+// TODO: Picked up from cmLocalUnixMakefileGenerator3.  Refactor it.
+std::string cmLocalNinjaGenerator
+::GetTargetDirectory(cmTarget const& target) const
+{
+  std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
+  dir += 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());
+}
+
+// TODO: Picked up from cmLocalUnixMakefileGenerator3.  Refactor it.
+std::string
+cmLocalNinjaGenerator
+::GetObjectFileName(const cmTarget& target,
+                    const cmSourceFile& source)
+{
+  // Make sure we never hit this old case.
+  if(source.GetProperty("MACOSX_PACKAGE_LOCATION"))
+    {
+    std::string msg = "MACOSX_PACKAGE_LOCATION set on source file: ";
+    msg += source.GetFullPath();
+    this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR,
+                                      msg.c_str());
+    }
+
+  // Start with the target directory.
+  std::string obj = this->GetTargetDirectory(target);
+  obj += "/";
+
+  // Get the object file name without the target directory.
+  std::string dir_max;
+  dir_max += this->Makefile->GetCurrentOutputDirectory();
+  dir_max += "/";
+  dir_max += obj;
+  std::string objectName =
+    this->GetObjectFileNameWithoutTarget(source, dir_max, 0);
+  // Append the object name to the target directory.
+  obj += objectName;
+  return obj;
+}
+
+//----------------------------------------------------------------------------
+// Virtual protected methods.
+
+std::string
+cmLocalNinjaGenerator::ConvertToLinkReference(std::string const& lib)
+{
+  return this->Convert(lib.c_str(), HOME_OUTPUT, SHELL);
+}
+
+std::string
+cmLocalNinjaGenerator::ConvertToIncludeReference(std::string const& path)
+{
+  return this->Convert(path.c_str(), HOME_OUTPUT, SHELL);
+}
+
+//----------------------------------------------------------------------------
+// Private methods.
+
+cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const
+{
+  return *this->GetGlobalNinjaGenerator()->GetBuildFileStream();
+}
+
+cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const
+{
+  return *this->GetGlobalNinjaGenerator()->GetRulesFileStream();
+}
+
+const cmake* cmLocalNinjaGenerator::GetCMakeInstance() const
+{
+  return this->GetGlobalGenerator()->GetCMakeInstance();
+}
+
+cmake* cmLocalNinjaGenerator::GetCMakeInstance()
+{
+  return this->GetGlobalGenerator()->GetCMakeInstance();
+}
+
+bool cmLocalNinjaGenerator::isRootMakefile() const
+{
+  return (strcmp(this->Makefile->GetCurrentDirectory(),
+                 this->GetCMakeInstance()->GetHomeDirectory()) == 0);
+}
+
+void cmLocalNinjaGenerator::WriteBuildFileTop()
+{
+  // We do that only once for the top CMakeLists.txt file.
+  if(!this->isRootMakefile())
+    return;
+
+  // For the build file.
+  this->WriteProjectHeader(this->GetBuildFileStream());
+  this->WriteNinjaFilesInclusion(this->GetBuildFileStream());
+
+  // For the rule file.
+  this->WriteProjectHeader(this->GetRulesFileStream());
+}
+
+void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
+{
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os
+    << "# Project: " << this->GetMakefile()->GetProjectName() << std::endl
+    << "# Configuration: " << this->ConfigName << std::endl
+    ;
+  cmGlobalNinjaGenerator::WriteDivider(os);
+}
+
+void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
+{
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os
+    << "# Include auxiliary files.\n"
+    << "\n"
+    ;
+  cmGlobalNinjaGenerator::WriteInclude(os,
+                                      cmGlobalNinjaGenerator::NINJA_RULES_FILE,
+                                       "Include rules file.");
+  os << "\n";
+}
+
+void cmLocalNinjaGenerator::SetConfigName()
+{
+  // Store the configuration name that will be generated.
+  if(const char* config =
+       this->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE"))
+    {
+    // Use the build type given by the user.
+    this->ConfigName = config;
+    }
+  else
+    {
+    // No configuration type given.
+    this->ConfigName = "";
+    }
+}
+
+void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
+{
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os
+    << "# Write statements declared in CMakeLists.txt:" << std::endl
+    << "# " << this->Makefile->GetCurrentListFile() << std::endl
+    ;
+  if(this->isRootMakefile())
+    os << "# Which is the root file." << std::endl;
+  cmGlobalNinjaGenerator::WriteDivider(os);
+  os << std::endl;
+}
+
+std::string cmLocalNinjaGenerator::ConvertToNinjaPath(const char *path)
+{
+  return this->Convert(path,
+                       cmLocalGenerator::HOME_OUTPUT,
+                       cmLocalGenerator::MAKEFILE);
+}
+
+void
+cmLocalNinjaGenerator
+::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+{
+  this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs);
+}
+
+void
+cmLocalNinjaGenerator
+::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
+{
+  this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs);
+}
+
+void cmLocalNinjaGenerator::AppendCustomCommandDeps(const cmCustomCommand *cc,
+                                                    cmNinjaDeps &ninjaDeps)
+{
+  const std::vector<std::string> &deps = cc->GetDepends();
+  for (std::vector<std::string>::const_iterator i = deps.begin();
+       i != deps.end(); ++i) {
+    std::string dep;
+    if (this->GetRealDependency(i->c_str(), this->GetConfigName(), dep))
+      ninjaDeps.push_back(ConvertToNinjaPath(dep.c_str()));
+  }
+}
+
+std::string cmLocalNinjaGenerator::BuildCommandLine(
+                                    const std::vector<std::string> &cmdLines)
+{
+  // If we have no commands but we need to build a command anyway, use ":".
+  // This happens when building a POST_BUILD value for link targets that
+  // don't use POST_BUILD.
+  if (cmdLines.empty())
+    return ":";
+
+  // TODO: This will work only on Unix platforms. I don't
+  // want to use a link.txt file because I will lose the benefit of the
+  // $in variables. A discussion about dealing with multiple commands in
+  // a rule is started here:
+  // http://groups.google.com/group/ninja-build/browse_thread/thread/d515f23a78986008
+  std::ostringstream cmd;
+  for (std::vector<std::string>::const_iterator li = cmdLines.begin();
+       li != cmdLines.end(); ++li) {
+    if (li != cmdLines.begin())
+      cmd << " && ";
+    cmd << *li;
+  }
+  return cmd.str();
+}
+
+void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
+                                            std::vector<std::string> &cmdLines)
+{
+  cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
+  if (ccg.GetNumberOfCommands() > 0) {
+    std::ostringstream cdCmd;
+    cdCmd << "cd ";
+    if (const char* wd = cc->GetWorkingDirectory())
+      cdCmd << wd;
+    else
+      cdCmd << this->GetMakefile()->GetStartOutputDirectory();
+    cmdLines.push_back(cdCmd.str());
+  }
+  for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
+    cmdLines.push_back(ccg.GetCommand(i));
+    std::string& cmd = cmdLines.back();
+    ccg.AppendArguments(i, cmd);
+  }
+}
+
+void
+cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(cmCustomCommand *cc,
+                                            const cmNinjaDeps& orderOnlyDeps)
+{
+  if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc))
+    return;
+
+  const std::vector<std::string> &outputs = cc->GetOutputs();
+  cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
+
+  std::transform(outputs.begin(), outputs.end(),
+                 ninjaOutputs.begin(), MapToNinjaPath());
+  this->AppendCustomCommandDeps(cc, ninjaDeps);
+
+  for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
+       ++i)
+    this->GetGlobalNinjaGenerator()->SeenCustomCommandOutput(*i);
+
+  std::vector<std::string> cmdLines;
+  this->AppendCustomCommandLines(cc, cmdLines);
+
+  if (cmdLines.empty()) {
+    cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+                                            "Phony custom command for " +
+                                              ninjaOutputs[0],
+                                            ninjaOutputs,
+                                            ninjaDeps,
+                                            cmNinjaDeps(),
+                                            orderOnlyDeps,
+                                            cmNinjaVars());
+  } else {
+    this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
+      this->BuildCommandLine(cmdLines),
+      this->ConstructComment(*cc),
+      "Custom command for " + ninjaOutputs[0],
+      ninjaOutputs,
+      ninjaDeps,
+      orderOnlyDeps);
+  }
+}
+
+void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand* cc,
+                                                   cmTarget* target)
+{
+  this->CustomCommandTargets[cc].insert(target);
+}
+
+void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
+{
+  for (CustomCommandTargetMap::iterator i = this->CustomCommandTargets.begin();
+       i != this->CustomCommandTargets.end(); ++i) {
+    // 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.
+    std::set<cmTarget*>::iterator j = i->second.begin();
+    assert(j != i->second.end());
+    std::vector<std::string> ccTargetDeps;
+    this->AppendTargetDepends(*j, ccTargetDeps);
+    std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
+    ++j;
+
+    for (; j != i->second.end(); ++j) {
+      std::vector<std::string> jDeps, depsIntersection;
+      this->AppendTargetDepends(*j, jDeps);
+      std::sort(jDeps.begin(), jDeps.end());
+      std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
+                            jDeps.begin(), jDeps.end(),
+                            std::back_inserter(depsIntersection));
+      ccTargetDeps = depsIntersection;
+    }
+
+    this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps);
+  }
+}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
new file mode 100644
index 0000000..fee9cd0
--- /dev/null
+++ b/Source/cmLocalNinjaGenerator.h
@@ -0,0 +1,134 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmLocalNinjaGenerator_h
+#  define cmLocalNinjaGenerator_h
+
+#  include "cmLocalGenerator.h"
+#  include "cmNinjaTypes.h"
+
+class cmGlobalNinjaGenerator;
+class cmGeneratedFileStream;
+class cmake;
+
+/**
+ * \class cmLocalNinjaGenerator
+ * \brief Write a local build.ninja file.
+ *
+ * cmLocalNinjaGenerator produces a local build.ninja file from its
+ * member Makefile.
+ */
+class cmLocalNinjaGenerator : public cmLocalGenerator
+{
+public:
+  /// Default constructor.
+  cmLocalNinjaGenerator();
+
+  /// Destructor.
+  virtual ~cmLocalNinjaGenerator();
+
+  /// Overloaded methods. @see cmLocalGenerator::Generate()
+  virtual void Generate();
+
+  /// Overloaded methods. @see cmLocalGenerator::Configure()
+  virtual void Configure();
+
+  /// Overloaded methods. @see cmLocalGenerator::GetTargetDirectory()
+  virtual std::string GetTargetDirectory(cmTarget const& target) const;
+
+public:
+  const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const;
+  cmGlobalNinjaGenerator* GetGlobalNinjaGenerator();
+
+  /**
+   * Shortcut to get the cmake instance throw the global generator.
+   * @return an instance of the cmake object.
+   */
+  const cmake* GetCMakeInstance() const;
+  cmake* GetCMakeInstance();
+
+  const char* GetConfigName() const
+  { return this->ConfigName.c_str(); }
+
+  std::string GetObjectFileName(const cmTarget& target,
+                                const cmSourceFile& source);
+
+  /// @return whether we are processing the top CMakeLists.txt file.
+  bool isRootMakefile() const;
+
+  /// @returns the relative path between the HomeOutputDirectory and this
+  /// local generators StartOutputDirectory.
+  std::string GetHomeRelativeOutputPath() const
+  { return this->HomeRelativeOutputPath; }
+
+protected:
+  virtual std::string ConvertToLinkReference(std::string const& lib);
+  virtual std::string ConvertToIncludeReference(std::string const& path);
+
+private:
+  friend class cmGlobalNinjaGenerator;
+
+  // In order to access to protected member of the local generator.
+  friend class cmNinjaTargetGenerator;
+  friend class cmNinjaNormalTargetGenerator;
+  friend class cmNinjaUtilityTargetGenerator;
+
+private:
+  cmGeneratedFileStream& GetBuildFileStream() const;
+  cmGeneratedFileStream& GetRulesFileStream() const;
+
+  void WriteBuildFileTop();
+  void WriteProjectHeader(std::ostream& os);
+  void WriteNinjaFilesInclusion(std::ostream& os);
+  void WriteProcessedMakefile(std::ostream& os);
+
+  void SetConfigName();
+
+  std::string ConvertToNinjaPath(const char *path);
+
+  struct map_to_ninja_path {
+    cmLocalNinjaGenerator *LocalGenerator;
+    map_to_ninja_path(cmLocalNinjaGenerator *LocalGenerator)
+      : LocalGenerator(LocalGenerator) {}
+    std::string operator()(const std::string &path) {
+      return LocalGenerator->ConvertToNinjaPath(path.c_str());
+    }
+  };
+  map_to_ninja_path MapToNinjaPath() {
+    return map_to_ninja_path(this);
+  }
+
+  void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
+  void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
+
+  void AppendCustomCommandDeps(const cmCustomCommand *cc,
+                               cmNinjaDeps &ninjaDeps);
+  std::string BuildCommandLine(const std::vector<std::string> &cmdLines);
+  void AppendCustomCommandLines(const cmCustomCommand *cc,
+                                std::vector<std::string> &cmdLines);
+  void WriteCustomCommandRule();
+  void WriteCustomCommandBuildStatement(cmCustomCommand *cc,
+                                        const cmNinjaDeps& orderOnlyDeps);
+
+  void AddCustomCommandTarget(cmCustomCommand* cc, cmTarget* target);
+  void WriteCustomCommandBuildStatements();
+
+private:
+  std::string ConfigName;
+  std::string HomeRelativeOutputPath;
+
+  typedef std::map<cmCustomCommand*, std::set<cmTarget*> >
+    CustomCommandTargetMap;
+  CustomCommandTargetMap CustomCommandTargets;
+};
+
+#endif // ! cmLocalNinjaGenerator_h
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
new file mode 100644
index 0000000..d7f8ad7
--- /dev/null
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -0,0 +1,430 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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 "cmNinjaNormalTargetGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmSourceFile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmMakefile.h"
+
+#include <assert.h>
+
+cmNinjaNormalTargetGenerator::
+cmNinjaNormalTargetGenerator(cmTarget* target)
+  : cmNinjaTargetGenerator(target)
+  , TargetNameOut()
+  , TargetNameSO()
+  , TargetNameReal()
+  , TargetNameImport()
+  , TargetNamePDB()
+  , TargetLinkLanguage(target->GetLinkerLanguage(this->GetConfigName()))
+{
+  if (target->GetType() == cmTarget::EXECUTABLE)
+    target->GetExecutableNames(this->TargetNameOut,
+                               this->TargetNameReal,
+                               this->TargetNameImport,
+                               this->TargetNamePDB,
+                               GetLocalGenerator()->GetConfigName());
+  else
+    target->GetLibraryNames(this->TargetNameOut,
+                            this->TargetNameSO,
+                            this->TargetNameReal,
+                            this->TargetNameImport,
+                            this->TargetNamePDB,
+                            GetLocalGenerator()->GetConfigName());
+}
+
+cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
+{
+}
+
+void cmNinjaNormalTargetGenerator::Generate()
+{
+  if (!this->TargetLinkLanguage) {
+    cmSystemTools::Error("CMake can not determine linker language for target:",
+                         this->GetTarget()->GetName());
+    return;
+  }
+
+  // Write the rules for each language.
+  this->WriteLanguagesRules();
+
+  // Write the build statements
+  this->WriteObjectBuildStatements();
+
+  this->WriteLinkRule();
+  this->WriteLinkStatement();
+
+  this->GetBuildFileStream() << "\n";
+  this->GetRulesFileStream() << "\n";
+}
+
+void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
+{
+  cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream());
+  this->GetRulesFileStream()
+    << "# Rules for each languages for "
+    << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+    << " target "
+    << this->GetTargetName()
+    << "\n\n";
+
+  std::set<cmStdString> languages;
+  this->GetTarget()->GetLanguages(languages);
+  for(std::set<cmStdString>::const_iterator l = languages.begin();
+      l != languages.end();
+      ++l)
+    this->WriteLanguageRules(*l);
+}
+
+const char *cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
+{
+  switch (this->GetTarget()->GetType()) {
+    case cmTarget::STATIC_LIBRARY:
+      return "static library";
+    case cmTarget::SHARED_LIBRARY:
+      return "shared library";
+    case cmTarget::MODULE_LIBRARY:
+      return "shared module";
+    case cmTarget::EXECUTABLE:
+      return "executable";
+    default:
+      return 0;
+  }
+}
+
+std::string
+cmNinjaNormalTargetGenerator
+::LanguageLinkerRule() const
+{
+  return std::string(this->TargetLinkLanguage)
+    + "_"
+    + cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+    + "_LINKER";
+}
+
+void
+cmNinjaNormalTargetGenerator
+::WriteLinkRule()
+{
+  cmTarget::TargetType targetType = this->GetTarget()->GetType();
+  std::string ruleName = this->LanguageLinkerRule();
+
+  if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
+    cmLocalGenerator::RuleVariables vars;
+    vars.RuleLauncher = "RULE_LAUNCH_LINK";
+    vars.CMTarget = this->GetTarget();
+    vars.Language = this->TargetLinkLanguage;
+    vars.Objects = "$in";
+    std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
+    objdir += this->GetTargetName();
+    objdir += ".dir";
+    objdir = this->GetLocalGenerator()->Convert(objdir.c_str(),
+                                                cmLocalGenerator::START_OUTPUT,
+                                                cmLocalGenerator::SHELL);
+    vars.ObjectDir = objdir.c_str();
+    vars.Target = "$out";
+    vars.TargetSOName = "$SONAME";
+    vars.TargetInstallNameDir = "$INSTALLNAME_DIR";
+
+    // Setup the target version.
+    std::string targetVersionMajor;
+    std::string targetVersionMinor;
+    {
+    cmOStringStream majorStream;
+    cmOStringStream minorStream;
+    int major;
+    int minor;
+    this->GetTarget()->GetTargetVersion(major, minor);
+    majorStream << major;
+    minorStream << minor;
+    targetVersionMajor = majorStream.str();
+    targetVersionMinor = minorStream.str();
+    }
+    vars.TargetVersionMajor = targetVersionMajor.c_str();
+    vars.TargetVersionMinor = targetVersionMinor.c_str();
+
+    vars.LinkLibraries = "$LINK_LIBRARIES";
+    vars.Flags = "$FLAGS";
+    vars.LinkFlags = "$LINK_FLAGS";
+
+    std::string langFlags;
+    this->GetLocalGenerator()->AddLanguageFlags(langFlags,
+                                                this->TargetLinkLanguage,
+                                                this->GetConfigName());
+    if (targetType != cmTarget::EXECUTABLE)
+      langFlags += " $ARCH_FLAGS";
+    vars.LanguageCompileFlags = langFlags.c_str();
+
+    // Rule for linking library.
+    std::vector<std::string> linkCmds = this->ComputeLinkCmd();
+    for(std::vector<std::string>::iterator i = linkCmds.begin();
+        i != linkCmds.end();
+        ++i)
+      {
+      this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+      }
+    linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
+    linkCmds.push_back("$POST_BUILD");
+    std::string linkCmd =
+      this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+
+    // Write the linker rule.
+    std::ostringstream comment;
+    comment << "Rule for linking " << this->TargetLinkLanguage << " "
+            << this->GetVisibleTypeName() << ".";
+    std::ostringstream description;
+    description << "Linking " << this->TargetLinkLanguage << " "
+                << this->GetVisibleTypeName() << " $out";
+    this->GetGlobalGenerator()->AddRule(ruleName,
+                                        linkCmd,
+                                        description.str(),
+                                        comment.str());
+  }
+
+  if (this->TargetNameOut != this->TargetNameReal) {
+    std::string cmakeCommand =
+      this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
+    if (targetType == cmTarget::EXECUTABLE)
+      this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_EXECUTABLE",
+                                          cmakeCommand +
+                                          " -E cmake_symlink_executable"
+                                          " $in $out && $POST_BUILD",
+                                          "Creating executable symlink $out",
+                                      "Rule for creating executable symlink.");
+    else
+      this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_LIBRARY",
+                                          cmakeCommand +
+                                          " -E cmake_symlink_library"
+                                          " $in $SONAME $out && $POST_BUILD",
+                                          "Creating library symlink $out",
+                                         "Rule for creating library symlink.");
+  }
+}
+
+std::vector<std::string>
+cmNinjaNormalTargetGenerator
+::ComputeLinkCmd()
+{
+  cmTarget::TargetType targetType = this->GetTarget()->GetType();
+  switch (targetType) {
+    case cmTarget::STATIC_LIBRARY: {
+      // Check if you have a non archive way to create the static library.
+      {
+      std::string linkCmdVar = "CMAKE_";
+      linkCmdVar += this->TargetLinkLanguage;
+      linkCmdVar += "_CREATE_STATIC_LIBRARY";
+      if (const char *linkCmd =
+            this->GetMakefile()->GetDefinition(linkCmdVar.c_str()))
+        {
+        return std::vector<std::string>(1, linkCmd);
+        }
+      }
+
+      // We have archive link commands set. First, delete the existing archive.
+      std::vector<std::string> linkCmds;
+      std::string cmakeCommand =
+        this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
+      linkCmds.push_back(cmakeCommand + " -E remove $out");
+
+      // TODO: Use ARCHIVE_APPEND for archives over a certain size.
+      {
+      std::string linkCmdVar = "CMAKE_";
+      linkCmdVar += this->TargetLinkLanguage;
+      linkCmdVar += "_ARCHIVE_CREATE";
+      const char *linkCmd =
+        this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+      linkCmds.push_back(linkCmd);
+      }
+      {
+      std::string linkCmdVar = "CMAKE_";
+      linkCmdVar += this->TargetLinkLanguage;
+      linkCmdVar += "_ARCHIVE_FINISH";
+      const char *linkCmd =
+        this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+      linkCmds.push_back(linkCmd);
+      }
+      return linkCmds;
+    }
+    case cmTarget::SHARED_LIBRARY:
+    case cmTarget::MODULE_LIBRARY:
+    case cmTarget::EXECUTABLE: {
+      std::string linkCmdVar = "CMAKE_";
+      linkCmdVar += this->TargetLinkLanguage;
+      switch (targetType) {
+      case cmTarget::SHARED_LIBRARY:
+        linkCmdVar += "_CREATE_SHARED_LIBRARY";
+        break;
+      case cmTarget::MODULE_LIBRARY:
+        linkCmdVar += "_CREATE_SHARED_MODULE";
+        break;
+      case cmTarget::EXECUTABLE:
+        linkCmdVar += "_LINK_EXECUTABLE";
+        break;
+      default:
+        assert(0 && "Unexpected target type");
+      }
+      const char *linkCmd =
+        this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+      return std::vector<std::string>(1, linkCmd);
+    }
+    default:
+      assert(0 && "Unexpected target type");
+  }
+}
+
+void cmNinjaNormalTargetGenerator::WriteLinkStatement()
+{
+  cmTarget::TargetType targetType = this->GetTarget()->GetType();
+
+  // Write comments.
+  cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+  this->GetBuildFileStream()
+    << "# Link build statements for "
+    << cmTarget::GetTargetTypeName(targetType)
+    << " target "
+    << this->GetTargetName()
+    << "\n\n";
+
+  cmNinjaDeps emptyDeps;
+  cmNinjaVars vars;
+
+  std::string targetOutput = ConvertToNinjaPath(
+    this->GetTarget()->GetFullPath(this->GetConfigName()).c_str());
+  std::string targetOutputReal = ConvertToNinjaPath(
+    this->GetTarget()->GetFullPath(this->GetConfigName(),
+                                   /*implib=*/false,
+                                   /*realpath=*/true).c_str());
+
+  // Compute the comment.
+  std::ostringstream comment;
+  comment << "Link the " << this->GetVisibleTypeName() << " "
+          << targetOutputReal;
+
+  // Compute outputs.
+  cmNinjaDeps outputs;
+  outputs.push_back(targetOutputReal);
+
+  // Compute specific libraries to link with.
+  cmNinjaDeps explicitDeps = this->GetObjects(),
+              implicitDeps = this->ComputeLinkDeps();
+
+  this->GetLocalGenerator()->GetTargetFlags(vars["LINK_LIBRARIES"],
+                                            vars["FLAGS"],
+                                            vars["LINK_FLAGS"],
+                                            *this->GetTarget());
+
+  // Compute architecture specific link flags.  Yes, these go into a different
+  // variable for executables, probably due to a mistake made when duplicating
+  // code between the Makefile executable and library generators.
+  this->GetLocalGenerator()
+      ->AddArchitectureFlags(targetType == cmTarget::EXECUTABLE
+                               ? vars["FLAGS"]
+                               : vars["ARCH_FLAGS"],
+                             this->GetTarget(),
+                             this->TargetLinkLanguage,
+                             this->GetConfigName());
+  vars["SONAME"] = this->TargetNameSO;
+
+  if (targetType == cmTarget::SHARED_LIBRARY) {
+    std::string install_name_dir =
+      this->GetTarget()->GetInstallNameDirForBuildTree(this->GetConfigName());
+
+    if (!install_name_dir.empty()) {
+      vars["INSTALLNAME_DIR"] =
+        this->GetLocalGenerator()->Convert(install_name_dir.c_str(),
+            cmLocalGenerator::NONE,
+            cmLocalGenerator::SHELL, false);
+    }
+  }
+
+  std::vector<cmCustomCommand> *cmdLists[3] = {
+    &this->GetTarget()->GetPreBuildCommands(),
+    &this->GetTarget()->GetPreLinkCommands(),
+    &this->GetTarget()->GetPostBuildCommands()
+  };
+
+  std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
+  std::vector<std::string> *cmdLineLists[3] = {
+    &preLinkCmdLines,
+    &preLinkCmdLines,
+    &postBuildCmdLines
+  };
+
+  for (unsigned i = 0; i != 3; ++i) {
+    for (std::vector<cmCustomCommand>::const_iterator
+         ci = cmdLists[i]->begin();
+         ci != cmdLists[i]->end(); ++ci) {
+      this->GetLocalGenerator()->AppendCustomCommandLines(&*ci,
+                                                          *cmdLineLists[i]);
+    }
+  }
+
+  // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
+  // the link commands.
+  if (!preLinkCmdLines.empty())
+    preLinkCmdLines.push_back(std::string("cd ") +
+                              this->GetMakefile()->GetHomeOutputDirectory());
+
+  vars["PRE_LINK"] =
+    this->GetLocalGenerator()->BuildCommandLine(preLinkCmdLines);
+  std::string postBuildCmdLine =
+    this->GetLocalGenerator()->BuildCommandLine(postBuildCmdLines);
+
+  cmNinjaVars symlinkVars;
+  if (targetOutput == targetOutputReal) {
+    vars["POST_BUILD"] = postBuildCmdLine;
+  } else {
+    vars["POST_BUILD"] = ":";
+    symlinkVars["POST_BUILD"] = postBuildCmdLine;
+  }
+
+  // Write the build statement for this target.
+  cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+                                     comment.str(),
+                                     this->LanguageLinkerRule(),
+                                     outputs,
+                                     explicitDeps,
+                                     implicitDeps,
+                                     emptyDeps,
+                                     vars);
+
+  if (targetOutput != targetOutputReal) {
+    if (targetType == cmTarget::EXECUTABLE) {
+      cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+                                  "Create executable symlink " + targetOutput,
+                                         "CMAKE_SYMLINK_EXECUTABLE",
+                                         cmNinjaDeps(1, targetOutput),
+                                         cmNinjaDeps(1, targetOutputReal),
+                                         emptyDeps,
+                                         emptyDeps,
+                                         symlinkVars);
+    } else {
+      symlinkVars["SONAME"] = this->GetTargetFilePath(this->TargetNameSO);
+      cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+                                      "Create library symlink " + targetOutput,
+                                         "CMAKE_SYMLINK_LIBRARY",
+                                         cmNinjaDeps(1, targetOutput),
+                                         cmNinjaDeps(1, targetOutputReal),
+                                         emptyDeps,
+                                         emptyDeps,
+                                         symlinkVars);
+    }
+  }
+
+  // Add aliases for the file name and the target name.
+  this->GetGlobalGenerator()->AddTargetAlias(this->TargetNameOut,
+                                             this->GetTarget());
+  this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+                                             this->GetTarget());
+}
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
new file mode 100644
index 0000000..99f5a13
--- /dev/null
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -0,0 +1,47 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmNinjaNormalTargetGenerator_h
+#  define cmNinjaNormalTargetGenerator_h
+
+#  include "cmNinjaTargetGenerator.h"
+#  include "cmNinjaTypes.h"
+
+class cmSourceFile;
+
+class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
+{
+public:
+  cmNinjaNormalTargetGenerator(cmTarget* target);
+  ~cmNinjaNormalTargetGenerator();
+
+  void Generate();
+
+private:
+  std::string LanguageLinkerRule() const;
+  const char* GetVisibleTypeName() const;
+  void WriteLanguagesRules();
+  void WriteLinkRule();
+  void WriteLinkStatement();
+  std::vector<std::string> ComputeLinkCmd();
+
+private:
+  // Target name info.
+  std::string TargetNameOut;
+  std::string TargetNameSO;
+  std::string TargetNameReal;
+  std::string TargetNameImport;
+  std::string TargetNamePDB;
+  const char *TargetLinkLanguage;
+};
+
+#endif // ! cmNinjaNormalTargetGenerator_h
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
new file mode 100644
index 0000000..1e31044
--- /dev/null
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -0,0 +1,445 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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 "cmNinjaTargetGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmNinjaNormalTargetGenerator.h"
+#include "cmNinjaUtilityTargetGenerator.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+#include "cmComputeLinkInformation.h"
+#include "cmSourceFile.h"
+#include "cmCustomCommandGenerator.h"
+
+#include <algorithm>
+
+cmNinjaTargetGenerator *
+cmNinjaTargetGenerator::New(cmTarget* target)
+{
+  switch (target->GetType())
+    {
+      case cmTarget::EXECUTABLE:
+      case cmTarget::SHARED_LIBRARY:
+      case cmTarget::STATIC_LIBRARY:
+      case cmTarget::MODULE_LIBRARY:
+        return new cmNinjaNormalTargetGenerator(target);
+
+      case cmTarget::UTILITY:
+        return new cmNinjaUtilityTargetGenerator(target);;
+
+      case cmTarget::GLOBAL_TARGET: {
+        // We only want to process global targets that live in the home
+        // (i.e. top-level) directory.  CMake creates copies of these targets
+        // in every directory, which we don't need.
+        cmMakefile *mf = target->GetMakefile();
+        if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0)
+          return new cmNinjaUtilityTargetGenerator(target);
+        // else fallthrough
+      }
+
+      default:
+        return 0;
+    }
+}
+
+cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
+  : Target(target),
+    Makefile(target->GetMakefile()),
+    LocalGenerator(
+      static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
+    Objects()
+{
+}
+
+cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
+{
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
+{
+  return *this->GetGlobalGenerator()->GetBuildFileStream();
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const
+{
+  return *this->GetGlobalGenerator()->GetRulesFileStream();
+}
+
+cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
+{
+  return this->LocalGenerator->GetGlobalNinjaGenerator();
+}
+
+const char* cmNinjaTargetGenerator::GetConfigName() const
+{
+  return this->LocalGenerator->ConfigName.c_str();
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator.  Refactor it.
+const char* cmNinjaTargetGenerator::GetFeature(const char* feature)
+{
+  return this->Target->GetFeature(feature, this->GetConfigName());
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator.  Refactor it.
+bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature)
+{
+  return cmSystemTools::IsOn(this->GetFeature(feature));
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator.  Refactor it.
+void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags,
+                                             const char* lang)
+{
+  // Add language-specific flags.
+  this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName());
+
+  if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
+    {
+    this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+    }
+}
+
+// TODO: Most of the code is picked up from
+// void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink),
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
+// Refactor it.
+std::string
+cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
+                                              const std::string& language)
+{
+  std::string flags;
+
+  this->AddFeatureFlags(flags, language.c_str());
+
+  this->GetLocalGenerator()->AddArchitectureFlags(flags,
+                                                  this->GetTarget(),
+                                                  language.c_str(),
+                                                  this->GetConfigName());
+
+  // TODO: Fortran support.
+  // // Fortran-specific flags computed for this target.
+  // if(*l == "Fortran")
+  //   {
+  //   this->AddFortranFlags(flags);
+  //   }
+
+  // Add shared-library flags if needed.
+  {
+  bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
+                 (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
+  this->GetLocalGenerator()->AddSharedFlags(flags, language.c_str(), shared);
+  }
+
+  // TODO: Handle response file.
+  // Add include directory flags.
+  {
+  std::string includeFlags =
+    this->LocalGenerator->GetIncludeFlags(language.c_str(), false);
+  this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
+  }
+
+  // Append old-style preprocessor definition flags.
+  this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
+
+  // Add target-specific and source-specific flags.
+  this->LocalGenerator->AppendFlags(flags,
+                                   this->Target->GetProperty("COMPILE_FLAGS"));
+  this->LocalGenerator->AppendFlags(flags,
+                                    source->GetProperty("COMPILE_FLAGS"));
+
+  // TODO: Handle Apple frameworks.
+
+  return flags;
+}
+
+// TODO: Refactor with
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
+std::string
+cmNinjaTargetGenerator::
+ComputeDefines(cmSourceFile *source, const std::string& language)
+{
+  std::string defines;
+
+  // Add the export symbol definition for shared library objects.
+  if(const char* exportMacro = this->Target->GetExportMacro())
+    {
+    this->LocalGenerator->AppendDefines(defines, exportMacro,
+                                        language.c_str());
+    }
+
+  // Add preprocessor definitions for this target and configuration.
+  this->LocalGenerator->AppendDefines
+    (defines,
+     this->Makefile->GetProperty("COMPILE_DEFINITIONS"),
+     language.c_str());
+  this->LocalGenerator->AppendDefines
+    (defines,
+     this->Target->GetProperty("COMPILE_DEFINITIONS"),
+     language.c_str());
+  this->LocalGenerator->AppendDefines
+    (defines,
+     source->GetProperty("COMPILE_DEFINITIONS"),
+     language.c_str());
+  {
+  std::string defPropName = "COMPILE_DEFINITIONS_";
+  defPropName += cmSystemTools::UpperCase(this->GetConfigName());
+  this->LocalGenerator->AppendDefines
+    (defines,
+     this->Makefile->GetProperty(defPropName.c_str()),
+     language.c_str());
+  this->LocalGenerator->AppendDefines
+    (defines,
+     this->Target->GetProperty(defPropName.c_str()),
+     language.c_str());
+  this->LocalGenerator->AppendDefines
+    (defines,
+     source->GetProperty(defPropName.c_str()),
+     language.c_str());
+  }
+
+  return defines;
+}
+
+std::string cmNinjaTargetGenerator::ConvertToNinjaPath(const char *path) const
+{
+  return this->LocalGenerator->Convert(path,
+                                       cmLocalGenerator::HOME_OUTPUT,
+                                       cmLocalGenerator::MAKEFILE);
+}
+
+cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
+{
+  // Static libraries never depend on other targets for linking.
+  if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+    return cmNinjaDeps();
+
+  cmComputeLinkInformation* cli =
+    this->Target->GetLinkInformation(this->GetConfigName());
+  if(!cli)
+    return cmNinjaDeps();
+
+  const std::vector<std::string> &deps = cli->GetDepends();
+  cmNinjaDeps result(deps.size());
+  std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+  return result;
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetSourceFilePath(cmSourceFile* source) const
+{
+  return ConvertToNinjaPath(source->GetFullPath().c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetObjectFilePath(cmSourceFile* source) const
+{
+  std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+  if(!path.empty())
+    path += "/";
+  path += this->LocalGenerator->GetObjectFileName(*this->Target, *source);
+  return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
+{
+  std::string dir = this->Target->GetDirectory(this->GetConfigName());
+  return ConvertToNinjaPath(dir.c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetTargetFilePath(const std::string& name) const
+{
+  std::string path = this->GetTargetOutputDir();
+  if (path.empty() || path == ".")
+    return name;
+  path += "/";
+  path += name;
+  return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetName() const
+{
+  return this->Target->GetName();
+}
+
+void
+cmNinjaTargetGenerator
+::WriteLanguageRules(const std::string& language)
+{
+  this->GetRulesFileStream()
+    << "# Rules for language " << language << "\n\n";
+  this->WriteCompileRule(language);
+  this->GetRulesFileStream() << "\n";
+}
+
+void
+cmNinjaTargetGenerator
+::WriteCompileRule(const std::string& language)
+{
+  cmLocalGenerator::RuleVariables vars;
+  vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
+  vars.CMTarget = this->GetTarget();
+  std::string lang = language;
+  vars.Language = lang.c_str();
+  vars.Source = "$in";
+  vars.Object = "$out";
+  std::string flags = "$FLAGS";
+  vars.Defines = "$DEFINES";
+
+  std::string depfile;
+  std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
+  const char *depfileFlags =
+    this->GetMakefile()->GetDefinition(depfileFlagsName.c_str());
+  if (depfileFlags) {
+    std::string depfileFlagsStr = depfileFlags;
+    depfile = "$out.d";
+    cmSystemTools::ReplaceString(depfileFlagsStr, "<DEPFILE>",
+                                 depfile.c_str());
+    flags += " " + depfileFlagsStr;
+  }
+  vars.Flags = flags.c_str();
+
+  // Rule for compiling object file.
+  std::string compileCmdVar = "CMAKE_";
+  compileCmdVar += language;
+  compileCmdVar += "_COMPILE_OBJECT";
+  std::string compileCmd =
+    this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
+
+  this->GetLocalGenerator()->ExpandRuleVariables(compileCmd, vars);
+
+  // Write the rule for compiling file of the given language.
+  std::ostringstream comment;
+  comment << "Rule for compiling " << language << " files.";
+  std::ostringstream description;
+  description << "Building " << language << " object $out";
+  this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
+                                      compileCmd,
+                                      description.str(),
+                                      comment.str(),
+                                      depfile);
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatements()
+{
+  // Write comments.
+  cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+  this->GetBuildFileStream()
+    << "# Object build statements for "
+    << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+    << " target "
+    << this->GetTargetName()
+    << "\n\n";
+
+  // For each source files of this target.
+  for(std::vector<cmSourceFile*>::const_iterator i =
+        this->GetTarget()->GetSourceFiles().begin();
+      i != this->GetTarget()->GetSourceFiles().end();
+      ++i)
+    this->WriteObjectBuildStatement(*i);
+
+  this->GetBuildFileStream() << "\n";
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatement(cmSourceFile* source)
+{
+  if (cmCustomCommand *cc = source->GetCustomCommand())
+    this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+
+  cmNinjaDeps emptyDeps;
+
+  std::string comment;
+  const char* language = source->GetLanguage();
+  // If we cannot get the language this is probably a non-source file provided
+  // in the list (typically an header file).
+  if (!language) {
+    if (source->GetPropertyAsBool("EXTERNAL_OBJECT"))
+      this->Objects.push_back(this->GetSourceFilePath(source));
+    return;
+  }
+
+  if (source->GetPropertyAsBool("HEADER_FILE_ONLY"))
+    return;
+
+  std::string rule = this->LanguageCompilerRule(language);
+
+  cmNinjaDeps outputs;
+  std::string objectFileName = this->GetObjectFilePath(source);
+  outputs.push_back(objectFileName);
+  // Add this object to the list of object files.
+  this->Objects.push_back(objectFileName);
+
+  cmNinjaDeps explicitDeps;
+  std::string sourceFileName = this->GetSourceFilePath(source);
+  explicitDeps.push_back(sourceFileName);
+
+  // Ensure that the target dependencies are built before any source file in
+  // the target, using order-only dependencies.
+  cmNinjaDeps orderOnlyDeps;
+  this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
+
+  if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
+    std::vector<std::string> depList;
+    cmSystemTools::ExpandListArgument(objectDeps, depList);
+    std::transform(depList.begin(), depList.end(),
+                   std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+  }
+
+  // Add order-only dependency on any header file with a custom command.
+  {
+    const std::vector<cmSourceFile*>& sources =
+      this->GetTarget()->GetSourceFiles();
+    for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
+        si != sources.end(); ++si) {
+      if (!(*si)->GetLanguage()) {
+        if (cmCustomCommand* cc = (*si)->GetCustomCommand()) {
+          const std::vector<std::string>& ccoutputs = cc->GetOutputs();
+          std::transform(ccoutputs.begin(), ccoutputs.end(),
+                         std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+        }
+      }
+    }
+  }
+
+  // If the source file is GENERATED and does not have a custom command
+  // (either attached to this source file or another one), assume that one of
+  // the target dependencies, OBJECT_DEPENDS or header file custom commands
+  // will rebuild the file.
+  if (source->GetPropertyAsBool("GENERATED") && !source->GetCustomCommand() &&
+      !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
+    this->GetGlobalGenerator()->AddAssumedSourceDependencies(sourceFileName,
+                                                             orderOnlyDeps);
+  }
+
+  cmNinjaVars vars;
+  vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
+  vars["DEFINES"] = this->ComputeDefines(source, language);
+
+  cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+                                     comment,
+                                     rule,
+                                     outputs,
+                                     explicitDeps,
+                                     emptyDeps,
+                                     orderOnlyDeps,
+                                     vars);
+}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
new file mode 100644
index 0000000..cf47abf
--- /dev/null
+++ b/Source/cmNinjaTargetGenerator.h
@@ -0,0 +1,115 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmNinjaTargetGenerator_h
+#define cmNinjaTargetGenerator_h
+
+#include "cmStandardIncludes.h"
+#include "cmNinjaTypes.h"
+#include "cmLocalNinjaGenerator.h"
+
+class cmTarget;
+class cmGlobalNinjaGenerator;
+class cmGeneratedFileStream;
+class cmMakefile;
+class cmSourceFile;
+class cmCustomCommand;
+
+class cmNinjaTargetGenerator
+{
+public:
+  /// Create a cmNinjaTargetGenerator according to the @a target's type.
+  static cmNinjaTargetGenerator* New(cmTarget* target);
+
+  /// Build a NinjaTargetGenerator.
+  cmNinjaTargetGenerator(cmTarget* target);
+
+  /// Destructor.
+  virtual ~cmNinjaTargetGenerator();
+
+  virtual void Generate() = 0;
+
+  std::string GetTargetName() const;
+
+protected:
+  cmGeneratedFileStream& GetBuildFileStream() const;
+  cmGeneratedFileStream& GetRulesFileStream() const;
+
+  cmTarget* GetTarget() const
+  { return this->Target; }
+
+  cmLocalNinjaGenerator* GetLocalGenerator() const
+  { return this->LocalGenerator; }
+
+  cmGlobalNinjaGenerator* GetGlobalGenerator() const;
+
+  cmMakefile* GetMakefile() const
+  { return this->Makefile; }
+
+  const char* GetConfigName() const;
+
+  std::string LanguageCompilerRule(const std::string& lang) const
+  { return lang + "_COMPILER"; }
+
+  const char* GetFeature(const char* feature);
+  bool GetFeatureAsBool(const char* feature);
+  void AddFeatureFlags(std::string& flags, const char* lang);
+
+  /**
+   * Compute the flags for compilation of object files for a given @a language.
+   * @note Generally it is the value of the variable whose name is computed
+   *       by LanguageFlagsVarName().
+   */
+  std::string ComputeFlagsForObject(cmSourceFile *source,
+                                    const std::string& language);
+
+  std::string ComputeDefines(cmSourceFile *source,
+                             const std::string& language);
+
+  std::string ConvertToNinjaPath(const char *path) const;
+  cmLocalNinjaGenerator::map_to_ninja_path MapToNinjaPath() const {
+    return this->GetLocalGenerator()->MapToNinjaPath();
+  }
+
+  /// @return the list of link dependency for the given target @a target.
+  cmNinjaDeps ComputeLinkDeps() const;
+
+  /// @return the source file path for the given @a source.
+  std::string GetSourceFilePath(cmSourceFile* source) const;
+
+  /// @return the object file path for the given @a source.
+  std::string GetObjectFilePath(cmSourceFile* source) const;
+
+  /// @return the file path where the target named @a name is generated.
+  std::string GetTargetFilePath(const std::string& name) const;
+
+  /// @return the output path for the target.
+  virtual std::string GetTargetOutputDir() const;
+
+  void WriteLanguageRules(const std::string& language);
+  void WriteCompileRule(const std::string& language);
+  void WriteObjectBuildStatements();
+  void WriteObjectBuildStatement(cmSourceFile* source);
+  void WriteCustomCommandBuildStatement(cmCustomCommand *cc);
+
+  cmNinjaDeps GetObjects() const
+  { return this->Objects; }
+
+private:
+  cmTarget* Target;
+  cmMakefile* Makefile;
+  cmLocalNinjaGenerator* LocalGenerator;
+  /// List of object files for this target.
+  cmNinjaDeps Objects;
+};
+
+#endif // ! cmNinjaTargetGenerator_h
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
new file mode 100644
index 0000000..498f6b6
--- /dev/null
+++ b/Source/cmNinjaTypes.h
@@ -0,0 +1,19 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmNinjaTypes_h
+#  define cmNinjaTypes_h
+
+typedef std::vector<std::string> cmNinjaDeps;
+typedef std::map<std::string, std::string> cmNinjaVars;
+
+#endif // ! cmNinjaTypes_h
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
new file mode 100644
index 0000000..0a15834
--- /dev/null
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -0,0 +1,99 @@
+#include "cmNinjaUtilityTargetGenerator.h"
+#include "cmCustomCommand.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(cmTarget *target)
+  : cmNinjaTargetGenerator(target) {}
+
+cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
+
+void cmNinjaUtilityTargetGenerator::Generate()
+{
+  std::vector<std::string> commands;
+  cmNinjaDeps deps, outputs;
+
+  const std::vector<cmCustomCommand> *cmdLists[2] = {
+    &this->GetTarget()->GetPreBuildCommands(),
+    &this->GetTarget()->GetPostBuildCommands()
+  };
+
+  for (unsigned i = 0; i != 2; ++i) {
+    for (std::vector<cmCustomCommand>::const_iterator
+         ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
+      this->GetLocalGenerator()->AppendCustomCommandDeps(&*ci, deps);
+      this->GetLocalGenerator()->AppendCustomCommandLines(&*ci, commands);
+    }
+  }
+
+  const std::vector<cmSourceFile*>& sources =
+    this->GetTarget()->GetSourceFiles();
+  for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
+      source != sources.end(); ++source)
+    {
+    if(cmCustomCommand* cc = (*source)->GetCustomCommand())
+      {
+      this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+
+      // Depend on all custom command outputs.
+      const std::vector<std::string>& outputs = cc->GetOutputs();
+      std::transform(outputs.begin(), outputs.end(),
+                     std::back_inserter(deps), MapToNinjaPath());
+      }
+    }
+
+  this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
+  this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);
+
+  if (commands.empty()) {
+    cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+                                            "Utility command for "
+                                            + this->GetTargetName(),
+                                            outputs,
+                                            deps);
+  } else {
+    std::string command =
+      this->GetLocalGenerator()->BuildCommandLine(commands);
+    const char *echoStr = this->GetTarget()->GetProperty("EchoString");
+    std::string desc;
+    if (echoStr)
+      desc = echoStr;
+    else
+      desc = "Running utility command for " + this->GetTargetName();
+
+    // TODO: fix problematic global targets.  For now, search and replace the
+    // makefile vars.
+    cmSystemTools::ReplaceString(command, "$(CMAKE_SOURCE_DIR)",
+                         this->GetTarget()->GetMakefile()->GetHomeDirectory());
+    cmSystemTools::ReplaceString(command, "$(CMAKE_BINARY_DIR)",
+                   this->GetTarget()->GetMakefile()->GetHomeOutputDirectory());
+    cmSystemTools::ReplaceString(command, "$(ARGS)", "");
+
+    if (command.find('$') != std::string::npos)
+      return;
+
+    std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
+    utilCommandName += this->GetTargetName() + ".util";
+
+    this->GetGlobalGenerator()->WriteCustomCommandBuild(
+      command,
+      desc,
+      "Utility command for " + this->GetTargetName(),
+      cmNinjaDeps(1, utilCommandName),
+      deps);
+
+    cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+                                            "",
+                                            outputs,
+                                            cmNinjaDeps(1, utilCommandName),
+                                            cmNinjaDeps(),
+                                            cmNinjaDeps(),
+                                            cmNinjaVars());
+  }
+
+  this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+                                             this->GetTarget());
+}
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
new file mode 100644
index 0000000..8b82ce4
--- /dev/null
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -0,0 +1,30 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2011 Peter Collingbourne <peter at pcc.me.uk>
+  Copyright 2011 Nicolas Despres <nicolas.despres at 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.
+============================================================================*/
+#ifndef cmNinjaUtilityTargetGenerator_h
+#  define cmNinjaUtilityTargetGenerator_h
+
+#  include "cmNinjaTargetGenerator.h"
+#  include "cmNinjaTypes.h"
+
+class cmSourceFile;
+
+class cmNinjaUtilityTargetGenerator : public cmNinjaTargetGenerator
+{
+public:
+  cmNinjaUtilityTargetGenerator(cmTarget* target);
+  ~cmNinjaUtilityTargetGenerator();
+
+  void Generate();
+};
+
+#endif // ! cmNinjaUtilityTargetGenerator_h
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index d691f46..1d793d7 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -84,6 +84,10 @@
 #endif
 #include "cmGlobalUnixMakefileGenerator3.h"
 
+#ifdef CMAKE_USE_NINJA
+#  include "cmGlobalNinjaGenerator.h"
+#endif
+
 #if defined(CMAKE_HAVE_VS_GENERATORS)
 #include "cmCallVisualStudioMacro.h"
 #endif
@@ -2614,6 +2618,10 @@ void cmake::AddDefaultGenerators()
 #endif
   this->Generators[cmGlobalUnixMakefileGenerator3::GetActualName()] =
     &cmGlobalUnixMakefileGenerator3::New;
+#ifdef CMAKE_USE_NINJA
+  this->Generators[cmGlobalNinjaGenerator::GetActualName()] =
+    &cmGlobalNinjaGenerator::New;
+#endif
 #ifdef CMAKE_USE_XCODE
   this->Generators[cmGlobalXCodeGenerator::GetActualName()] =
     &cmGlobalXCodeGenerator::New;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2c5acd9..066926a 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -334,6 +334,15 @@ IF(BUILD_TESTING)
       --build-target car
       --test-command car
       )
+
+    IF(${CMAKE_TEST_GENERATOR} MATCHES "Ninja")
+      # The Ninja generator does not create a recursive build system.  Start
+      # from the root directory.
+      SET(SubProject_SUBDIR)
+    ELSE()
+      SET(SubProject_SUBDIR "/foo")
+    ENDIF()
+
     # For stage 2, do not run cmake again.
     # Then build the foo sub project which should build
     # the bar library which should be referenced because
@@ -341,13 +350,14 @@ IF(BUILD_TESTING)
     # directly in the foo sub project
     ADD_TEST(SubProject-Stage2  ${CMAKE_CTEST_COMMAND}
       --build-and-test
-      "${CMake_SOURCE_DIR}/Tests/SubProject/foo"
-      "${CMake_BINARY_DIR}/Tests/SubProject/foo"
+      "${CMake_SOURCE_DIR}/Tests/SubProject${SubProject_SUBDIR}"
+      "${CMake_BINARY_DIR}/Tests/SubProject${SubProject_SUBDIR}"
       --build-generator ${CMAKE_TEST_GENERATOR}
       --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
       --build-nocmake
       --build-project foo
       --build-target foo
+      --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo"
       --test-command foo
       )
     SET_TESTS_PROPERTIES ( SubProject-Stage2 PROPERTIES DEPENDS SubProject)
diff --git a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
index c7cc090..c362e79 100644
--- a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
+++ b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
@@ -24,6 +24,12 @@ IF ("${PROJECT_SOURCE_DIR}" STREQUAL "${ANOTHER_PROJ_SOURCE_DIR}")
     MATH(EXPR MAXPATH "${MAXPATH} - 46")
   ENDIF()
 
+  # Ninja imposes a maximum path component count of 30.  Permit more
+  # path components in the source path.
+  IF(${CMAKE_GENERATOR} MATCHES "Ninja")
+    MATH(EXPR MAXPATH "${MAXPATH} - 44")
+  ENDIF()
+
   # MAXPATH less 25 for last /and/deeper/simple.cxx part and small safety
   MATH(EXPR MAXPATH "${MAXPATH} - 25")
   STRING(LENGTH "${DEEPDIR}" DEEPDIR_LEN)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7eb8d9036c73784f14da9d8381023c1e26df1275
commit 7eb8d9036c73784f14da9d8381023c1e26df1275
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Tue Nov 15 04:39:52 2011 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Thu Feb 2 23:36:49 2012 +0000

    Provide dependency file flags to generator
    
    Causes compiler modules (currently only GNU) to set a
    CMAKE_DEPFILE_FLAGS_${lang} variable, which communicates to
    the generator the flags required to cause the compiler to create
    dependency files.

diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 8d6f5df..bdcaf9d 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -24,6 +24,15 @@ macro(__compiler_gnu lang)
   set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
 
+  # Older versions of gcc (< 4.5) contain a bug causing them to report a missing
+  # header file as a warning if depfiles are enabled, causing check_header_file
+  # tests to always succeed.  Work around this by disabling dependency tracking
+  # in try_compile mode.
+  GET_PROPERTY(_IN_TC GLOBAL PROPERTY IN_TRY_COMPILE)
+  if(NOT _IN_TC OR CMAKE_FORCE_DEPFILES)
+    set(CMAKE_DEPFILE_FLAGS_${lang} "-MMD -MF <DEPFILE>")
+  endif()
+
   # Initial configuration flags.
   set(CMAKE_${lang}_FLAGS_INIT "")
   set(CMAKE_${lang}_FLAGS_DEBUG_INIT "-g")
diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 31392b5..aa32d67 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -40,6 +40,8 @@ if("${CMAKE_GENERATOR}" MATCHES "Make")
 endif()
 list(APPEND _cmake_options "-DTEST_LINK_DEPENDS=${TEST_LINK_DEPENDS}")
 
+list(APPEND _cmake_options "-DCMAKE_FORCE_DEPFILES=1")
+
 file(MAKE_DIRECTORY ${BuildDepends_BINARY_DIR}/Project)
 message("Creating Project/foo.cxx")
 write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4468edf12b0b87e32768fcdce7abd30afddcad7b
commit 4468edf12b0b87e32768fcdce7abd30afddcad7b
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Fri Nov 11 19:11:38 2011 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Thu Feb 2 23:36:42 2012 +0000

    Add executable with exports flag support to cmLocalGenerator::GetTargetFlags

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index ffbeb48..1cfefed 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1583,6 +1583,16 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
           this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
         linkFlags += " ";
         }
+      if (target.IsExecutableWithExports())
+        {
+        std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
+        exportFlagVar += linkLanguage;
+        exportFlagVar += "_FLAG";
+
+        linkFlags +=
+          this->Makefile->GetSafeDefinition(exportFlagVar.c_str());
+        linkFlags += " ";
+        }
       const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
       if(targetLinkFlags)
         {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2cd36550b073fd4f559f7edc5a5170af534f1068
commit 2cd36550b073fd4f559f7edc5a5170af534f1068
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Fri Nov 11 05:00:35 2011 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Thu Feb 2 23:04:38 2012 +0000

    Add cmSystemTools::TrimWhitespace function

diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 02060ca..3e927cf 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -196,6 +196,20 @@ std::string cmSystemTools::EscapeQuotes(const char* str)
   return result;
 }
 
+std::string cmSystemTools::TrimWhitespace(const std::string& s)
+{
+  std::string::const_iterator start = s.begin();
+  while(start != s.end() && *start == ' ')
+    ++start;
+  if (start == s.end())
+    return "";
+
+  std::string::const_iterator stop = s.end()-1;
+  while(*stop == ' ')
+    --stop;
+  return std::string(start, stop+1);
+}
+
 void cmSystemTools::Error(const char* m1, const char* m2,
                           const char* m3, const char* m4)
 {
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 2137340..88ae1c0 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -49,6 +49,11 @@ public:
   ///! Escape quotes in a string.
   static std::string EscapeQuotes(const char* str);
 
+  /**
+   * Returns a string that has whitespace removed from the start and the end.
+   */
+  static std::string TrimWhitespace(const std::string& s);
+
   typedef  void (*ErrorCallback)(const char*, const char*, bool&, void*);
   /**
    *  Set the function used by GUI's to display error messages

-----------------------------------------------------------------------

Summary of changes:
 ...UnixFindMake.cmake => CMakeNinjaFindMake.cmake} |    5 +-
 Modules/Compiler/GNU.cmake                         |    9 +
 Modules/ExternalProject.cmake                      |   19 +-
 Source/CMakeLists.txt                              |   18 +
 Source/cmGlobalNinjaGenerator.cxx                  |  774 ++++++++++++++++++++
 Source/cmGlobalNinjaGenerator.h                    |  329 +++++++++
 Source/cmLocalGenerator.cxx                        |   10 +
 Source/cmLocalNinjaGenerator.cxx                   |  413 +++++++++++
 Source/cmLocalNinjaGenerator.h                     |  134 ++++
 Source/cmNinjaNormalTargetGenerator.cxx            |  430 +++++++++++
 Source/cmNinjaNormalTargetGenerator.h              |   47 ++
 Source/cmNinjaTargetGenerator.cxx                  |  445 +++++++++++
 Source/cmNinjaTargetGenerator.h                    |  115 +++
 Source/{cmBreakCommand.cxx => cmNinjaTypes.h}      |   16 +-
 Source/cmNinjaUtilityTargetGenerator.cxx           |   99 +++
 ...athWidget.h => cmNinjaUtilityTargetGenerator.h} |   24 +-
 Source/cmSystemTools.cxx                           |   14 +
 Source/cmSystemTools.h                             |    5 +
 Source/cmake.cxx                                   |    8 +
 Source/kwsys/kwsysDateStamp.cmake                  |    2 +-
 Tests/BuildDepends/CMakeLists.txt                  |    2 +
 Tests/CMakeLists.txt                               |   14 +-
 Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt |    6 +
 23 files changed, 2911 insertions(+), 27 deletions(-)
 copy Modules/{CMakeUnixFindMake.cmake => CMakeNinjaFindMake.cmake} (83%)
 create mode 100644 Source/cmGlobalNinjaGenerator.cxx
 create mode 100644 Source/cmGlobalNinjaGenerator.h
 create mode 100644 Source/cmLocalNinjaGenerator.cxx
 create mode 100644 Source/cmLocalNinjaGenerator.h
 create mode 100644 Source/cmNinjaNormalTargetGenerator.cxx
 create mode 100644 Source/cmNinjaNormalTargetGenerator.h
 create mode 100644 Source/cmNinjaTargetGenerator.cxx
 create mode 100644 Source/cmNinjaTargetGenerator.h
 copy Source/{cmBreakCommand.cxx => cmNinjaTypes.h} (63%)
 create mode 100644 Source/cmNinjaUtilityTargetGenerator.cxx
 copy Source/{CursesDialog/cmCursesFilePathWidget.h => cmNinjaUtilityTargetGenerator.h} (51%)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list