[Cmake-commits] CMake branch, next, updated. v2.8.7-3237-g1061124

Brad King brad.king at kitware.com
Mon Mar 19 09:29:01 EDT 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  10611245f56fb32c2b872b681f5da0be98c3358f (commit)
       via  848520859afebb3353a91561725e4e96b48a6c35 (commit)
       via  df847671b43f35162570db1e6f2801bc3b2de11a (commit)
       via  48eb7fc7d7b3fa5570a7b32968fa2cff07bf6fe7 (commit)
       via  bba37dd51753165ce3ade61badb61c07e1058e90 (commit)
       via  ac800f49d07337df79565c77fe0847222ade520b (commit)
       via  9a0d5a828a8f47b4388dbeab8bde9921ee3b7146 (commit)
       via  d40eebd89df7d0a9bfa12d12c7a11d61e8cfec1a (commit)
       via  8c634330db7988c56d0327d60c8056460634974b (commit)
       via  dbe3dce54670d774fd43e061be673b11e1dd18de (commit)
       via  f1bb08f55b1ee0e8ae72d66289ad89ad27d75701 (commit)
       via  7a6b5f465122a9da1f9439ec3cec461e1c0c999c (commit)
       via  80ff2102a41117fc829ad64c7c963bd0858a221b (commit)
       via  d2731a376cce3044b507bfaf4427d89f0a03d2cf (commit)
       via  eabc9b0bc5d2dc237d247d1e86fb0818b22d31c0 (commit)
       via  bada88e8e45640afa5ef063aeab180fd6f1cfee4 (commit)
       via  54bd175eea66704a879fc72278cdbb49efdd801c (commit)
       via  a1a30340a2eb0174f9f6911ee1e2cf4a36eaac96 (commit)
       via  21997cea4d8694077e8bcf9ba4cbd3d96a3f163c (commit)
       via  3b847415154b13e401bf9f71042578ad21c9c1c9 (commit)
       via  adb54f3dbf802f643c8af9f8de6f67f24804dd22 (commit)
       via  895914881be32f862dee638a0a86313366f9b7b4 (commit)
       via  70c39c845f2f2909413d8bcb19a6b72e19ff83c4 (commit)
       via  0643fee2fe92b7dccc4e63be7329f6da96f2e61f (commit)
       via  43b1d8bad0cf78148e4d6e7b4013850731d5a824 (commit)
       via  cea03e632b71589592660614a63ff102ba923de8 (commit)
       via  9362440a0b9193c417b42c50495d0a3ea6e098c4 (commit)
       via  99856d537c996544bf495f33e6b058d83af4c6b7 (commit)
       via  f999a59afe804063cebf4dd89ef99662829bf3e4 (commit)
       via  7fb2bb3e8b0dc7bc718aadc4ab9a74cb7fdb656e (commit)
       via  5d19e8aa6aac75fb08897aece8aa5545360aeeb2 (commit)
       via  bfe56f6802fc7db7f8e824aab8881be6cf23ccef (commit)
       via  69984906ef41ed9549d4acd75590c67030281df9 (commit)
       via  6dd410c2b98d5152adf69b5986b5f25d4dcd9e2a (commit)
      from  73a126367cdbcc4ef8664afa18c2008ef80346ef (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=10611245f56fb32c2b872b681f5da0be98c3358f
commit 10611245f56fb32c2b872b681f5da0be98c3358f
Merge: 73a1263 8485208
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Mar 19 09:28:57 2012 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Mar 19 09:28:57 2012 -0400

    Merge topic 'ninja-generator' into next
    
    8485208 Ninja: shell escape $(CMAKE_SOURCE_DIR) and $(CMAKE_BINARY_DIR)
    df84767 Ninja: add support for OBJECT_OUTPUTS, fix PrecompiledHeader test case
    48eb7fc Ninja: Avoid using 'this' in member initializers
    bba37dd Ninja: Fix for PDB files with spaces in the path.
    ac800f4 Ninja: Constify use of cmCustomCommand
    9a0d5a8 Ninja: add /DEF: flag to linker call
    d40eebd Ninja: Add a cache option CMAKE_ENABLE_NINJA to enable the ninja generator.
    8c63433 Ninja: Add friend struct so it can access the private ConvertToNinjaPath.
    dbe3dce Ninja: add .def file support
    f1bb08f Ninja: ensure the output dir exists at compile time
    7a6b5f4 Ninja: Remove an unnecessary variable
    80ff210 Ninja: Use cmSystemTools::ExpandListArgument to split compile/link commands
    d2731a3 Ninja: Add a missed license header
    eabc9b0 Ninja: CMake: Adapt Ninja generator for per-target include dirs
    bada88e Merge branch 'target-include-directories' into ninja-generator
    54bd175 Ninja: windows msvc: create for each target a .pdb file
    ...


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=848520859afebb3353a91561725e4e96b48a6c35
commit 848520859afebb3353a91561725e4e96b48a6c35
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sat Mar 17 20:55:09 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sat Mar 17 23:16:40 2012 +0000

    Ninja: shell escape $(CMAKE_SOURCE_DIR) and $(CMAKE_BINARY_DIR)

diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 8eeca77..9c2fd13 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -78,10 +78,18 @@ void cmNinjaUtilityTargetGenerator::Generate()
 
     // 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,
+      "$(CMAKE_SOURCE_DIR)",
+      this->GetLocalGenerator()->ConvertToOutputFormat(
+        this->GetTarget()->GetMakefile()->GetHomeDirectory(),
+        cmLocalGenerator::SHELL).c_str());
+    cmSystemTools::ReplaceString(
+      command,
+      "$(CMAKE_BINARY_DIR)",
+      this->GetLocalGenerator()->ConvertToOutputFormat(
+        this->GetTarget()->GetMakefile()->GetHomeOutputDirectory(),
+        cmLocalGenerator::SHELL).c_str());
     cmSystemTools::ReplaceString(command, "$(ARGS)", "");
 
     if (command.find('$') != std::string::npos)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=df847671b43f35162570db1e6f2801bc3b2de11a
commit df847671b43f35162570db1e6f2801bc3b2de11a
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sat Mar 17 20:49:36 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sat Mar 17 23:16:40 2012 +0000

    Ninja: add support for OBJECT_OUTPUTS, fix PrecompiledHeader test case

diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index b9f997d..9acbc67 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -475,6 +475,17 @@ cmNinjaTargetGenerator
                                      emptyDeps,
                                      orderOnlyDeps,
                                      vars);
+
+  if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
+    std::vector<std::string> outputList;
+    cmSystemTools::ExpandListArgument(objectOutputs, outputList);
+    std::transform(outputList.begin(), outputList.end(), outputList.begin(),
+                   MapToNinjaPath());
+    cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+                                            "Additional output files.",
+                                            outputList,
+                                            outputs);
+  }
 }
 
 //----------------------------------------------------------------------------
diff --git a/Tests/PrecompiledHeader/CMakeLists.txt b/Tests/PrecompiledHeader/CMakeLists.txt
index d423cae..3374e32 100644
--- a/Tests/PrecompiledHeader/CMakeLists.txt
+++ b/Tests/PrecompiledHeader/CMakeLists.txt
@@ -47,7 +47,8 @@ SET_SOURCE_FILES_PROPERTIES(foo_precompile.c PROPERTIES
 
 # Setup dependencies for precompiled header creation and use.  The VS
 # IDE takes care of this automatically.
-IF("${CMAKE_GENERATOR}" MATCHES "Makefile")
+IF("${CMAKE_GENERATOR}" MATCHES "Makefile" OR
+   "${CMAKE_GENERATOR}" MATCHES "Ninja")
   # This source file creates the precompiled header as a side-effect.
   SET_SOURCE_FILES_PROPERTIES(foo_precompile.c PROPERTIES
     OBJECT_OUTPUTS "${PCH_DIR}/foo_precompiled.pch")

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=48eb7fc7d7b3fa5570a7b32968fa2cff07bf6fe7
commit 48eb7fc7d7b3fa5570a7b32968fa2cff07bf6fe7
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Mar 16 09:58:32 2012 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Mar 16 10:16:55 2012 -0400

    Ninja: Avoid using 'this' in member initializers
    
    VS complains
    
     warning C4355: 'this' : used in base member initializer list
    
    so initialize the member in the constructor body instead.

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 439f734..9242181 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -27,8 +27,8 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
   , TargetNameReal()
   , TargetNameImport()
   , TargetNamePDB()
-  , TargetLinkLanguage(target->GetLinkerLanguage(this->GetConfigName()))
 {
+  this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
   if (target->GetType() == cmTarget::EXECUTABLE)
     target->GetExecutableNames(this->TargetNameOut,
                                this->TargetNameReal,

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bba37dd51753165ce3ade61badb61c07e1058e90
commit bba37dd51753165ce3ade61badb61c07e1058e90
Author:     Bill Hoffman <bill.hoffman at kitware.com>
AuthorDate: Tue Mar 13 17:01:25 2012 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Mar 16 10:16:45 2012 -0400

    Ninja: Fix for PDB files with spaces in the path.
    
    This calls ConvertToOutputFormat on the PDB paths for pdb file paths
    used in both library creation and the building of object files.

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index af7bcd6..439f734 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -372,7 +372,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
       targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
   }
 
-  vars["TARGET_PDB"] = this->GetTargetPDB();
+  vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+    this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
 
   std::vector<cmCustomCommand> *cmdLists[3] = {
     &this->GetTarget()->GetPreBuildCommands(),
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 8fa367f..b9f997d 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -464,7 +464,8 @@ cmNinjaTargetGenerator
   cmNinjaVars vars;
   vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
   vars["DEFINES"] = this->ComputeDefines(source, language);
-  vars["TARGET_PDB"] = this->GetTargetPDB();
+  vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+    this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
 
   cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
                                      comment,

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ac800f49d07337df79565c77fe0847222ade520b
commit ac800f49d07337df79565c77fe0847222ade520b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Mar 13 09:17:46 2012 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Mar 13 11:23:14 2012 -0400

    Ninja: Constify use of cmCustomCommand
    
    The generator never needs to modify custom command instances.

diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index e77252f..39df826 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -270,7 +270,7 @@ private:
 
   /// Called when we have seen the given custom command.  Returns true
   /// if we has seen it before.
-  bool SeenCustomCommand(cmCustomCommand *cc) {
+  bool SeenCustomCommand(cmCustomCommand const *cc) {
     return !this->CustomCommands.insert(cc).second;
   }
 
@@ -315,7 +315,7 @@ private:
   cmNinjaDeps AllDependencies;
 
   /// The set of custom commands we have seen.
-  std::set<cmCustomCommand *> CustomCommands;
+  std::set<cmCustomCommand const*> CustomCommands;
 
   /// The set of custom command outputs we have seen.
   std::set<std::string> CustomCommandOutputs;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index ea03cbb..78072b5 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -343,8 +343,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
 }
 
 void
-cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(cmCustomCommand *cc,
-                                            const cmNinjaDeps& orderOnlyDeps)
+cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
+  cmCustomCommand const *cc, const cmNinjaDeps& orderOnlyDeps)
 {
   if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc))
     return;
@@ -383,7 +383,7 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(cmCustomCommand *cc,
   }
 }
 
-void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand* cc,
+void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
                                                    cmTarget* target)
 {
   this->CustomCommandTargets[cc].insert(target);
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index e9bbf43..28b431d 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -118,17 +118,17 @@ private:
   void AppendCustomCommandLines(const cmCustomCommand *cc,
                                 std::vector<std::string> &cmdLines);
   void WriteCustomCommandRule();
-  void WriteCustomCommandBuildStatement(cmCustomCommand *cc,
+  void WriteCustomCommandBuildStatement(cmCustomCommand const *cc,
                                         const cmNinjaDeps& orderOnlyDeps);
 
-  void AddCustomCommandTarget(cmCustomCommand* cc, cmTarget* target);
+  void AddCustomCommandTarget(cmCustomCommand const* cc, cmTarget* target);
   void WriteCustomCommandBuildStatements();
 
 private:
   std::string ConfigName;
   std::string HomeRelativeOutputPath;
 
-  typedef std::map<cmCustomCommand*, std::set<cmTarget*> >
+  typedef std::map<cmCustomCommand const*, std::set<cmTarget*> >
     CustomCommandTargetMap;
   CustomCommandTargetMap CustomCommandTargets;
 };

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9a0d5a828a8f47b4388dbeab8bde9921ee3b7146
commit 9a0d5a828a8f47b4388dbeab8bde9921ee3b7146
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sat Mar 10 12:19:18 2012 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Mar 13 11:20:29 2012 -0400

    Ninja: add /DEF: flag to linker call

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 9e05b4c..af7bcd6 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -341,6 +341,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
                                             vars["LINK_FLAGS"],
                                             *this->GetTarget());
 
+  this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]);
+
   // 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.

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d40eebd89df7d0a9bfa12d12c7a11d61e8cfec1a
commit d40eebd89df7d0a9bfa12d12c7a11d61e8cfec1a
Author:     Bill Hoffman <bill.hoffman at kitware.com>
AuthorDate: Fri Mar 9 14:28:21 2012 -0500
Commit:     Bill Hoffman <bill.hoffman at kitware.com>
CommitDate: Fri Mar 9 14:28:21 2012 -0500

    Ninja: Add a cache option CMAKE_ENABLE_NINJA to enable the ninja generator.
    
    Make the option default to on, for platforms where CMake passes
    all tests with the ninja generator.  This is currently only Linux.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index eb4327c..18f9b8b 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,7 +353,18 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
-if(NOT WIN32)
+# turn on Ninja by default
+set(_CMAKE_DEFAULT_NINJA_VALUE TRUE)
+# turn it off for platforms where it does not pass all the
+# tests
+if(WIN32 OR APPLE)
+  SET(_CMAKE_DEFAULT_NINJA_VALUE FALSE)
+endif()
+SET(CMAKE_ENABLE_NINJA ${_CMAKE_DEFAULT_NINJA_VALUE} CACHE BOOL
+    "Enable the ninja generator for CMake. currently not fully working for Windows or OSX")
+MARK_AS_ADVANCED(CMAKE_ENABLE_NINJA)
+IF(CMAKE_ENABLE_NINJA)
+  MESSAGE(STATUS "Enable ninja generator.")
   SET(SRCS ${SRCS}
     cmGlobalNinjaGenerator.cxx
     cmGlobalNinjaGenerator.h
@@ -368,7 +379,9 @@ if(NOT WIN32)
     cmNinjaUtilityTargetGenerator.h
     )
   ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
-endif()
+ELSE()
+  MESSAGE(STATUS "Disable ninja generator.")
+ENDIF()
 
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8c634330db7988c56d0327d60c8056460634974b
commit 8c634330db7988c56d0327d60c8056460634974b
Author:     David Cole <david.cole at kitware.com>
AuthorDate: Wed Mar 7 16:07:45 2012 -0500
Commit:     David Cole <david.cole at kitware.com>
CommitDate: Wed Mar 7 16:24:34 2012 -0500

    Ninja: Add friend struct so it can access the private ConvertToNinjaPath.
    
    The HP aCC compiler is apparently more strict than all our other
    dashboard compilers with respect to complaining about this.

diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 8ef4d28..e9bbf43 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -95,6 +95,8 @@ private:
 
   std::string ConvertToNinjaPath(const char *path);
 
+  struct map_to_ninja_path;
+  friend struct map_to_ninja_path;
   struct map_to_ninja_path {
     cmLocalNinjaGenerator *LocalGenerator;
     map_to_ninja_path(cmLocalNinjaGenerator *LocalGen)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dbe3dce54670d774fd43e061be673b11e1dd18de
commit dbe3dce54670d774fd43e061be673b11e1dd18de
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Tue Mar 6 23:41:40 2012 +0100
Commit:     David Cole <david.cole at kitware.com>
CommitDate: Wed Mar 7 16:24:34 2012 -0500

    Ninja: add .def file support

diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 3f8644e..e77252f 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -325,6 +325,8 @@ private:
 
   typedef std::map<std::string, cmTarget*> TargetAliasMap;
   TargetAliasMap TargetAliases;
+
+  static cmLocalGenerator* LocalGenerator;
 };
 
 #endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index aa3286c..3920b89 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1503,7 +1503,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
             linkFlags +=
               this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
             linkFlags += this->Convert(sf->GetFullPath().c_str(),
-                                       START_OUTPUT, SHELL);
+                                       FULL, SHELL);
             linkFlags += " ";
             }
           }
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index f4069c7..9e05b4c 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -285,6 +285,7 @@ cmNinjaNormalTargetGenerator
       default:
         assert(0 && "Unexpected target type");
       }
+
       const char *linkCmd =
         this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
       cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d0b4156..8fa367f 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -229,6 +229,13 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   const std::vector<std::string> &deps = cli->GetDepends();
   cmNinjaDeps result(deps.size());
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+
+  // Add a dependency on the link definitions file, if any.
+  if(!this->ModuleDefinitionFile.empty())
+    {
+    result.push_back(this->ModuleDefinitionFile);
+    }
+
   return result;
 }
 
@@ -328,6 +335,7 @@ cmNinjaTargetGenerator
   }
   vars.Flags = flags.c_str();
 
+
   // Rule for compiling object file.
   std::string compileCmdVar = "CMAKE_";
   compileCmdVar += language;
@@ -395,6 +403,8 @@ cmNinjaTargetGenerator
   if (!language) {
     if (source->GetPropertyAsBool("EXTERNAL_OBJECT"))
       this->Objects.push_back(this->GetSourceFilePath(source));
+    if(cmSystemTools::UpperCase(source->GetExtension()) == "DEF")
+      this->ModuleDefinitionFile = GetSourceFilePath(source);
     return;
   }
 
@@ -465,3 +475,29 @@ cmNinjaTargetGenerator
                                      orderOnlyDeps,
                                      vars);
 }
+
+//----------------------------------------------------------------------------
+void
+cmNinjaTargetGenerator
+::AddModuleDefinitionFlag(std::string& flags)
+{
+  if(this->ModuleDefinitionFile.empty())
+    {
+    return;
+    }
+
+  // TODO: Create a per-language flag variable.
+  const char* defFileFlag =
+    this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+  if(!defFileFlag)
+    {
+    return;
+    }
+
+  // Append the flag and value.  Use ConvertToLinkReference to help
+  // vs6's "cl -link" pass it to the linker.
+  std::string flag = defFileFlag;
+  flag += (this->LocalGenerator->ConvertToLinkReference(
+             this->ModuleDefinitionFile.c_str()));
+  this->LocalGenerator->AppendFlags(flags, flag.c_str());
+}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index f9270a2..3e70a2c 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -107,12 +107,18 @@ protected:
   cmNinjaDeps GetObjects() const
   { return this->Objects; }
 
+  // Helper to add flag for windows .def file.
+  void AddModuleDefinitionFlag(std::string& flags);
+
 private:
   cmTarget* Target;
   cmMakefile* Makefile;
   cmLocalNinjaGenerator* LocalGenerator;
   /// List of object files for this target.
   cmNinjaDeps Objects;
+
+  // The windows module definition source file (.def), if any.
+  std::string ModuleDefinitionFile;
 };
 
 #endif // ! cmNinjaTargetGenerator_h

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f1bb08f55b1ee0e8ae72d66289ad89ad27d75701
commit f1bb08f55b1ee0e8ae72d66289ad89ad27d75701
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Thu Feb 23 19:39:54 2012 +0100
Commit:     David Cole <david.cole at kitware.com>
CommitDate: Wed Mar 7 16:24:33 2012 -0500

    Ninja: ensure the output dir exists at compile time

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 88f6f87..f4069c7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -42,6 +42,11 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
                             this->TargetNameImport,
                             this->TargetNamePDB,
                             GetLocalGenerator()->GetConfigName());
+
+  // on Windows the output dir is already needed at compile time
+  // ensure the directory exists (OutDir test)
+  std::string outpath = target->GetDirectory(this->GetConfigName());
+  cmSystemTools::MakeDirectory(outpath.c_str());
 }
 
 cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7a6b5f465122a9da1f9439ec3cec461e1c0c999c
commit 7a6b5f465122a9da1f9439ec3cec461e1c0c999c
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Tue Feb 28 02:55:24 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Tue Feb 28 02:55:32 2012 +0000

    Ninja: Remove an unnecessary variable

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 613c7b5..88f6f87 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -237,7 +237,6 @@ cmNinjaNormalTargetGenerator
       }
 
       // We have archive link commands set. First, delete the existing archive.
-      std::vector<std::string> linkCmds;
       std::string cmakeCommand =
         this->GetLocalGenerator()->ConvertToOutputFormat(
           this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=80ff2102a41117fc829ad64c7c963bd0858a221b
commit 80ff2102a41117fc829ad64c7c963bd0858a221b
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Mon Feb 27 04:05:31 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Mon Feb 27 04:05:38 2012 +0000

    Ninja: Use cmSystemTools::ExpandListArgument to split compile/link commands

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 6e08bca..613c7b5 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -219,6 +219,7 @@ std::vector<std::string>
 cmNinjaNormalTargetGenerator
 ::ComputeLinkCmd()
 {
+  std::vector<std::string> linkCmds;
   cmTarget::TargetType targetType = this->GetTarget()->GetType();
   switch (targetType) {
     case cmTarget::STATIC_LIBRARY: {
@@ -230,7 +231,8 @@ cmNinjaNormalTargetGenerator
       if (const char *linkCmd =
             this->GetMakefile()->GetDefinition(linkCmdVar.c_str()))
         {
-        return std::vector<std::string>(1, linkCmd);
+        cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+        return linkCmds;
         }
       }
 
@@ -249,7 +251,7 @@ cmNinjaNormalTargetGenerator
       linkCmdVar += "_ARCHIVE_CREATE";
       const char *linkCmd =
         this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
-      linkCmds.push_back(linkCmd);
+      cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
       }
       {
       std::string linkCmdVar = "CMAKE_";
@@ -257,7 +259,7 @@ cmNinjaNormalTargetGenerator
       linkCmdVar += "_ARCHIVE_FINISH";
       const char *linkCmd =
         this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
-      linkCmds.push_back(linkCmd);
+      cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
       }
       return linkCmds;
     }
@@ -281,7 +283,8 @@ cmNinjaNormalTargetGenerator
       }
       const char *linkCmd =
         this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
-      return std::vector<std::string>(1, linkCmd);
+      cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+      return linkCmds;
     }
     default:
       assert(0 && "Unexpected target type");
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index c776fcf..d0b4156 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -334,8 +334,15 @@ cmNinjaTargetGenerator
   compileCmdVar += "_COMPILE_OBJECT";
   std::string compileCmd =
     this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
+  std::vector<std::string> compileCmds;
+  cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
 
-  this->GetLocalGenerator()->ExpandRuleVariables(compileCmd, vars);
+  for (std::vector<std::string>::iterator i = compileCmds.begin();
+       i != compileCmds.end(); ++i)
+    this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+
+  std::string cmdLine =
+    this->GetLocalGenerator()->BuildCommandLine(compileCmds);
 
   // Write the rule for compiling file of the given language.
   std::ostringstream comment;
@@ -343,7 +350,7 @@ cmNinjaTargetGenerator
   std::ostringstream description;
   description << "Building " << language << " object $out";
   this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
-                                      compileCmd,
+                                      cmdLine,
                                       description.str(),
                                       comment.str(),
                                       depfile);

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d2731a376cce3044b507bfaf4427d89f0a03d2cf
commit d2731a376cce3044b507bfaf4427d89f0a03d2cf
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Thu Feb 23 22:25:03 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Mon Feb 27 02:41:00 2012 +0000

    Ninja: Add a missed license header

diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index bf8194d..8eeca77 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -1,3 +1,15 @@
+/*============================================================================
+  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 "cmNinjaUtilityTargetGenerator.h"
 #include "cmCustomCommand.h"
 #include "cmGeneratedFileStream.h"

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eabc9b0bc5d2dc237d247d1e86fb0818b22d31c0
commit eabc9b0bc5d2dc237d247d1e86fb0818b22d31c0
Author:     David Cole <david.cole at kitware.com>
AuthorDate: Wed Feb 22 16:31:00 2012 -0500
Commit:     David Cole <david.cole at kitware.com>
CommitDate: Wed Feb 22 16:31:00 2012 -0500

    Ninja: CMake: Adapt Ninja generator for per-target include dirs
    
    The confluence of the ninja-generator and target-include-directories
    branches conspired to produce a nice little compiler error when
    they were both merged into 'next'...
    
    Yay for Continuous dashboards!

diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 7b1c7d9..c776fcf 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -145,8 +145,11 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
   // TODO: Handle response file.
   // Add include directory flags.
   {
+  std::vector<std::string> includes;
+  this->LocalGenerator->GetIncludeDirectories(includes, this->Target,
+                                              language.c_str());
   std::string includeFlags =
-    this->LocalGenerator->GetIncludeFlags(language.c_str(), false);
+    this->LocalGenerator->GetIncludeFlags(includes, language.c_str(), false);
   this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
   }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bada88e8e45640afa5ef063aeab180fd6f1cfee4
commit bada88e8e45640afa5ef063aeab180fd6f1cfee4
Merge: 54bd175 8233636
Author:     David Cole <david.cole at kitware.com>
AuthorDate: Wed Feb 22 16:21:48 2012 -0500
Commit:     David Cole <david.cole at kitware.com>
CommitDate: Wed Feb 22 16:21:48 2012 -0500

    Merge branch 'target-include-directories' into ninja-generator


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=54bd175eea66704a879fc72278cdbb49efdd801c
commit 54bd175eea66704a879fc72278cdbb49efdd801c
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Tue Feb 21 21:18:05 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Tue Feb 21 21:18:05 2012 +0100

    Ninja: windows msvc: create for each target a .pdb file

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 9294a01..6e08bca 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -136,6 +136,7 @@ cmNinjaNormalTargetGenerator
     vars.Target = "$out";
     vars.TargetSOName = "$SONAME";
     vars.TargetInstallNameDir = "$INSTALLNAME_DIR";
+    vars.TargetPDB = "$TARGET_PDB";
 
     // Setup the target version.
     std::string targetVersionMajor;
@@ -361,6 +362,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
       targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
   }
 
+  vars["TARGET_PDB"] = this->GetTargetPDB();
+
   std::vector<cmCustomCommand> *cmdLists[3] = {
     &this->GetTarget()->GetPreBuildCommands(),
     &this->GetTarget()->GetPreLinkCommands(),
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 8a563b6..7b1c7d9 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -270,6 +270,23 @@ std::string cmNinjaTargetGenerator::GetTargetName() const
   return this->Target->GetName();
 }
 
+std::string cmNinjaTargetGenerator::GetTargetPDB() const
+{
+  std::string targetFullPathPDB;
+  if(this->Target->GetType() == cmTarget::EXECUTABLE ||
+     this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
+     this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+     this->Target->GetType() == cmTarget::MODULE_LIBRARY)
+    {
+    targetFullPathPDB = this->Target->GetDirectory(this->GetConfigName());
+    targetFullPathPDB += "/";
+    targetFullPathPDB += this->Target->GetPDBName(this->GetConfigName());
+    }
+
+  return ConvertToNinjaPath(targetFullPathPDB.c_str());
+}
+
+
 void
 cmNinjaTargetGenerator
 ::WriteLanguageRules(const std::string& language)
@@ -293,6 +310,7 @@ cmNinjaTargetGenerator
   vars.Object = "$out";
   std::string flags = "$FLAGS";
   vars.Defines = "$DEFINES";
+  vars.TargetPDB = "$TARGET_PDB";
 
   std::string depfile;
   std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
@@ -426,6 +444,7 @@ cmNinjaTargetGenerator
   cmNinjaVars vars;
   vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
   vars["DEFINES"] = this->ComputeDefines(source, language);
+  vars["TARGET_PDB"] = this->GetTargetPDB();
 
   cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
                                      comment,
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 2986844..f9270a2 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -38,6 +38,7 @@ public:
 
   virtual void Generate() = 0;
 
+  std::string GetTargetPDB() const;
   std::string GetTargetName() const;
 
 protected:

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a1a30340a2eb0174f9f6911ee1e2cf4a36eaac96
commit a1a30340a2eb0174f9f6911ee1e2cf4a36eaac96
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 19 21:38:10 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 19 23:20:03 2012 +0000

    Ninja: Import library support for Windows

diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 687dbb8..ea03cbb 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -31,6 +31,7 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator()
 #ifdef _WIN32
   this->WindowsShell = true;
 #endif
+  this->TargetImplib = "$TARGET_IMPLIB";
 }
 
 //----------------------------------------------------------------------------
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 66714e9..9294a01 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -172,10 +172,6 @@ cmNinjaNormalTargetGenerator
         i != linkCmds.end();
         ++i)
       {
-#ifdef _WIN32
-       // TODO TARGET_IMPLIB is empty
-       cmSystemTools::ReplaceString(*i, "/implib:", "");
-#endif
       this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
       }
     linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
@@ -314,6 +310,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     this->GetTarget()->GetFullPath(this->GetConfigName(),
                                    /*implib=*/false,
                                    /*realpath=*/true).c_str());
+  std::string targetOutputImplib = ConvertToNinjaPath(
+    this->GetTarget()->GetFullPath(this->GetConfigName(),
+                                   /*implib=*/true).c_str());
 
   // Compute the comment.
   std::ostringstream comment;
@@ -357,6 +356,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     }
   }
 
+  if (!this->TargetNameImport.empty()) {
+    vars["TARGET_IMPLIB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+      targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
+  }
+
   std::vector<cmCustomCommand> *cmdLists[3] = {
     &this->GetTarget()->GetPreBuildCommands(),
     &this->GetTarget()->GetPreLinkCommands(),
@@ -434,6 +438,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     }
   }
 
+  if (!this->TargetNameImport.empty()) {
+    // Since using multiple outputs would mess up the $out variable, use an
+    // alias for the import library.
+    cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+                                            "Alias for import library.",
+                                            cmNinjaDeps(1, targetOutputImplib),
+                                            cmNinjaDeps(1, targetOutputReal));
+  }
+
   // Add aliases for the file name and the target name.
   this->GetGlobalGenerator()->AddTargetAlias(this->TargetNameOut,
                                              this->GetTarget());
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1a8d13d..8a563b6 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -223,22 +223,9 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   if(!cli)
     return cmNinjaDeps();
 
-
-#ifndef _WIN32
   const std::vector<std::string> &deps = cli->GetDepends();
   cmNinjaDeps result(deps.size());
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
-#else
-  // TODO The ninja generator misses a lot on Windows.
-  //      This hack avoids a problem when a Dll is build:
-  //      It builds the .dll but uses the .lib which is then unknown to ninja.
-  cmNinjaDeps result;
-  for(unsigned i = 0; i < cli->GetItems().size(); ++i) {
-    if( cli->GetItems()[i].Target ) {
-      result.push_back( cli->GetItems()[i].Target->GetName() );
-    }
-  }
-#endif
   return result;
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=21997cea4d8694077e8bcf9ba4cbd3d96a3f163c
commit 21997cea4d8694077e8bcf9ba4cbd3d96a3f163c
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sun Feb 19 19:21:05 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sun Feb 19 19:21:05 2012 +0100

    Ninja: mark the Windows specific hacks with a comment only

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 97b46bf..66714e9 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -172,7 +172,8 @@ cmNinjaNormalTargetGenerator
         i != linkCmds.end();
         ++i)
       {
-#ifdef ENABLE_WIN32_NINJA_HACKS
+#ifdef _WIN32
+       // TODO TARGET_IMPLIB is empty
        cmSystemTools::ReplaceString(*i, "/implib:", "");
 #endif
       this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index cc6024b..1a8d13d 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -224,11 +224,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
     return cmNinjaDeps();
 
 
-#ifndef ENABLE_WIN32_NINJA_HACKS
+#ifndef _WIN32
   const std::vector<std::string> &deps = cli->GetDepends();
   cmNinjaDeps result(deps.size());
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
 #else
+  // TODO The ninja generator misses a lot on Windows.
+  //      This hack avoids a problem when a Dll is build:
+  //      It builds the .dll but uses the .lib which is then unknown to ninja.
   cmNinjaDeps result;
   for(unsigned i = 0; i < cli->GetItems().size(); ++i) {
     if( cli->GetItems()[i].Target ) {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3b847415154b13e401bf9f71042578ad21c9c1c9
commit 3b847415154b13e401bf9f71042578ad21c9c1c9
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sun Feb 19 19:15:57 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sun Feb 19 19:15:57 2012 +0100

    Ninja: disable unfinished Windows ninja support
    
    This way the branch is ready-to-merge, even when the generator is broken on Windows.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a53a0c1..3ae9464 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,23 +353,21 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
-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)
-IF(WIN32)
-  # TODO remove
-  ADD_DEFINITIONS(-DENABLE_WIN32_NINJA_HACKS)
+if(NOT WIN32)
+  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()
 
 # create a library used by the command line and the GUI

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=adb54f3dbf802f643c8af9f8de6f67f24804dd22
commit adb54f3dbf802f643c8af9f8de6f67f24804dd22
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sun Feb 19 11:30:07 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sun Feb 19 11:30:07 2012 +0100

    Ninja: add some hacks for Windows

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e0a6f42..a53a0c1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -367,6 +367,10 @@ SET(SRCS ${SRCS}
   cmNinjaUtilityTargetGenerator.h
   )
 ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
+IF(WIN32)
+  # TODO remove
+  ADD_DEFINITIONS(-DENABLE_WIN32_NINJA_HACKS)
+endif()
 
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 0174c3d..97b46bf 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -172,8 +172,7 @@ cmNinjaNormalTargetGenerator
         i != linkCmds.end();
         ++i)
       {
-#ifdef _WIN32
-       // HACK: no TARGET_IMPLIB here???
+#ifdef ENABLE_WIN32_NINJA_HACKS
        cmSystemTools::ReplaceString(*i, "/implib:", "");
 #endif
       this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 8a563b6..cc6024b 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -223,9 +223,19 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   if(!cli)
     return cmNinjaDeps();
 
+
+#ifndef ENABLE_WIN32_NINJA_HACKS
   const std::vector<std::string> &deps = cli->GetDepends();
   cmNinjaDeps result(deps.size());
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+#else
+  cmNinjaDeps result;
+  for(unsigned i = 0; i < cli->GetItems().size(); ++i) {
+    if( cli->GetItems()[i].Target ) {
+      result.push_back( cli->GetItems()[i].Target->GetName() );
+    }
+  }
+#endif
   return result;
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=895914881be32f862dee638a0a86313366f9b7b4
commit 895914881be32f862dee638a0a86313366f9b7b4
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sun Feb 19 11:10:18 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sun Feb 19 11:10:18 2012 +0100

    Ninja: also build ninja support on Windows

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 7ddabbd..e0a6f42 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,23 +353,20 @@ 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)
+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)
 
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=70c39c845f2f2909413d8bcb19a6b72e19ff83c4
commit 70c39c845f2f2909413d8bcb19a6b72e19ff83c4
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 19 03:07:21 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 19 05:57:22 2012 +0000

    Ninja: Shell encode the command used in custom commands

diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 32f3833..687dbb8 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -334,7 +334,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
     cmdLines.push_back(cdCmd.str());
   }
   for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
-    cmdLines.push_back(ccg.GetCommand(i));
+    cmdLines.push_back(this->ConvertToOutputFormat(ccg.GetCommand(i).c_str(),
+                                                   SHELL));
     std::string& cmd = cmdLines.back();
     ccg.AppendArguments(i, cmd);
   }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0643fee2fe92b7dccc4e63be7329f6da96f2e61f
commit 0643fee2fe92b7dccc4e63be7329f6da96f2e61f
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 19 03:07:09 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 19 05:57:22 2012 +0000

    Ninja: Shell encode various CMake invocations

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b1d8e5b..7c1529b 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -743,12 +743,19 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
 
 void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
 {
-  cmMakefile* mfRoot = this->LocalGenerators[0]->GetMakefile();
+  cmLocalGenerator *lg = this->LocalGenerators[0];
+  cmMakefile* mfRoot = lg->GetMakefile();
 
   std::ostringstream cmd;
-  cmd << mfRoot->GetRequiredDefinition("CMAKE_COMMAND")
-      << " -H" << mfRoot->GetHomeDirectory()
-      << " -B" << mfRoot->GetHomeOutputDirectory();
+  cmd << lg->ConvertToOutputFormat(
+           mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
+           cmLocalGenerator::SHELL)
+      << " -H"
+      << lg->ConvertToOutputFormat(mfRoot->GetHomeDirectory(),
+                                   cmLocalGenerator::SHELL)
+      << " -B"
+      << lg->ConvertToOutputFormat(mfRoot->GetHomeOutputDirectory(),
+                                   cmLocalGenerator::SHELL);
   WriteRule(*this->RulesFileStream,
             "RERUN_CMAKE",
             cmd.str(),
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 4434aef..0174c3d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -198,7 +198,9 @@ cmNinjaNormalTargetGenerator
 
   if (this->TargetNameOut != this->TargetNameReal) {
     std::string cmakeCommand =
-      this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
+      this->GetLocalGenerator()->ConvertToOutputFormat(
+        this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
+        cmLocalGenerator::SHELL);
     if (targetType == cmTarget::EXECUTABLE)
       this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_EXECUTABLE",
                                           cmakeCommand +
@@ -238,7 +240,9 @@ cmNinjaNormalTargetGenerator
       // We have archive link commands set. First, delete the existing archive.
       std::vector<std::string> linkCmds;
       std::string cmakeCommand =
-        this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
+        this->GetLocalGenerator()->ConvertToOutputFormat(
+          this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
+          cmLocalGenerator::SHELL);
       linkCmds.push_back(cmakeCommand + " -E remove $out");
 
       // TODO: Use ARCHIVE_APPEND for archives over a certain size.

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=43b1d8bad0cf78148e4d6e7b4013850731d5a824
commit 43b1d8bad0cf78148e4d6e7b4013850731d5a824
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 19 02:46:37 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 19 05:43:47 2012 +0000

    Ninja: Shell encode paths used in "cd" commands

diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 28e8d47..32f3833 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -325,12 +325,12 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
 {
   cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
   if (ccg.GetNumberOfCommands() > 0) {
+    const char* wd = cc->GetWorkingDirectory();
+    if (!wd)
+      wd = this->GetMakefile()->GetStartOutputDirectory();
+
     std::ostringstream cdCmd;
-    cdCmd << "cd ";
-    if (const char* wd = cc->GetWorkingDirectory())
-      cdCmd << wd;
-    else
-      cdCmd << this->GetMakefile()->GetStartOutputDirectory();
+    cdCmd << "cd " << this->ConvertToOutputFormat(wd, SHELL);
     cmdLines.push_back(cdCmd.str());
   }
   for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 7cce45b..4434aef 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -377,9 +377,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
 
   // 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());
+  if (!preLinkCmdLines.empty()) {
+    std::string path = this->GetLocalGenerator()->ConvertToOutputFormat(
+      this->GetMakefile()->GetHomeOutputDirectory(),
+      cmLocalGenerator::SHELL);
+    preLinkCmdLines.push_back("cd " + path);
+  }
 
   vars["PRE_LINK"] =
     this->GetLocalGenerator()->BuildCommandLine(preLinkCmdLines);

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cea03e632b71589592660614a63ff102ba923de8
commit cea03e632b71589592660614a63ff102ba923de8
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 19 01:50:53 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 19 04:00:02 2012 +0000

    Ninja: Backslash rules for Windows
    
    Generally these are only required in build statements, as Ninja wants
    to be able to chop paths up.  But it doesn't hurt to also try to use
    them in command line arguments.

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index e9264ec..b1d8e5b 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -84,6 +84,15 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
   return result;
 }
 
+std::string cmGlobalNinjaGenerator::EncodePath(const std::string &path)
+{
+  std::string result = path;
+#ifdef _WIN32
+  cmSystemTools::ReplaceString(result, "/", "\\");
+#endif
+  return EncodeLiteral(result);
+}
+
 void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
                                         const std::string& comment,
                                         const std::string& rule,
@@ -122,7 +131,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
   for(cmNinjaDeps::const_iterator i = outputs.begin();
       i != outputs.end();
       ++i)
-    builds << " " << EncodeIdent(*i, os);
+    builds << " " << EncodeIdent(EncodePath(*i), os);
   builds << ":";
 
   // Write the rule.
@@ -132,7 +141,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
   for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
       i != explicitDeps.end();
       ++i)
-    builds  << " " << EncodeIdent(*i, os);
+    builds  << " " << EncodeIdent(EncodePath(*i), os);
 
   // Write implicit dependencies.
   if(!implicitDeps.empty())
@@ -141,7 +150,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
     for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
         i != implicitDeps.end();
         ++i)
-      builds  << " " << EncodeIdent(*i, os);
+      builds  << " " << EncodeIdent(EncodePath(*i), os);
     }
 
   // Write order-only dependencies.
@@ -151,7 +160,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
     for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
         i != orderOnlyDeps.end();
         ++i)
-      builds  << " " << EncodeIdent(*i, os);
+      builds  << " " << EncodeIdent(EncodePath(*i), os);
     }
 
   builds << "\n";
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 6f3c6b2..3f8644e 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -59,6 +59,7 @@ public:
 
   static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
   static std::string EncodeLiteral(const std::string &lit);
+  static std::string EncodePath(const std::string &path);
 
   /**
    * Write the given @a comment to the output stream @a os. It
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index cf0e36a..28e8d47 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -28,6 +28,9 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator()
   , HomeRelativeOutputPath("")
 {
   this->IsMakefileGenerator = true;
+#ifdef _WIN32
+  this->WindowsShell = true;
+#endif
 }
 
 //----------------------------------------------------------------------------
@@ -256,9 +259,11 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
 
 std::string cmLocalNinjaGenerator::ConvertToNinjaPath(const char *path)
 {
-  return this->Convert(path,
-                       cmLocalGenerator::HOME_OUTPUT,
-                       cmLocalGenerator::MAKEFILE);
+  std::string convPath = this->Convert(path, cmLocalGenerator::HOME_OUTPUT);
+#ifdef _WIN32
+  cmSystemTools::ReplaceString(convPath, "/", "\\");
+#endif
+  return convPath;
 }
 
 void
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1e31044..8a563b6 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -212,13 +212,6 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
   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.
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index cf47abf..2986844 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -75,7 +75,9 @@ protected:
   std::string ComputeDefines(cmSourceFile *source,
                              const std::string& language);
 
-  std::string ConvertToNinjaPath(const char *path) const;
+  std::string ConvertToNinjaPath(const char *path) const {
+    return this->GetLocalGenerator()->ConvertToNinjaPath(path);
+  }
   cmLocalNinjaGenerator::map_to_ninja_path MapToNinjaPath() const {
     return this->GetLocalGenerator()->MapToNinjaPath();
   }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9362440a0b9193c417b42c50495d0a3ea6e098c4
commit 9362440a0b9193c417b42c50495d0a3ea6e098c4
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sat Feb 18 19:04:55 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sat Feb 18 20:33:39 2012 +0000

    Ninja: Identifier encoding rules for ' ' and ':'

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7ff33ba..e9264ec 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -56,7 +56,8 @@ static bool IsIdentChar(char c)
     ('a' <= c && c <= 'z') ||
     ('+' <= c && c <= '9') ||  // +,-./ and numbers
     ('A' <= c && c <= 'Z') ||
-    (c == '_') || (c == '$') || (c == '\\');
+    (c == '_') || (c == '$') || (c == '\\') ||
+    (c == ' ') || (c == ':');
 }
 
 std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
@@ -69,7 +70,10 @@ std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
     vars << names.str() << " = " << ident << "\n";
     return "$" + names.str();
   } else {
-    return ident;
+    std::string result = ident;
+    cmSystemTools::ReplaceString(result, " ", "$ ");
+    cmSystemTools::ReplaceString(result, ":", "$:");
+    return result;
   }
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=99856d537c996544bf495f33e6b058d83af4c6b7
commit 99856d537c996544bf495f33e6b058d83af4c6b7
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sat Feb 18 16:32:47 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sat Feb 18 20:33:33 2012 +0000

    Ninja: Partially revert "win fixes: escape back slash/colon, use cd. as cmd.exe nop"
    
    It introduced encoding rules in the wrong place, and broke the
    CustomCommand test case.
    
    This reverts commit 7fb2bb3e8b0dc7bc718aadc4ab9a74cb7fdb656e.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 7cc56d7..7ddabbd 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,8 +353,9 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
-
-SET(SRCS ${SRCS}
+# Ninja only works on UNIX.
+IF(UNIX)
+  SET(SRCS ${SRCS}
     cmGlobalNinjaGenerator.cxx
     cmGlobalNinjaGenerator.h
     cmNinjaTypes.h
@@ -367,8 +368,8 @@ SET(SRCS ${SRCS}
     cmNinjaUtilityTargetGenerator.cxx
     cmNinjaUtilityTargetGenerator.h
     )
-ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
-
+  ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
+ENDIF(UNIX)
 
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 879a973..7ff33ba 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -59,7 +59,6 @@ static bool IsIdentChar(char c)
     (c == '_') || (c == '$') || (c == '\\');
 }
 
-
 std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
                                                 std::ostream &vars) {
   if (std::find_if(ident.begin(), ident.end(),
@@ -70,19 +69,14 @@ std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
     vars << names.str() << " = " << ident << "\n";
     return "$" + names.str();
   } else {
-    return EncodeLiteral(ident);
+    return ident;
   }
 }
 
-
 std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
 {
   std::string result = lit;
   cmSystemTools::ReplaceString(result, "$", "$$");
-  cmSystemTools::ReplaceString(result, ":", "$:");
-#ifdef _WIN32
-  cmSystemTools::ReplaceString(result, "/", "\\");
-#endif
   return result;
 }
 
@@ -206,8 +200,7 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
   this->AddCustomCommandRule();
 
   cmNinjaVars vars;
-
-  vars["COMMAND"] = EncodeLiteral(command);
+  vars["COMMAND"] = command;
   vars["DESC"] = EncodeLiteral(description);
 
   cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f999a59afe804063cebf4dd89ef99662829bf3e4
commit f999a59afe804063cebf4dd89ef99662829bf3e4
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sat Feb 18 11:24:41 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sat Feb 18 11:24:41 2012 +0100

    Ninja: don't define MSVC_IDE when using the ninja generator
    
    Thanks to Oscar Fuentes

diff --git a/Modules/Platform/Windows-cl.cmake b/Modules/Platform/Windows-cl.cmake
index ccccbc9..be6abb6 100644
--- a/Modules/Platform/Windows-cl.cmake
+++ b/Modules/Platform/Windows-cl.cmake
@@ -37,7 +37,7 @@ SET(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>")
 # that is automatically copied into try_compile directories
 # by the global generator.
 SET(MSVC_IDE 1)
-IF(CMAKE_GENERATOR MATCHES "Makefiles")
+IF(CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
   SET(MSVC_IDE 0)
   IF(NOT CMAKE_VC_COMPILER_TESTS_RUN)
     SET(CMAKE_VC_COMPILER_TESTS 1)
@@ -125,7 +125,7 @@ IF(CMAKE_GENERATOR MATCHES "Makefiles")
     ENDIF(CMAKE_COMPILER_RETURN)
     MAKE_DIRECTORY("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp3")
   ENDIF(NOT CMAKE_VC_COMPILER_TESTS_RUN)
-ENDIF(CMAKE_GENERATOR MATCHES "Makefiles")
+ENDIF(CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
 
 IF(MSVC_C_ARCHITECTURE_ID MATCHES 64)
   SET(CMAKE_CL_64 1)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7fb2bb3e8b0dc7bc718aadc4ab9a74cb7fdb656e
commit 7fb2bb3e8b0dc7bc718aadc4ab9a74cb7fdb656e
Author:     Peter Kuemmel <syntheticpp at gmx.net>
AuthorDate: Sat Feb 18 08:07:11 2012 +0100
Commit:     Peter Kuemmel <syntheticpp at gmx.net>
CommitDate: Sat Feb 18 08:15:23 2012 +0100

    Ninja: win fixes: escape back slash/colon, use cd. as cmd.exe nop

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 7ddabbd..7cc56d7 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -353,9 +353,8 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
-# Ninja only works on UNIX.
-IF(UNIX)
-  SET(SRCS ${SRCS}
+
+SET(SRCS ${SRCS}
     cmGlobalNinjaGenerator.cxx
     cmGlobalNinjaGenerator.h
     cmNinjaTypes.h
@@ -368,8 +367,8 @@ IF(UNIX)
     cmNinjaUtilityTargetGenerator.cxx
     cmNinjaUtilityTargetGenerator.h
     )
-  ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
-ENDIF(UNIX)
+ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
+
 
 # create a library used by the command line and the GUI
 ADD_LIBRARY(CMakeLib ${SRCS})
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7ff33ba..879a973 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -59,6 +59,7 @@ static bool IsIdentChar(char c)
     (c == '_') || (c == '$') || (c == '\\');
 }
 
+
 std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
                                                 std::ostream &vars) {
   if (std::find_if(ident.begin(), ident.end(),
@@ -69,14 +70,19 @@ std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
     vars << names.str() << " = " << ident << "\n";
     return "$" + names.str();
   } else {
-    return ident;
+    return EncodeLiteral(ident);
   }
 }
 
+
 std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
 {
   std::string result = lit;
   cmSystemTools::ReplaceString(result, "$", "$$");
+  cmSystemTools::ReplaceString(result, ":", "$:");
+#ifdef _WIN32
+  cmSystemTools::ReplaceString(result, "/", "\\");
+#endif
   return result;
 }
 
@@ -200,7 +206,8 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
   this->AddCustomCommandRule();
 
   cmNinjaVars vars;
-  vars["COMMAND"] = command;
+
+  vars["COMMAND"] = EncodeLiteral(command);
   vars["DESC"] = EncodeLiteral(description);
 
   cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index a4e66e4..cf0e36a 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -294,7 +294,11 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
   // This happens when building a POST_BUILD value for link targets that
   // don't use POST_BUILD.
   if (cmdLines.empty())
+#ifdef _WIN32
+    return "cd.";
+#else
     return ":";
+#endif
 
   // 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
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 4dd6a9b..7cce45b 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -172,6 +172,10 @@ cmNinjaNormalTargetGenerator
         i != linkCmds.end();
         ++i)
       {
+#ifdef _WIN32
+       // HACK: no TARGET_IMPLIB here???
+       cmSystemTools::ReplaceString(*i, "/implib:", "");
+#endif
       this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
       }
     linkCmds.insert(linkCmds.begin(), "$PRE_LINK");

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d19e8aa6aac75fb08897aece8aa5545360aeeb2
commit 5d19e8aa6aac75fb08897aece8aa5545360aeeb2
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 5 01:48:08 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 5 01:48:08 2012 +0000

    Ninja: Appease various compilers

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 8b633bf..7ff33ba 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -367,7 +367,7 @@ void cmGlobalNinjaGenerator::Generate()
 
   this->cmGlobalGenerator::Generate();
 
-  this->WriteAssumedSourceDependencies(*this->BuildFileStream);
+  this->WriteAssumedSourceDependencies();
   this->WriteTargetAliases(*this->BuildFileStream);
   this->WriteBuiltinTargets(*this->BuildFileStream);
 
@@ -591,15 +591,16 @@ void cmGlobalNinjaGenerator::AddDependencyToAll(cmTarget* target)
   this->AppendTargetOutputs(target, this->AllDependencies);
 }
 
-void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
 {
   for (std::map<std::string, std::set<std::string> >::iterator
        i = this->AssumedSourceDependencies.begin();
        i != this->AssumedSourceDependencies.end(); ++i) {
+    cmNinjaDeps deps;
+    std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
     WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
                             "Assume dependencies for generated source file.",
-                            cmNinjaDeps(1, i->first),
-                            cmNinjaDeps(i->second.begin(), i->second.end()));
+                            cmNinjaDeps(1, i->first), deps);
   }
 }
 
@@ -653,7 +654,7 @@ cmGlobalNinjaGenerator
     // 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());
+    std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
   } else {
     cmTargetDependSet const& targetDeps =
       this->GetTargetDirectDepends(*target);
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 171d14b..6f3c6b2 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -255,7 +255,7 @@ private:
 
   void AddDependencyToAll(cmTarget* target);
 
-  void WriteAssumedSourceDependencies(std::ostream& os);
+  void WriteAssumedSourceDependencies();
 
   void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
   void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index fee9cd0..8ef4d28 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -97,8 +97,8 @@ private:
 
   struct map_to_ninja_path {
     cmLocalNinjaGenerator *LocalGenerator;
-    map_to_ninja_path(cmLocalNinjaGenerator *LocalGenerator)
-      : LocalGenerator(LocalGenerator) {}
+    map_to_ninja_path(cmLocalNinjaGenerator *LocalGen)
+      : LocalGenerator(LocalGen) {}
     std::string operator()(const std::string &path) {
       return LocalGenerator->ConvertToNinjaPath(path.c_str());
     }
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index d7f8ad7..4dd6a9b 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -281,6 +281,7 @@ cmNinjaNormalTargetGenerator
     default:
       assert(0 && "Unexpected target type");
   }
+  return std::vector<std::string>();
 }
 
 void cmNinjaNormalTargetGenerator::WriteLinkStatement()
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index bfe6f07..bf8194d 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -39,8 +39,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
       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(),
+      const std::vector<std::string>& ccOutputs = cc->GetOutputs();
+      std::transform(ccOutputs.begin(), ccOutputs.end(),
                      std::back_inserter(deps), MapToNinjaPath());
       }
     }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bfe56f6802fc7db7f8e824aab8881be6cf23ccef
commit bfe56f6802fc7db7f8e824aab8881be6cf23ccef
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 5 01:48:01 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 5 01:48:01 2012 +0000

    Ninja: Remove some default arguments

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 24900c5..8b633bf 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -767,8 +767,5 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
   WritePhonyBuild(os,
                   "A missing CMake input file is not an error.",
                   implicitDeps,
-                  cmNinjaDeps(),
-                  cmNinjaDeps(),
-                  cmNinjaDeps(),
-                  cmNinjaVars());
+                  cmNinjaDeps());
 }
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 0a15834..bfe6f07 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -88,10 +88,7 @@ void cmNinjaUtilityTargetGenerator::Generate()
     cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
                                             "",
                                             outputs,
-                                            cmNinjaDeps(1, utilCommandName),
-                                            cmNinjaDeps(),
-                                            cmNinjaDeps(),
-                                            cmNinjaVars());
+                                            cmNinjaDeps(1, utilCommandName));
   }
 
   this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=69984906ef41ed9549d4acd75590c67030281df9
commit 69984906ef41ed9549d4acd75590c67030281df9
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Sun Feb 5 00:55:34 2012 +0000
Commit:     Peter Collingbourne <peter at pcc.me.uk>
CommitDate: Sun Feb 5 00:57:22 2012 +0000

    Ninja: Fix a 79-col violation

diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 6ae5032..a4e66e4 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -300,7 +300,7 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
   // 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
+  // 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) {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6dd410c2b98d5152adf69b5986b5f25d4dcd9e2a
commit 6dd410c2b98d5152adf69b5986b5f25d4dcd9e2a
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

    Ninja: 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)

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

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list