[Cmake-commits] CMake branch, next, updated. v3.1.0-rc2-668-gc2a87de

Brad King brad.king at kitware.com
Mon Nov 17 09:37:45 EST 2014


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  c2a87deafe277348e7fba5ffc55d67f7624dce9b (commit)
       via  557aef0b94c86d13e802e6e8e34a491304d7be2f (commit)
       via  e15a7075b58aef6fe7b6eb56f810d0f33bc31feb (commit)
       via  67bd514adce689f4c7f537cdc446c01f7373f5a5 (commit)
       via  ef42e57d470db499a41c8bca695391c3e3e5cb86 (commit)
       via  592644c42c58312aadf1fd1b28e95c7f0fbbb2f8 (commit)
       via  2d75d7e56bc00c9abe51d39c4306084b24fe8cd5 (commit)
       via  f42d86f0b834c73b28a919ef1b4279753a6ec1bd (commit)
       via  f281ae01a2b89d8a7d327b3f6e73b727195d8dfd (commit)
       via  d5eae5563f99fb28c99695fb4886f1bd40d98414 (commit)
       via  4d1fedf46e9cbdb388728c9a986cbf89db810c73 (commit)
       via  fe5d6e8c0f2e37bac0621a3b976d95c471891f38 (commit)
      from  f77a1b1f89fd74036cb98f1d0ba45e34d8c5f02f (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=c2a87deafe277348e7fba5ffc55d67f7624dce9b
commit c2a87deafe277348e7fba5ffc55d67f7624dce9b
Merge: f77a1b1 557aef0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Nov 17 09:37:43 2014 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Nov 17 09:37:43 2014 -0500

    Merge topic 'custom-command-byproducts' into next
    
    557aef0b ExternalProject: Add options to specify BYPRODUCTS (#14963)
    e15a7075 Add an option for explicit BYPRODUCTS of custom commands (#14963)
    67bd514a Ninja: Refactor restat to be a string internally
    ef42e57d Ninja: Use a TARGET_FILE variable to hold the link output file
    592644c4 Tests/BuildDepends: Drop unneeded help for Ninja
    2d75d7e5 Help: Add notes for topic 'console-pool'
    f42d86f0 Ninja: Implement USES_TERMINAL using the console pool if available
    f281ae01 Ninja: Remove unused declaration
    d5eae556 Ninja: factor out the test for console pool support
    4d1fedf4 Give the interactive cache editor the USES_TERMINAL property
    fe5d6e8c Add USES_TERMINAL option for custom commands


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=557aef0b94c86d13e802e6e8e34a491304d7be2f
commit 557aef0b94c86d13e802e6e8e34a491304d7be2f
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Nov 13 19:26:36 2014 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Nov 17 09:36:42 2014 -0500

    ExternalProject: Add options to specify BYPRODUCTS (#14963)
    
    The external project's build process may generate byproducts on which
    other rules in the driving project's build later depend.  Provide a way
    for the driving project to specify what byproducts it expects to be made
    available by the custom commands that drive the external project.

diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 32f6d2c..e5616b1 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -132,6 +132,9 @@ Create custom targets to build projects in external trees
     Use source dir for build dir
   ``BUILD_ALWAYS 1``
     No stamp file, build step always runs
+  ``BUILD_BYPRODUCTS <file>...``
+    Files that will be generated by the build command but may or may
+    not have their modification time updated by subsequent builds.
 
   Install step options are:
 
@@ -234,6 +237,9 @@ Create custom targets to build projects in external trees
     Steps that depend on this step
   ``DEPENDS <file>...``
     Files on which this step depends
+  ``BYPRODUCTS <file>...``
+    Files that will be generated by this step but may or may not
+    have their modification time updated by subsequent builds.
   ``ALWAYS 1``
     No stamp file, step always runs
   ``EXCLUDE_FROM_MAIN 1``
@@ -1409,6 +1415,9 @@ function(ExternalProject_Add_Step name step)
   # Dependencies on files.
   get_property(depends TARGET ${name} PROPERTY _EP_${step}_DEPENDS)
 
+  # Byproducts of the step.
+  get_property(byproducts TARGET ${name} PROPERTY _EP_${step}_BYPRODUCTS)
+
   # Dependencies on steps.
   get_property(dependees TARGET ${name} PROPERTY _EP_${step}_DEPENDEES)
   foreach(dependee IN LISTS dependees)
@@ -1466,6 +1475,7 @@ function(ExternalProject_Add_Step name step)
 
   add_custom_command(
     OUTPUT ${stamp_file}
+    BYPRODUCTS ${byproducts}
     COMMENT ${comment}
     COMMAND ${command}
     COMMAND ${touch}
@@ -2139,8 +2149,11 @@ function(_ep_add_build_command name)
     set(always 0)
   endif()
 
+  get_property(build_byproducts TARGET ${name} PROPERTY _EP_BUILD_BYPRODUCTS)
+
   ExternalProject_Add_Step(${name} build
     COMMAND ${cmd}
+    BYPRODUCTS ${build_byproducts}
     WORKING_DIRECTORY ${binary_dir}
     DEPENDEES configure
     ALWAYS ${always}
diff --git a/Tests/CustomCommandByproducts/CMakeLists.txt b/Tests/CustomCommandByproducts/CMakeLists.txt
index c39a536..884f8c2 100644
--- a/Tests/CustomCommandByproducts/CMakeLists.txt
+++ b/Tests/CustomCommandByproducts/CMakeLists.txt
@@ -79,6 +79,29 @@ add_custom_command(OUTPUT timestamp8.txt
     ${CMAKE_CURRENT_SOURCE_DIR}/byproduct8.c.in
   )
 
+# Generate the library file of an imported target as a byproduct
+# of an external project.
+if(CMAKE_CONFIGURATION_TYPES)
+  set(cfg /${CMAKE_CFG_INTDIR})
+else()
+  set(cfg)
+endif()
+set(ExternalLibrary_LIBRARY
+  ${CMAKE_CURRENT_BINARY_DIR}/External-build${cfg}/${CMAKE_STATIC_LIBRARY_PREFIX}ExternalLibrary${CMAKE_STATIC_LIBRARY_SUFFIX}
+  )
+include(ExternalProject)
+ExternalProject_Add(ExternalTarget
+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/External"
+  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/External-build"
+  PREFIX     "${CMAKE_CURRENT_BINARY_DIR}/External-build/root"
+  DOWNLOAD_COMMAND ""
+  INSTALL_COMMAND ""
+  BUILD_BYPRODUCTS "${ExternalLibrary_LIBRARY}"
+  )
+add_library(ExternalLibrary STATIC IMPORTED)
+set_property(TARGET ExternalLibrary PROPERTY IMPORTED_LOCATION ${ExternalLibrary_LIBRARY})
+add_dependencies(ExternalLibrary ExternalTarget)
+
 # Add an executable consuming all the byproducts.
 add_executable(CustomCommandByproducts
   CustomCommandByproducts.c
@@ -94,6 +117,7 @@ add_executable(CustomCommandByproducts
 add_dependencies(CustomCommandByproducts Producer2)
 add_dependencies(CustomCommandByproducts Producer3_4)
 add_dependencies(CustomCommandByproducts ProducerExe)
+target_link_libraries(CustomCommandByproducts ExternalLibrary)
 
 if(CMAKE_GENERATOR STREQUAL "Ninja")
   add_custom_target(CheckNinja ALL
diff --git a/Tests/CustomCommandByproducts/CustomCommandByproducts.c b/Tests/CustomCommandByproducts/CustomCommandByproducts.c
index d9db9e6..1916427 100644
--- a/Tests/CustomCommandByproducts/CustomCommandByproducts.c
+++ b/Tests/CustomCommandByproducts/CustomCommandByproducts.c
@@ -6,6 +6,7 @@ extern int byproduct5(void);
 extern int byproduct6(void);
 extern int byproduct7(void);
 extern int byproduct8(void);
+extern int ExternalLibrary(void);
 int main(void)
 {
   return (
@@ -17,5 +18,6 @@ int main(void)
     byproduct6() +
     byproduct7() +
     byproduct8() +
+    ExternalLibrary() +
     0);
 }
diff --git a/Tests/CustomCommandByproducts/External/CMakeLists.txt b/Tests/CustomCommandByproducts/External/CMakeLists.txt
new file mode 100644
index 0000000..feaa12e
--- /dev/null
+++ b/Tests/CustomCommandByproducts/External/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.1)
+project(External C)
+
+add_library(ExternalLibrary STATIC ExternalLibrary.c)
diff --git a/Tests/CustomCommandByproducts/External/ExternalLibrary.c b/Tests/CustomCommandByproducts/External/ExternalLibrary.c
new file mode 100644
index 0000000..a1dacf0
--- /dev/null
+++ b/Tests/CustomCommandByproducts/External/ExternalLibrary.c
@@ -0,0 +1 @@
+int ExternalLibrary(void) { return 0; }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e15a7075b58aef6fe7b6eb56f810d0f33bc31feb
commit e15a7075b58aef6fe7b6eb56f810d0f33bc31feb
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Nov 13 18:54:52 2014 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 16:16:00 2014 -0500

    Add an option for explicit BYPRODUCTS of custom commands (#14963)
    
    A common idiom in CMake-based build systems is to have custom commands
    that generate files not listed explicitly as outputs so that these
    files do not have to be newer than the inputs.  The file modification
    times of such "byproducts" are updated only when their content changes.
    Then other build rules can depend on the byproducts explicitly so that
    their dependents rebuild when the content of the original byproducts
    really does change.
    
    This "undeclared byproduct" approach is necessary for Makefile, VS, and
    Xcode build tools because if a byproduct were listed as an output of a
    rule then the rule would always rerun when the input is newer than the
    byproduct but the byproduct may never be updated.
    
    Ninja solves this problem by offering a 'restat' feature to check
    whether an output was really modified after running a rule and tracking
    the fact that it is up to date separately from its timestamp.  However,
    Ninja also stats all dependencies up front and will only restat files
    that are listed as outputs of rules with the 'restat' option enabled.
    Therefore an undeclared byproduct that does not exist at the start of
    the build will be considered missing and the build will fail even if
    other dependencies would cause the byproduct to be available before its
    dependents build.
    
    CMake works around this limitation by adding 'phony' build rules for
    custom command dependencies in the build tree that do not have any
    explicit specification of what produces them.  This is not optimal
    because it prevents Ninja from reporting an error when an input to a
    rule really is missing.  A better approach is to allow projects to
    explicitly specify the byproducts of their custom commands so that no
    phony rules are needed for them.  In order to work with the non-Ninja
    generators, the byproducts must be known separately from the outputs.
    
    Add a new "BYPRODUCTS" option to the add_custom_command and
    add_custom_target commands to specify byproducts explicitly.  Teach the
    Ninja generator to specify byproducts as outputs of the custom commands.
    In the case of POST_BUILD, PRE_LINK, and PRE_BUILD events on targets
    that link, the byproducts must be specified as outputs of the link rule
    that runs the commands.  Activate 'restat' for such rules so that Ninja
    knows it needs to check the byproducts, but not for link rules that have
    no byproducts.

diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index cb0746b..9fbad4b 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -15,6 +15,7 @@ The first signature is for adding a custom command to produce an output::
                      [COMMAND command2 [ARGS] [args2...] ...]
                      [MAIN_DEPENDENCY depend]
                      [DEPENDS [depends...]]
+                     [BYPRODUCTS [files...]]
                      [IMPLICIT_DEPENDS <lang1> depend1
                                       [<lang2> depend2] ...]
                      [WORKING_DIRECTORY dir]
@@ -44,6 +45,27 @@ The options are:
   options are currently ignored when APPEND is given, but may be
   used in the future.
 
+``BYPRODUCTS``
+  Specify the files the command is expected to produce but whose
+  modification time may or may not be newer than the dependencies.
+  If a byproduct name is a relative path it will be interpreted
+  relative to the build tree directory corresponding to the
+  current source directory.
+  Each byproduct file will be marked with the :prop_sf:`GENERATED`
+  source file property automatically.
+
+  Explicit specification of byproducts is supported by the
+  :generator:`Ninja` generator to tell the ``ninja`` build tool
+  how to regenerate byproducts when they are missing.  It is
+  also useful when other build rules (e.g. custom commands)
+  depend on the byproducts.  Ninja requires a build rule for any
+  generated file on which another rule depends even if there are
+  order-only dependencies to ensure the byproducts will be
+  available before their dependents build.
+
+  The ``BYPRODUCTS`` option is ignored on non-Ninja generators
+  except to mark byproducts ``GENERATED``.
+
 ``COMMAND``
   Specify the command-line(s) to execute at build time.
   If more than one ``COMMAND`` is specified they will be executed in order,
@@ -156,6 +178,7 @@ target is already built, the command will not execute.
                      PRE_BUILD | PRE_LINK | POST_BUILD
                      COMMAND command1 [ARGS] [args1...]
                      [COMMAND command2 [ARGS] [args2...] ...]
+                     [BYPRODUCTS [files...]]
                      [WORKING_DIRECTORY dir]
                      [COMMENT comment]
                      [VERBATIM] [USES_TERMINAL])
diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst
index 8b7472d..996d08e 100644
--- a/Help/command/add_custom_target.rst
+++ b/Help/command/add_custom_target.rst
@@ -8,6 +8,7 @@ Add a target with no output so it will always be built.
   add_custom_target(Name [ALL] [command1 [args1...]]
                     [COMMAND command2 [args2...] ...]
                     [DEPENDS depend depend depend ... ]
+                    [BYPRODUCTS [files...]]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment]
                     [VERBATIM] [USES_TERMINAL]
@@ -28,6 +29,27 @@ The options are:
   target so that it will be run every time (the command cannot be
   called ``ALL``).
 
+``BYPRODUCTS``
+  Specify the files the command is expected to produce but whose
+  modification time may or may not be updated on subsequent builds.
+  If a byproduct name is a relative path it will be interpreted
+  relative to the build tree directory corresponding to the
+  current source directory.
+  Each byproduct file will be marked with the :prop_sf:`GENERATED`
+  source file property automatically.
+
+  Explicit specification of byproducts is supported by the
+  :generator:`Ninja` generator to tell the ``ninja`` build tool
+  how to regenerate byproducts when they are missing.  It is
+  also useful when other build rules (e.g. custom commands)
+  depend on the byproducts.  Ninja requires a build rule for any
+  generated file on which another rule depends even if there are
+  order-only dependencies to ensure the byproducts will be
+  available before their dependents build.
+
+  The ``BYPRODUCTS`` option is ignored on non-Ninja generators
+  except to mark byproducts ``GENERATED``.
+
 ``COMMAND``
   Specify the command-line(s) to execute at build time.
   If more than one ``COMMAND`` is specified they will be executed in order,
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 410f978..818b910 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -32,7 +32,7 @@ bool cmAddCustomCommandCommand
   std::string source, target, main_dependency, working;
   std::string comment_buffer;
   const char* comment = 0;
-  std::vector<std::string> depends, outputs, output;
+  std::vector<std::string> depends, outputs, output, byproducts;
   bool verbatim = false;
   bool append = false;
   bool uses_terminal = false;
@@ -57,6 +57,7 @@ bool cmAddCustomCommandCommand
     doing_main_dependency,
     doing_output,
     doing_outputs,
+    doing_byproducts,
     doing_comment,
     doing_working_directory,
     doing_nothing
@@ -127,6 +128,10 @@ bool cmAddCustomCommandCommand
       {
       doing = doing_output;
       }
+    else if (copy == "BYPRODUCTS")
+      {
+      doing = doing_byproducts;
+      }
     else if (copy == "WORKING_DIRECTORY")
       {
       doing = doing_working_directory;
@@ -150,6 +155,7 @@ bool cmAddCustomCommandCommand
         {
         case doing_output:
         case doing_outputs:
+        case doing_byproducts:
           if (!cmSystemTools::FileIsFullPath(copy.c_str()))
             {
             // This is an output to be generated, so it should be
@@ -233,6 +239,9 @@ bool cmAddCustomCommandCommand
          case doing_outputs:
            outputs.push_back(filename);
            break;
+         case doing_byproducts:
+           byproducts.push_back(filename);
+           break;
          case doing_comment:
            comment_buffer = copy;
            comment = comment_buffer.c_str();
@@ -272,7 +281,9 @@ bool cmAddCustomCommandCommand
     }
 
   // Make sure the output names and locations are safe.
-  if(!this->CheckOutputs(output) || !this->CheckOutputs(outputs))
+  if(!this->CheckOutputs(output) ||
+     !this->CheckOutputs(outputs) ||
+     !this->CheckOutputs(byproducts))
     {
     return false;
     }
@@ -314,7 +325,7 @@ bool cmAddCustomCommandCommand
     {
     // Source is empty, use the target.
     std::vector<std::string> no_depends;
-    this->Makefile->AddCustomCommandToTarget(target, no_depends,
+    this->Makefile->AddCustomCommandToTarget(target, byproducts, no_depends,
                                              commandLines, cctype,
                                              comment, working.c_str(),
                                              escapeOldStyle, uses_terminal);
@@ -322,8 +333,8 @@ bool cmAddCustomCommandCommand
   else if(target.empty())
     {
     // Target is empty, use the output.
-    this->Makefile->AddCustomCommandToOutput(output, depends,
-                                             main_dependency,
+    this->Makefile->AddCustomCommandToOutput(output, byproducts,
+                                             depends, main_dependency,
                                              commandLines, comment,
                                              working.c_str(), false,
                                              escapeOldStyle, uses_terminal);
@@ -351,6 +362,11 @@ bool cmAddCustomCommandCommand
         }
       }
     }
+  else if (!byproducts.empty())
+    {
+    this->SetError("BYPRODUCTS may not be specified with SOURCE signatures");
+    return false;
+    }
   else if (uses_terminal)
     {
     this->SetError("USES_TERMINAL may not be used with SOURCE signatures");
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index fc4f8f1..09c8af5 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -45,7 +45,7 @@ bool cmAddCustomTargetCommand
   cmCustomCommandLines commandLines;
 
   // Accumulate dependencies.
-  std::vector<std::string> depends;
+  std::vector<std::string> depends, byproducts;
   std::string working_directory;
   bool verbatim = false;
   bool uses_terminal = false;
@@ -57,6 +57,7 @@ bool cmAddCustomTargetCommand
   enum tdoing {
     doing_command,
     doing_depends,
+    doing_byproducts,
     doing_working_directory,
     doing_comment,
     doing_source,
@@ -85,6 +86,10 @@ bool cmAddCustomTargetCommand
       {
       doing = doing_depends;
       }
+    else if(copy == "BYPRODUCTS")
+      {
+      doing = doing_byproducts;
+      }
     else if(copy == "WORKING_DIRECTORY")
       {
       doing = doing_working_directory;
@@ -128,6 +133,19 @@ bool cmAddCustomTargetCommand
         case doing_command:
           currentLine.push_back(copy);
           break;
+        case doing_byproducts:
+          {
+          std::string filename;
+          if (!cmSystemTools::FileIsFullPath(copy.c_str()))
+            {
+            filename = this->Makefile->GetCurrentOutputDirectory();
+            filename += "/";
+            }
+          filename += copy;
+          cmSystemTools::ConvertToUnixSlashes(filename);
+          byproducts.push_back(filename);
+          }
+          break;
         case doing_depends:
           {
           std::string dep = copy;
@@ -227,6 +245,12 @@ bool cmAddCustomTargetCommand
       cmSystemTools::CollapseFullPath(working_directory, build_dir);
     }
 
+  if (commandLines.empty() && !byproducts.empty())
+    {
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+      "BYPRODUCTS may not be specified without any COMMAND");
+    return true;
+    }
   if (commandLines.empty() && uses_terminal)
     {
     this->Makefile->IssueMessage(cmake::FATAL_ERROR,
@@ -238,7 +262,8 @@ bool cmAddCustomTargetCommand
   bool escapeOldStyle = !verbatim;
   cmTarget* target =
     this->Makefile->AddUtilityCommand(targetName, excludeFromAll,
-                                      working_directory.c_str(), depends,
+                                      working_directory.c_str(),
+                                      byproducts, depends,
                                       commandLines, escapeOldStyle, comment,
                                       uses_terminal);
 
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index dd2a1b8..b304f28 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -353,10 +353,11 @@ void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
     }
 
   // Pass the call to the makefile instance.
+  std::vector<std::string> no_byproducts;
   std::vector<std::string> no_depends;
   const char* no_comment = 0;
   const char* no_working_dir = 0;
-  mf->AddCustomCommandToTarget(target, no_depends, commandLines,
+  mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
                                cctype, no_comment, no_working_dir);
 }
 
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 45369cc..2afb029 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -28,6 +28,7 @@ cmCustomCommand::cmCustomCommand()
 //----------------------------------------------------------------------------
 cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
   Outputs(r.Outputs),
+  Byproducts(r.Byproducts),
   Depends(r.Depends),
   CommandLines(r.CommandLines),
   HaveComment(r.HaveComment),
@@ -49,6 +50,7 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
     }
 
   this->Outputs = r.Outputs;
+  this->Byproducts= r.Byproducts;
   this->Depends = r.Depends;
   this->CommandLines = r.CommandLines;
   this->HaveComment = r.HaveComment;
@@ -66,11 +68,13 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
 //----------------------------------------------------------------------------
 cmCustomCommand::cmCustomCommand(cmMakefile const* mf,
                                  const std::vector<std::string>& outputs,
+                                 const std::vector<std::string>& byproducts,
                                  const std::vector<std::string>& depends,
                                  const cmCustomCommandLines& commandLines,
                                  const char* comment,
                                  const char* workingDirectory):
   Outputs(outputs),
+  Byproducts(byproducts),
   Depends(depends),
   CommandLines(commandLines),
   HaveComment(comment?true:false),
@@ -100,6 +104,12 @@ const std::vector<std::string>& cmCustomCommand::GetOutputs() const
 }
 
 //----------------------------------------------------------------------------
+const std::vector<std::string>& cmCustomCommand::GetByproducts() const
+{
+  return this->Byproducts;
+}
+
+//----------------------------------------------------------------------------
 const std::vector<std::string>& cmCustomCommand::GetDepends() const
 {
   return this->Depends;
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 283a0e4..0bfaef2 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -32,6 +32,7 @@ public:
   /** Main constructor specifies all information for the command.  */
   cmCustomCommand(cmMakefile const* mf,
                   const std::vector<std::string>& outputs,
+                  const std::vector<std::string>& byproducts,
                   const std::vector<std::string>& depends,
                   const cmCustomCommandLines& commandLines,
                   const char* comment,
@@ -42,6 +43,9 @@ public:
   /** Get the output file produced by the command.  */
   const std::vector<std::string>& GetOutputs() const;
 
+  /** Get the extra files produced by the command.  */
+  const std::vector<std::string>& GetByproducts() const;
+
   /** Get the vector that holds the list of dependencies.  */
   const std::vector<std::string>& GetDepends() const;
 
@@ -86,6 +90,7 @@ public:
 
 private:
   std::vector<std::string> Outputs;
+  std::vector<std::string> Byproducts;
   std::vector<std::string> Depends;
   cmCustomCommandLines CommandLines;
   bool HaveComment;
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 1bca6e6..162d7a1 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -91,6 +91,12 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
 }
 
 //----------------------------------------------------------------------------
+std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
+{
+  return this->CC.GetByproducts();
+}
+
+//----------------------------------------------------------------------------
 std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
 {
   if (!this->DependsDone)
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 0d8a0a4..b4ae014 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -42,6 +42,7 @@ public:
   const char* GetComment() const;
   std::string GetWorkingDirectory() const;
   std::vector<std::string> const& GetOutputs() const;
+  std::vector<std::string> const& GetByproducts() const;
   std::vector<std::string> const& GetDepends() const;
 };
 
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 4d49fe3..b9c9b3b 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2510,10 +2510,11 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
   target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
 
   std::vector<std::string> no_outputs;
+  std::vector<std::string> no_byproducts;
   std::vector<std::string> no_depends;
   // Store the custom command in the target.
-  cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
-                     workingDirectory);
+  cmCustomCommand cc(0, no_outputs, no_byproducts, no_depends,
+                     *commandLines, 0, workingDirectory);
   cc.SetUsesTerminal(uses_terminal);
   target.AddPostBuildCommand(cc);
   target.SetProperty("EchoString", message);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 745515b..e6ce45d 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -341,9 +341,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
   // overwritten by the CreateVCProjBuildRule.
   // (this could be avoided with per-target source files)
   std::string no_main_dependency = "";
+  std::vector<std::string> no_byproducts;
   if(cmSourceFile* file =
      mf->AddCustomCommandToOutput(
-       stamps, listFiles,
+       stamps, no_byproducts, listFiles,
        no_main_dependency, commandLines, "Checking Build System",
        no_working_directory, true))
     {
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 5e7a898..b9f64e2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -477,7 +477,9 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
           this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)");
         cmCustomCommandLines commandLines;
         commandLines.push_back(makeHelper);
+        std::vector<std::string> no_byproducts;
         lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(),
+                                                    no_byproducts,
                                                     no_depends,
                                                     commandLines,
                                                     cmTarget::POST_BUILD,
@@ -1368,6 +1370,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
     cmCustomCommand command(this->CurrentMakefile,
       std::vector<std::string>(),
       std::vector<std::string>(),
+      std::vector<std::string>(),
       cmd,
       "Creating symlinks",
       "");
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 3c39b62..0b0d971 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -440,10 +440,18 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
   cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
 
   const std::vector<std::string> &outputs = ccg.GetOutputs();
-  cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
+  const std::vector<std::string> &byproducts = ccg.GetByproducts();
+  cmNinjaDeps ninjaOutputs(outputs.size()+byproducts.size()), ninjaDeps;
 
+#if 0
+#error TODO: Once CC in an ExternalProject target must provide the \
+    file of each imported target that has an add_dependencies pointing \
+    at us.  How to know which ExternalProject step actually provides it?
+#endif
   std::transform(outputs.begin(), outputs.end(),
                  ninjaOutputs.begin(), MapToNinjaPath());
+  std::transform(byproducts.begin(), byproducts.end(),
+                 ninjaOutputs.begin() + outputs.size(), MapToNinjaPath());
   this->AppendCustomCommandDeps(ccg, ninjaDeps);
 
   for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index c14fb2b..b9a5074 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -821,10 +821,12 @@ cmLocalVisualStudio6Generator::MaybeCreateOutputDir(cmTarget& target,
   command.push_back("make_directory");
   command.push_back(outDir);
   std::vector<std::string> no_output;
+  std::vector<std::string> no_byproducts;
   std::vector<std::string> no_depends;
   cmCustomCommandLines commands;
   commands.push_back(command);
-  pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
+  pcc.reset(new cmCustomCommand(0, no_output, no_byproducts,
+                                no_depends, commands, 0, 0));
   pcc->SetEscapeOldStyle(false);
   pcc->SetEscapeAllowMakeVars(true);
   return pcc;
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 9680d43..f01aa6b 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -95,10 +95,12 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
   command.push_back("make_directory");
   command.push_back(impDir);
   std::vector<std::string> no_output;
+  std::vector<std::string> no_byproducts;
   std::vector<std::string> no_depends;
   cmCustomCommandLines commands;
   commands.push_back(command);
-  pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
+  pcc.reset(new cmCustomCommand(0, no_output, no_byproducts,
+                                no_depends, commands, 0, 0));
   pcc->SetEscapeOldStyle(false);
   pcc->SetEscapeAllowMakeVars(true);
   return pcc;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 7e5e4e7..61807b2 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -880,13 +880,14 @@ void cmMakefile::ConfigureFinalPass()
 //----------------------------------------------------------------------------
 void
 cmMakefile::AddCustomCommandToTarget(const std::string& target,
+                                   const std::vector<std::string>& byproducts,
                                      const std::vector<std::string>& depends,
                                      const cmCustomCommandLines& commandLines,
                                      cmTarget::CustomCommandType type,
                                      const char* comment,
                                      const char* workingDir,
                                      bool escapeOldStyle,
-                                     bool uses_terminal) const
+                                     bool uses_terminal)
 {
   // Find the target to which to add the custom command.
   cmTargets::iterator ti = this->Targets.find(target);
@@ -936,9 +937,20 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
     this->IssueMessage(cmake::FATAL_ERROR, e.str());
     return;
     }
+
+  // Always create the byproduct sources and mark them generated.
+  for(std::vector<std::string>::const_iterator o = byproducts.begin();
+      o != byproducts.end(); ++o)
+    {
+    if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+      {
+      out->SetProperty("GENERATED", "1");
+      }
+    }
+
   // Add the command to the appropriate build step for the target.
   std::vector<std::string> no_output;
-  cmCustomCommand cc(this, no_output, depends,
+  cmCustomCommand cc(this, no_output, byproducts, depends,
                      commandLines, comment, workingDir);
   cc.SetEscapeOldStyle(escapeOldStyle);
   cc.SetEscapeAllowMakeVars(true);
@@ -960,6 +972,7 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
 //----------------------------------------------------------------------------
 cmSourceFile*
 cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+                                  const std::vector<std::string>& byproducts,
                                      const std::vector<std::string>& depends,
                                      const std::string& main_dependency,
                                      const cmCustomCommandLines& commandLines,
@@ -1058,6 +1071,14 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
       out->SetProperty("GENERATED", "1");
       }
     }
+  for(std::vector<std::string>::const_iterator o = byproducts.begin();
+      o != byproducts.end(); ++o)
+    {
+    if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+      {
+      out->SetProperty("GENERATED", "1");
+      }
+    }
 
   // Attach the custom command to the file.
   if(file)
@@ -1070,8 +1091,8 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
       }
 
     cmCustomCommand* cc =
-      new cmCustomCommand(this, outputs, depends2, commandLines,
-                          comment, workingDir);
+      new cmCustomCommand(this, outputs, byproducts, depends2,
+                          commandLines, comment, workingDir);
     cc->SetEscapeOldStyle(escapeOldStyle);
     cc->SetEscapeAllowMakeVars(true);
     cc->SetUsesTerminal(uses_terminal);
@@ -1128,7 +1149,9 @@ cmMakefile::AddCustomCommandToOutput(const std::string& output,
 {
   std::vector<std::string> outputs;
   outputs.push_back(output);
-  return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+  std::vector<std::string> no_byproducts;
+  return this->AddCustomCommandToOutput(outputs, no_byproducts,
+                                        depends, main_dependency,
                                         commandLines, comment, workingDir,
                                         replace, escapeOldStyle,
                                         uses_terminal);
@@ -1150,7 +1173,9 @@ cmMakefile::AddCustomCommandOldStyle(const std::string& target,
     // In the old-style signature if the source and target were the
     // same then it added a post-build rule to the target.  Preserve
     // this behavior.
-    this->AddCustomCommandToTarget(target, depends, commandLines,
+    std::vector<std::string> no_byproducts;
+    this->AddCustomCommandToTarget(target, no_byproducts,
+                                   depends, commandLines,
                                    cmTarget::POST_BUILD, comment, 0);
     return;
     }
@@ -1251,6 +1276,23 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
                               bool escapeOldStyle, const char* comment,
                               bool uses_terminal)
 {
+  std::vector<std::string> no_byproducts;
+  return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
+                                 no_byproducts, depends, commandLines,
+                                 escapeOldStyle, comment, uses_terminal);
+}
+
+//----------------------------------------------------------------------------
+cmTarget*
+cmMakefile::AddUtilityCommand(const std::string& utilityName,
+                              bool excludeFromAll,
+                              const char* workingDirectory,
+                              const std::vector<std::string>& byproducts,
+                              const std::vector<std::string>& depends,
+                              const cmCustomCommandLines& commandLines,
+                              bool escapeOldStyle, const char* comment,
+                              bool uses_terminal)
+{
   // Create a target instance for this utility.
   cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
   if (excludeFromAll)
@@ -1270,10 +1312,12 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
     force += cmake::GetCMakeFilesDirectory();
     force += "/";
     force += utilityName;
+    std::vector<std::string> forced;
+    forced.push_back(force);
     std::string no_main_dependency = "";
     bool no_replace = false;
-    this->AddCustomCommandToOutput(force, depends,
-                                   no_main_dependency,
+    this->AddCustomCommandToOutput(forced, byproducts,
+                                   depends, no_main_dependency,
                                    commandLines, comment,
                                    workingDirectory, no_replace,
                                    escapeOldStyle, uses_terminal);
@@ -1289,6 +1333,16 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
       cmSystemTools::Error("Could not get source file entry for ",
                           force.c_str());
       }
+
+    // Always create the byproduct sources and mark them generated.
+    for(std::vector<std::string>::const_iterator o = byproducts.begin();
+        o != byproducts.end(); ++o)
+      {
+      if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+        {
+        out->SetProperty("GENERATED", "1");
+        }
+      }
     }
   return target;
 }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 73c299e..0458d54 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -170,14 +170,16 @@ public:
 
   /** Add a custom command to the build.  */
   void AddCustomCommandToTarget(const std::string& target,
+                                const std::vector<std::string>& byproducts,
                                 const std::vector<std::string>& depends,
                                 const cmCustomCommandLines& commandLines,
                                 cmTarget::CustomCommandType type,
                                 const char* comment, const char* workingDir,
                                 bool escapeOldStyle = true,
-                                bool uses_terminal = false) const;
+                                bool uses_terminal = false);
   cmSourceFile* AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
+    const std::vector<std::string>& byproducts,
     const std::vector<std::string>& depends,
     const std::string& main_dependency,
     const cmCustomCommandLines& commandLines,
@@ -242,6 +244,15 @@ public:
                               bool escapeOldStyle = true,
                               const char* comment = 0,
                               bool uses_terminal = false);
+  cmTarget* AddUtilityCommand(const std::string& utilityName,
+                              bool excludeFromAll,
+                              const char* workingDirectory,
+                              const std::vector<std::string>& byproducts,
+                              const std::vector<std::string>& depends,
+                              const cmCustomCommandLines& commandLines,
+                              bool escapeOldStyle = true,
+                              const char* comment = 0,
+                              bool uses_terminal = false);
 
   /**
    * Add a link library to the build.
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 48c4a2d..25931f3 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -256,7 +256,7 @@ cmNinjaNormalTargetGenerator
                                         /*deptype*/ "",
                                         rspfile,
                                         rspcontent,
-                                        /*restat*/ "",
+                                        /*restat*/ "$RESTAT",
                                         /*generator*/ false);
   }
 
@@ -556,6 +556,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     &postBuildCmdLines
   };
 
+  cmNinjaDeps byproducts;
   for (unsigned i = 0; i != 3; ++i)
     {
     for (std::vector<cmCustomCommand>::const_iterator
@@ -564,6 +565,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
       {
       cmCustomCommandGenerator ccg(*ci, cfgName, mf);
       localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
+      std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
+      std::transform(ccByproducts.begin(), ccByproducts.end(),
+                     std::back_inserter(byproducts), MapToNinjaPath());
       }
     }
 
@@ -611,6 +615,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(),
     orderOnlyDeps);
 
+  // Ninja should restat after linking if and only if there are byproducts.
+  vars["RESTAT"] = byproducts.empty()? "" : "1";
+
+  for (cmNinjaDeps::const_iterator oi = byproducts.begin(),
+         oe = byproducts.end();
+       oi != oe; ++oi)
+    {
+    this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+    outputs.push_back(*oi);
+    }
+
   // Write the build statement for this target.
   globalGen.WriteBuild(this->GetBuildFileStream(),
                         comment.str(),
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 57fbcd3..7967762 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -538,8 +538,11 @@ cmNinjaTargetGenerator
     cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
                                  this->GetMakefile());
     const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
+    const std::vector<std::string>& ccbyproducts= ccg.GetByproducts();
     std::transform(ccoutputs.begin(), ccoutputs.end(),
                    std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+    std::transform(ccbyproducts.begin(), ccbyproducts.end(),
+                   std::back_inserter(orderOnlyDeps), MapToNinjaPath());
     }
 
   if (!orderOnlyDeps.empty())
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index c0a14ec..42d6b46 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -27,8 +27,11 @@ cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
 
 void cmNinjaUtilityTargetGenerator::Generate()
 {
+  std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
+  utilCommandName += this->GetTargetName() + ".util";
+
   std::vector<std::string> commands;
-  cmNinjaDeps deps, outputs;
+  cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
 
   const std::vector<cmCustomCommand> *cmdLists[2] = {
     &this->GetTarget()->GetPreBuildCommands(),
@@ -44,6 +47,9 @@ void cmNinjaUtilityTargetGenerator::Generate()
                                    this->GetMakefile());
       this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
       this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
+      std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
+      std::transform(ccByproducts.begin(), ccByproducts.end(),
+                     std::back_inserter(util_outputs), MapToNinjaPath());
       if (ci->GetUsesTerminal())
         uses_terminal = true;
     }
@@ -64,8 +70,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
 
       // Depend on all custom command outputs.
       const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
+      const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
       std::transform(ccOutputs.begin(), ccOutputs.end(),
                      std::back_inserter(deps), MapToNinjaPath());
+      std::transform(ccByproducts.begin(), ccByproducts.end(),
+                     std::back_inserter(deps), MapToNinjaPath());
       }
     }
 
@@ -107,15 +116,19 @@ void cmNinjaUtilityTargetGenerator::Generate()
     if (command.find('$') != std::string::npos)
       return;
 
-    std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
-    utilCommandName += this->GetTargetName() + ".util";
+    for (cmNinjaDeps::const_iterator
+           oi = util_outputs.begin(), oe = util_outputs.end();
+         oi != oe; ++oi)
+      {
+      this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+      }
 
     this->GetGlobalGenerator()->WriteCustomCommandBuild(
       command,
       desc,
       "Utility command for " + this->GetTargetName(),
       uses_terminal,
-      cmNinjaDeps(1, utilCommandName),
+      util_outputs,
       deps);
 
     this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 929cbc0..8f9c091 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -438,7 +438,8 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
     // rejection in cmMakefile::AddCustomCommandToTarget because we know
     // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
     std::vector<std::string> no_output;
-    cmCustomCommand cc(makefile, no_output, depends,
+    std::vector<std::string> no_byproducts;
+    cmCustomCommand cc(makefile, no_output, no_byproducts, depends,
                        commandLines, autogenComment.c_str(),
                        workingDirectory.c_str());
     cc.SetEscapeOldStyle(false);
@@ -451,7 +452,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
     cmTarget* autogenTarget = 0;
     if (!rcc_output.empty())
       {
-      makefile->AddCustomCommandToOutput(rcc_output, depends, "",
+      std::vector<std::string> no_byproducts;
+      makefile->AddCustomCommandToOutput(rcc_output, no_byproducts,
+                                         depends, "",
                                          commandLines, 0,
                                          workingDirectory.c_str(),
                                          false, false);
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 3e29683..ab28eca 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -716,6 +716,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     )
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommand")
 
+  ADD_TEST_MACRO(CustomCommandByproducts CustomCommandByproducts)
+
   ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND})
 
   add_test(CustomCommandWorkingDirectory  ${CMAKE_CTEST_COMMAND}
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index e260070..915da0a 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -117,6 +117,7 @@ add_custom_command(
   COMMAND ${CMAKE_COMMAND} -E echo " Copying doc1pre.txt to doc2post.txt."
   COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc1pre.txt
                                    ${PROJECT_BINARY_DIR}/doc2post.txt
+  BYPRODUCTS ${PROJECT_BINARY_DIR}/doc2post.txt
   COMMENT "Running TDocument post-build commands"
   )
 
diff --git a/Tests/CustomCommandByproducts/CMakeLists.txt b/Tests/CustomCommandByproducts/CMakeLists.txt
new file mode 100644
index 0000000..c39a536
--- /dev/null
+++ b/Tests/CustomCommandByproducts/CMakeLists.txt
@@ -0,0 +1,103 @@
+cmake_minimum_required(VERSION 3.1)
+project(CustomCommandByproducts C)
+
+# Generate a byproduct in a rule that runs in the target consuming it.
+add_custom_command(
+  OUTPUT timestamp1.txt
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct1.c.in byproduct1.c
+  BYPRODUCTS byproduct1.c
+  COMMAND ${CMAKE_COMMAND} -E touch timestamp1.txt
+  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/byproduct1.c.in
+  )
+
+# Generate a byproduct in a rule that runs in a dependency of the consumer.
+add_custom_command(
+  OUTPUT timestamp2.txt
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct2.c.in byproduct2.c
+  BYPRODUCTS byproduct2.c
+  COMMAND ${CMAKE_COMMAND} -E touch timestamp2.txt
+  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/byproduct2.c.in
+  )
+add_custom_target(Producer2 DEPENDS timestamp2.txt)
+
+# Generate a byproduct in a custom target.
+add_custom_target(Producer3_4
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct3.c.in byproduct3.c
+  BYPRODUCTS byproduct3.c
+  )
+
+# Generate a byproduct in a custom target POST_BUILD command.
+add_custom_command(
+  TARGET Producer3_4 POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct4.c.in byproduct4.c
+  BYPRODUCTS byproduct4.c
+  )
+
+add_executable(ProducerExe ProducerExe.c)
+
+# Generate a byproduct in an executable POST_BUILD command.
+add_custom_command(
+  TARGET ProducerExe POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct5.c.in byproduct5.c
+  BYPRODUCTS byproduct5.c
+  )
+
+# Generate a byproduct in an executable PRE_LINK command.
+add_custom_command(
+  TARGET ProducerExe PRE_LINK
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct6.c.in byproduct6.c
+  BYPRODUCTS byproduct6.c
+  )
+
+# Generate a byproduct in an executable PRE_BUILD command.
+add_custom_command(
+  TARGET ProducerExe PRE_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct7.c.in byproduct7.c
+  BYPRODUCTS byproduct7.c
+  )
+
+# Generate a byproduct in a custom command that consumes other byproducts.
+add_custom_command(OUTPUT timestamp8.txt
+  COMMAND ${CMAKE_COMMAND} -E copy_if_different
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct8.c.in byproduct8.c
+  COMMAND ${CMAKE_COMMAND} -E touch timestamp8.txt
+  BYPRODUCTS byproduct8.c
+  DEPENDS
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct2.c
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct3.c
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct4.c
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct5.c
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct6.c
+    ${CMAKE_CURRENT_BINARY_DIR}/byproduct7.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/byproduct8.c.in
+  )
+
+# Add an executable consuming all the byproducts.
+add_executable(CustomCommandByproducts
+  CustomCommandByproducts.c
+  byproduct1.c timestamp1.txt
+  byproduct2.c
+  byproduct3.c
+  byproduct4.c
+  byproduct5.c
+  byproduct6.c
+  byproduct7.c
+  byproduct8.c timestamp8.txt
+  )
+add_dependencies(CustomCommandByproducts Producer2)
+add_dependencies(CustomCommandByproducts Producer3_4)
+add_dependencies(CustomCommandByproducts ProducerExe)
+
+if(CMAKE_GENERATOR STREQUAL "Ninja")
+  add_custom_target(CheckNinja ALL
+    COMMENT "Checking build.ninja"
+    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/ninja-check.cmake
+    )
+endif()
diff --git a/Tests/CustomCommandByproducts/CustomCommandByproducts.c b/Tests/CustomCommandByproducts/CustomCommandByproducts.c
new file mode 100644
index 0000000..d9db9e6
--- /dev/null
+++ b/Tests/CustomCommandByproducts/CustomCommandByproducts.c
@@ -0,0 +1,21 @@
+extern int byproduct1(void);
+extern int byproduct2(void);
+extern int byproduct3(void);
+extern int byproduct4(void);
+extern int byproduct5(void);
+extern int byproduct6(void);
+extern int byproduct7(void);
+extern int byproduct8(void);
+int main(void)
+{
+  return (
+    byproduct1() +
+    byproduct2() +
+    byproduct3() +
+    byproduct4() +
+    byproduct5() +
+    byproduct6() +
+    byproduct7() +
+    byproduct8() +
+    0);
+}
diff --git a/Tests/CustomCommandByproducts/ProducerExe.c b/Tests/CustomCommandByproducts/ProducerExe.c
new file mode 100644
index 0000000..78f2de1
--- /dev/null
+++ b/Tests/CustomCommandByproducts/ProducerExe.c
@@ -0,0 +1 @@
+int main(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct1.c.in b/Tests/CustomCommandByproducts/byproduct1.c.in
new file mode 100644
index 0000000..5c3cc24
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct1.c.in
@@ -0,0 +1 @@
+int byproduct1(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct2.c.in b/Tests/CustomCommandByproducts/byproduct2.c.in
new file mode 100644
index 0000000..eeb69ef
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct2.c.in
@@ -0,0 +1 @@
+int byproduct2(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct3.c.in b/Tests/CustomCommandByproducts/byproduct3.c.in
new file mode 100644
index 0000000..7d15310
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct3.c.in
@@ -0,0 +1 @@
+int byproduct3(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct4.c.in b/Tests/CustomCommandByproducts/byproduct4.c.in
new file mode 100644
index 0000000..8b243dd
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct4.c.in
@@ -0,0 +1 @@
+int byproduct4(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct5.c.in b/Tests/CustomCommandByproducts/byproduct5.c.in
new file mode 100644
index 0000000..47f5990
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct5.c.in
@@ -0,0 +1 @@
+int byproduct5(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct6.c.in b/Tests/CustomCommandByproducts/byproduct6.c.in
new file mode 100644
index 0000000..d70c14f
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct6.c.in
@@ -0,0 +1 @@
+int byproduct6(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct7.c.in b/Tests/CustomCommandByproducts/byproduct7.c.in
new file mode 100644
index 0000000..0be5006
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct7.c.in
@@ -0,0 +1 @@
+int byproduct7(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/byproduct8.c.in b/Tests/CustomCommandByproducts/byproduct8.c.in
new file mode 100644
index 0000000..abefd62
--- /dev/null
+++ b/Tests/CustomCommandByproducts/byproduct8.c.in
@@ -0,0 +1 @@
+int byproduct8(void) { return 0; }
diff --git a/Tests/CustomCommandByproducts/ninja-check.cmake b/Tests/CustomCommandByproducts/ninja-check.cmake
new file mode 100644
index 0000000..2fc3cc2
--- /dev/null
+++ b/Tests/CustomCommandByproducts/ninja-check.cmake
@@ -0,0 +1,20 @@
+file(READ build.ninja build_ninja)
+if("${build_ninja}" MATCHES [====[
+# Unknown Build Time Dependencies.
+# Tell Ninja that they may appear as side effects of build rules
+# otherwise ordered by order-only dependencies.
+
+((build [^:]*: phony [^\n]*
+)*)# ========]====])
+  set(phony "${CMAKE_MATCH_1}")
+  if(NOT phony)
+    message(STATUS "build.ninja correctly does not have extra phony rules")
+  else()
+    string(REGEX REPLACE "\n+$" "" phony "${phony}")
+    string(REGEX REPLACE "\n" "\n  " phony "  ${phony}")
+    message(FATAL_ERROR "build.ninja incorrectly has extra phony rules:\n"
+      "${phony}")
+  endif()
+else()
+  message(FATAL_ERROR "build.ninja is incorrectly missing expected block")
+endif()
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index d0f429a..2f5c938 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -6,4 +6,5 @@ run_cmake(BadArgument)
 run_cmake(NoArguments)
 run_cmake(NoOutputOrTarget)
 run_cmake(OutputAndTarget)
+run_cmake(SourceByproducts)
 run_cmake(SourceUsesTerminal)
diff --git a/Tests/RunCMake/add_custom_command/SourceByproducts-result.txt b/Tests/RunCMake/add_custom_command/SourceByproducts-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceByproducts-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/SourceByproducts-stderr.txt b/Tests/RunCMake/add_custom_command/SourceByproducts-stderr.txt
new file mode 100644
index 0000000..a9cd64c
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceByproducts-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceByproducts.cmake:1 \(add_custom_command\):
+  add_custom_command BYPRODUCTS may not be specified with SOURCE signatures
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/SourceByproducts.cmake b/Tests/RunCMake/add_custom_command/SourceByproducts.cmake
new file mode 100644
index 0000000..824f41d
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceByproducts.cmake
@@ -0,0 +1 @@
+add_custom_command(SOURCE t TARGET t BYPRODUCTS b)
diff --git a/Tests/RunCMake/add_custom_target/ByproductsNoCommand-result.txt b/Tests/RunCMake/add_custom_target/ByproductsNoCommand-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/ByproductsNoCommand-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_target/ByproductsNoCommand-stderr.txt b/Tests/RunCMake/add_custom_target/ByproductsNoCommand-stderr.txt
new file mode 100644
index 0000000..6c80ca6
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/ByproductsNoCommand-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at ByproductsNoCommand.cmake:1 \(add_custom_target\):
+  BYPRODUCTS may not be specified without any COMMAND
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_target/ByproductsNoCommand.cmake b/Tests/RunCMake/add_custom_target/ByproductsNoCommand.cmake
new file mode 100644
index 0000000..6c142a2
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/ByproductsNoCommand.cmake
@@ -0,0 +1 @@
+add_custom_target(MyTarget BYPRODUCTS a b c d)
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index a612da9..92c4a38 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -2,4 +2,5 @@ include(RunCMake)
 
 run_cmake(NoArguments)
 run_cmake(BadTargetName)
+run_cmake(ByproductsNoCommand)
 run_cmake(UsesTerminalNoCommand)

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=67bd514adce689f4c7f537cdc446c01f7373f5a5
commit 67bd514adce689f4c7f537cdc446c01f7373f5a5
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Nov 13 18:32:44 2014 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 16:16:00 2014 -0500

    Ninja: Refactor restat to be a string internally
    
    This will allow values other than "" and "1" to be generated in
    the rules.ninja file.

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 60ab3e4..6f0586b 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -242,7 +242,7 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
                 /*deptype*/ "",
                 /*rspfile*/ "",
                 /*rspcontent*/ "",
-                /*restat*/ true,
+                /*restat*/ "1",
                 /*generator*/ false);
 }
 
@@ -309,7 +309,7 @@ cmGlobalNinjaGenerator::AddMacOSXContentRule()
                 /*deptype*/ "",
                 /*rspfile*/ "",
                 /*rspcontent*/ "",
-                /*restat*/ false,
+                /*restat*/ "",
                 /*generator*/ false);
 }
 
@@ -344,7 +344,7 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
                                        const std::string& deptype,
                                        const std::string& rspfile,
                                        const std::string& rspcontent,
-                                       bool restat,
+                                       const std::string& restat,
                                        bool generator)
 {
   // Make sure the rule has a name.
@@ -408,10 +408,10 @@ void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
     os << "rspfile_content = " << rspcontent << "\n";
     }
 
-  if(restat)
+  if(!restat.empty())
     {
     cmGlobalNinjaGenerator::Indent(os, 1);
-    os << "restat = 1\n";
+    os << "restat = " << restat << "\n";
     }
 
   if(generator)
@@ -607,7 +607,7 @@ void cmGlobalNinjaGenerator::AddRule(const std::string& name,
                                      const std::string& deptype,
                                      const std::string& rspfile,
                                      const std::string& rspcontent,
-                                     bool restat,
+                                     const std::string& restat,
                                      bool generator)
 {
   // Do not add the same rule twice.
@@ -1122,7 +1122,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
             /*deptype=*/ "",
             /*rspfile=*/ "",
             /*rspcontent*/ "",
-            /*restat=*/ false,
+            /*restat=*/ "",
             /*generator=*/ true);
 
   cmLocalNinjaGenerator *ng = static_cast<cmLocalNinjaGenerator *>(lg);
@@ -1206,7 +1206,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
             /*deptype=*/ "",
             /*rspfile=*/ "",
             /*rspcontent*/ "",
-            /*restat=*/ false,
+            /*restat=*/ "",
             /*generator=*/ false);
   WriteBuild(os,
              "Clean all the built files.",
@@ -1229,7 +1229,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
             /*deptype=*/ "",
             /*rspfile=*/ "",
             /*rspcontent*/ "",
-            /*restat=*/ false,
+            /*restat=*/ "",
             /*generator=*/ false);
   WriteBuild(os,
              "Print all primary targets available.",
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index a166938..3d443d8 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -125,7 +125,7 @@ public:
                         const std::string& deptype,
                         const std::string& rspfile,
                         const std::string& rspcontent,
-                        bool restat,
+                        const std::string& restat,
                         bool generator);
 
   /**
@@ -245,7 +245,7 @@ public:
                const std::string& deptype,
                const std::string& rspfile,
                const std::string& rspcontent,
-               bool restat,
+               const std::string& restat,
                bool generator);
 
   bool HasRule(const std::string& name);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 0614ae7..48c4a2d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -256,7 +256,7 @@ cmNinjaNormalTargetGenerator
                                         /*deptype*/ "",
                                         rspfile,
                                         rspcontent,
-                                        /*restat*/ false,
+                                        /*restat*/ "",
                                         /*generator*/ false);
   }
 
@@ -278,7 +278,7 @@ cmNinjaNormalTargetGenerator
                                           /*deptype*/ "",
                                           /*rspfile*/ "",
                                           /*rspcontent*/ "",
-                                          /*restat*/ false,
+                                          /*restat*/ "",
                                           /*generator*/ false);
     else
       this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_LIBRARY",
@@ -292,7 +292,7 @@ cmNinjaNormalTargetGenerator
                                           /*deptype*/ "",
                                           /*rspfile*/ "",
                                           /*rspcontent*/ "",
-                                          /*restat*/ false,
+                                          /*restat*/ "",
                                           /*generator*/ false);
   }
 }
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 80213d8..57fbcd3 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -477,7 +477,7 @@ cmNinjaTargetGenerator
                                       deptype,
                                       /*rspfile*/ "",
                                       /*rspcontent*/ "",
-                                      /*restat*/ false,
+                                      /*restat*/ "",
                                       /*generator*/ false);
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ef42e57d470db499a41c8bca695391c3e3e5cb86
commit ef42e57d470db499a41c8bca695391c3e3e5cb86
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Nov 13 15:29:51 2014 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 16:16:00 2014 -0500

    Ninja: Use a TARGET_FILE variable to hold the link output file
    
    Use an explicit "$TARGET_FILE" variable instead of "$out" so that
    we can have multiple output files while still only referencing the
    main one in command lines.

diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 0cc3e3b..0614ae7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -194,12 +194,7 @@ cmNinjaNormalTargetGenerator
 
     vars.ObjectDir = "$OBJECT_DIR";
 
-    // TODO:
-    // Makefile generator expands <TARGET> to the plain target name
-    // with suffix. $out expands to a relative path. This difference
-    // could make trouble when switching to Ninja generator. Maybe
-    // using TARGET_NAME and RuleVariables::TargetName is a fix.
-    vars.Target = "$out";
+    vars.Target = "$TARGET_FILE";
 
     vars.SONameFlag = "$SONAME_FLAG";
     vars.TargetSOName = "$SONAME";
@@ -252,7 +247,7 @@ cmNinjaNormalTargetGenerator
             << this->GetVisibleTypeName() << ".";
     cmOStringStream description;
     description << "Linking " << this->TargetLinkLanguage << " "
-                << this->GetVisibleTypeName() << " $out";
+                << this->GetVisibleTypeName() << " $TARGET_FILE";
     this->GetGlobalGenerator()->AddRule(ruleName,
                                         linkCmd,
                                         description.str(),
@@ -326,7 +321,7 @@ cmNinjaNormalTargetGenerator
         this->GetLocalGenerator()->ConvertToOutputFormat(
           mf->GetRequiredDefinition("CMAKE_COMMAND"),
           cmLocalGenerator::SHELL);
-      linkCmds.push_back(cmakeCommand + " -E remove $out");
+      linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE");
       }
       // TODO: Use ARCHIVE_APPEND for archives over a certain size.
       {
@@ -450,6 +445,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
                                     this->GetConfigName());
   bool useWatcomQuote = mf->IsOn(createRule+"_USE_WATCOM_QUOTE");
   cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
+
+  vars["TARGET_FILE"] =
+    localGen.ConvertToOutputFormat(targetOutputReal, cmLocalGenerator::SHELL);
+
   localGen.GetTargetFlags(vars["LINK_LIBRARIES"],
                           vars["FLAGS"],
                           vars["LINK_FLAGS"],
@@ -509,6 +508,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
                                               cmLocalGenerator::SHELL);
     vars["TARGET_IMPLIB"] = impLibPath;
     EnsureParentDirectoryExists(impLibPath);
+    if(target.HasImportLibrary())
+      {
+      outputs.push_back(targetOutputImplib);
+      }
     }
 
   if (!this->SetMsvcTargetPdbVariable(vars))
@@ -659,16 +662,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
       }
     }
 
-  if (!this->TargetNameImport.empty())
-    {
-    // Since using multiple outputs would mess up the $out variable, use an
-    // alias for the import library.
-    globalGen.WritePhonyBuild(this->GetBuildFileStream(),
-                              "Alias for import library.",
-                              cmNinjaDeps(1, targetOutputImplib),
-                              cmNinjaDeps(1, targetOutputReal));
-    }
-
   // Add aliases for the file name and the target name.
   globalGen.AddTargetAlias(this->TargetNameOut, &target);
   globalGen.AddTargetAlias(this->GetTargetName(), &target);

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=592644c42c58312aadf1fd1b28e95c7f0fbbb2f8
commit 592644c42c58312aadf1fd1b28e95c7f0fbbb2f8
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Nov 13 13:19:13 2014 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 16:16:00 2014 -0500

    Tests/BuildDepends: Drop unneeded help for Ninja
    
    The extra post-modification invocations of 'ninja' does not seem to be
    needed anymore for the BuildDepends test to pass.

diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 8df331e..6209bb8 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -28,10 +28,6 @@ function(help_xcode_depends)
   endif()
 endfunction()
 
-if("${CMAKE_GENERATOR}" MATCHES "Ninja")
-  set(HELP_NINJA 1) # TODO Why is this needed?
-endif()
-
 # The Intel compiler causes the MSVC linker to crash during
 # incremental linking, so avoid the /INCREMENTAL:YES flag.
 if(WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
@@ -218,7 +214,7 @@ try_compile(RESULT
   OUTPUT_VARIABLE OUTPUT)
 
 # Xcode is in serious need of help here
-if(HELP_XCODE OR HELP_NINJA)
+if(HELP_XCODE)
   try_compile(RESULT
     ${BuildDepends_BINARY_DIR}/Project
     ${BuildDepends_SOURCE_DIR}/Project

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2d75d7e56bc00c9abe51d39c4306084b24fe8cd5
commit 2d75d7e56bc00c9abe51d39c4306084b24fe8cd5
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 22:04:30 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:56:34 2014 -0500

    Help: Add notes for topic 'console-pool'

diff --git a/Help/release/dev/console-pool.rst b/Help/release/dev/console-pool.rst
new file mode 100644
index 0000000..19c2f19
--- /dev/null
+++ b/Help/release/dev/console-pool.rst
@@ -0,0 +1,8 @@
+console-pool
+------------
+
+* The :command:`add_custom_command` and :command:`add_custom_target`
+  commands learned a new ``USES_TERMINAL`` option to request that
+  the command be given direct access to the terminal if possible.
+  The :generator:`Ninja` generator will places such commands in the
+  ``console`` pool.

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f42d86f0b834c73b28a919ef1b4279753a6ec1bd
commit f42d86f0b834c73b28a919ef1b4279753a6ec1bd
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 21:42:18 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:56:33 2014 -0500

    Ninja: Implement USES_TERMINAL using the console pool if available

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 688eca4..60ab3e4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -250,6 +250,7 @@ void
 cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
                                                 const std::string& description,
                                                 const std::string& comment,
+                                                bool uses_terminal,
                                                 const cmNinjaDeps& outputs,
                                                 const cmNinjaDeps& deps,
                                                 const cmNinjaDeps& orderOnly)
@@ -266,6 +267,10 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
   cmNinjaVars vars;
   vars["COMMAND"] = cmd;
   vars["DESC"] = EncodeLiteral(description);
+  if (uses_terminal && SupportsConsolePool())
+    {
+    vars["pool"] = "console";
+    }
 
   this->WriteBuild(*this->BuildFileStream,
                    comment,
@@ -826,6 +831,7 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
     std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
     WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
                             "Assume dependencies for generated source file.",
+                            /*uses_terminal*/false,
                             cmNinjaDeps(1, i->first), deps);
   }
 }
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 38b5ef5..a166938 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -103,6 +103,7 @@ public:
   void WriteCustomCommandBuild(const std::string& command,
                                const std::string& description,
                                const std::string& comment,
+                               bool uses_terminal,
                                const cmNinjaDeps& outputs,
                                const cmNinjaDeps& deps = cmNinjaDeps(),
                                const cmNinjaDeps& orderOnly = cmNinjaDeps());
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 9225f64..3c39b62 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -468,6 +468,7 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
       this->BuildCommandLine(cmdLines),
       this->ConstructComment(ccg),
       "Custom command for " + ninjaOutputs[0],
+      cc->GetUsesTerminal(),
       ninjaOutputs,
       ninjaDeps,
       orderOnlyDeps);
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index f5d18dc..c0a14ec 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -35,6 +35,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
     &this->GetTarget()->GetPostBuildCommands()
   };
 
+  bool uses_terminal = false;
+
   for (unsigned i = 0; i != 2; ++i) {
     for (std::vector<cmCustomCommand>::const_iterator
          ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
@@ -42,6 +44,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
                                    this->GetMakefile());
       this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
       this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
+      if (ci->GetUsesTerminal())
+        uses_terminal = true;
     }
   }
 
@@ -110,6 +114,7 @@ void cmNinjaUtilityTargetGenerator::Generate()
       command,
       desc,
       "Utility command for " + this->GetTargetName(),
+      uses_terminal,
       cmNinjaDeps(1, utilCommandName),
       deps);
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f281ae01a2b89d8a7d327b3f6e73b727195d8dfd
commit f281ae01a2b89d8a7d327b3f6e73b727195d8dfd
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 21:40:43 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:56:33 2014 -0500

    Ninja: Remove unused declaration

diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 40a15a3..17cf517 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -116,7 +116,6 @@ protected:
   void WriteObjectBuildStatements();
   void WriteObjectBuildStatement(cmSourceFile const* source,
                                  bool writeOrderDependsTargetForTarget);
-  void WriteCustomCommandBuildStatement(cmCustomCommand *cc);
 
   cmNinjaDeps GetObjects() const
   { return this->Objects; }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d5eae5563f99fb28c99695fb4886f1bd40d98414
commit d5eae5563f99fb28c99695fb4886f1bd40d98414
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 21:40:14 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:56:33 2014 -0500

    Ninja: factor out the test for console pool support

diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 498ae9a..688eca4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1141,9 +1141,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
   cmNinjaVars variables;
   // Use 'console' pool to get non buffered output of the CMake re-run call
   // Available since Ninja 1.5
-  if(cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
-                                   ninjaVersion().c_str(),
-                                   "1.5") == false)
+  if(SupportsConsolePool())
     {
     variables["pool"] = "console";
     }
@@ -1185,6 +1183,12 @@ std::string cmGlobalNinjaGenerator::ninjaVersion() const
   return version;
 }
 
+bool cmGlobalNinjaGenerator::SupportsConsolePool() const
+{
+  return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+                                       ninjaVersion().c_str(), "1.5") == false;
+}
+
 void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
 {
   WriteRule(*this->RulesFileStream,
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index f666ee3..38b5ef5 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -299,6 +299,9 @@ public:
   virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
 
   std::string ninjaVersion() const;
+
+  bool SupportsConsolePool() const;
+
 protected:
 
   /// Overloaded methods. @see cmGlobalGenerator::Generate()

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4d1fedf46e9cbdb388728c9a986cbf89db810c73
commit 4d1fedf46e9cbdb388728c9a986cbf89db810c73
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 21:39:32 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:56:33 2014 -0500

    Give the interactive cache editor the USES_TERMINAL property

diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 5a3c238..4d49fe3 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2207,7 +2207,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
       = this->CreateGlobalTarget(this->GetPackageTargetName(),
                                  "Run CPack packaging tool...",
                                  &cpackCommandLines, depends,
-                                 workingDir.c_str());
+                                 workingDir.c_str(), /*uses_terminal*/false);
     }
   // CPack source
   const char* packageSourceTargetName = this->GetPackageSourceTargetName();
@@ -2231,8 +2231,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
         = this->CreateGlobalTarget(packageSourceTargetName,
                                    "Run CPack packaging tool for source...",
                                    &cpackCommandLines, depends,
-                                   workingDir.c_str()
-                                   );
+                                   workingDir.c_str(), /*uses_terminal*/false);
       }
     }
 
@@ -2257,7 +2256,8 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
     cpackCommandLines.push_back(singleLine);
     (*targets)[this->GetTestTargetName()]
       = this->CreateGlobalTarget(this->GetTestTargetName(),
-        "Running tests...", &cpackCommandLines, depends, 0);
+        "Running tests...", &cpackCommandLines, depends, 0,
+        /*uses_terminal*/false);
     }
 
   //Edit Cache
@@ -2280,7 +2280,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
       (*targets)[editCacheTargetName] =
         this->CreateGlobalTarget(
           editCacheTargetName, "Running CMake cache editor...",
-          &cpackCommandLines, depends, 0);
+          &cpackCommandLines, depends, 0, /*uses_terminal*/true);
       }
     else
       {
@@ -2293,7 +2293,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
         this->CreateGlobalTarget(
           editCacheTargetName,
           "No interactive CMake dialog available...",
-          &cpackCommandLines, depends, 0);
+          &cpackCommandLines, depends, 0, /*uses_terminal*/false);
       }
     }
 
@@ -2312,7 +2312,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
     (*targets)[rebuildCacheTargetName] =
       this->CreateGlobalTarget(
         rebuildCacheTargetName, "Running CMake to regenerate build system...",
-        &cpackCommandLines, depends, 0);
+        &cpackCommandLines, depends, 0, /*uses_terminal*/false);
     }
 
   //Install
@@ -2352,7 +2352,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
       (*targets)["list_install_components"]
         = this->CreateGlobalTarget("list_install_components",
           ostr.str().c_str(),
-          &cpackCommandLines, depends, 0);
+          &cpackCommandLines, depends, 0, /*uses_terminal*/false);
       }
     std::string cmd = cmakeCommand;
     cpackCommandLines.erase(cpackCommandLines.begin(),
@@ -2393,7 +2393,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
     (*targets)[this->GetInstallTargetName()] =
       this->CreateGlobalTarget(
         this->GetInstallTargetName(), "Install the project...",
-        &cpackCommandLines, depends, 0);
+        &cpackCommandLines, depends, 0, /*uses_terminal*/false);
 
     // install_local
     if(const char* install_local = this->GetInstallLocalTargetName())
@@ -2409,7 +2409,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
       (*targets)[install_local] =
         this->CreateGlobalTarget(
           install_local, "Installing only the local directory...",
-          &cpackCommandLines, depends, 0);
+          &cpackCommandLines, depends, 0, /*uses_terminal*/false);
       }
 
     // install_strip
@@ -2426,7 +2426,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
       (*targets)[install_strip] =
         this->CreateGlobalTarget(
           install_strip, "Installing the project stripped...",
-          &cpackCommandLines, depends, 0);
+          &cpackCommandLines, depends, 0, /*uses_terminal*/false);
       }
     }
 }
@@ -2500,7 +2500,8 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
   const std::string& name, const char* message,
   const cmCustomCommandLines* commandLines,
   std::vector<std::string> depends,
-  const char* workingDirectory)
+  const char* workingDirectory,
+  bool uses_terminal)
 {
   // Package
   cmTarget target;
@@ -2513,6 +2514,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
   // Store the custom command in the target.
   cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
                      workingDirectory);
+  cc.SetUsesTerminal(uses_terminal);
   target.AddPostBuildCommand(cc);
   target.SetProperty("EchoString", message);
   std::vector<std::string>::iterator dit;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 8a10d38..926efe7 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -385,7 +385,8 @@ protected:
   void CreateDefaultGlobalTargets(cmTargets* targets);
   cmTarget CreateGlobalTarget(const std::string& name, const char* message,
     const cmCustomCommandLines* commandLines,
-    std::vector<std::string> depends, const char* workingDir);
+    std::vector<std::string> depends, const char* workingDir,
+    bool uses_terminal);
 
   bool NeedSymbolicMark;
   bool UseLinkScript;

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe5d6e8c0f2e37bac0621a3b976d95c471891f38
commit fe5d6e8c0f2e37bac0621a3b976d95c471891f38
Author:     Peter Collingbourne <peter at pcc.me.uk>
AuthorDate: Wed Nov 5 21:37:52 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Nov 14 11:55:09 2014 -0500

    Add USES_TERMINAL option for custom commands
    
    Teach the add_custom_command and add_custom_target commands a new
    USES_TERMINAL option.  Use it to tell the generator to give the command
    direct access to the terminal if possible.

diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 2d67b98..cb0746b 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -18,7 +18,8 @@ The first signature is for adding a custom command to produce an output::
                      [IMPLICIT_DEPENDS <lang1> depend1
                                       [<lang2> depend2] ...]
                      [WORKING_DIRECTORY dir]
-                     [COMMENT comment] [VERBATIM] [APPEND])
+                     [COMMENT comment]
+                     [VERBATIM] [APPEND] [USES_TERMINAL])
 
 This defines a command to generate specified ``OUTPUT`` file(s).
 A target created in the same directory (``CMakeLists.txt`` file)
@@ -120,6 +121,11 @@ The options are:
   as a file on disk it should be marked with the :prop_sf:`SYMBOLIC`
   source file property.
 
+``USES_TERMINAL``
+  The command will be given direct access to the terminal if possible.
+  With the :generator:`Ninja` generator, this places the command in
+  the ``console`` pool.
+
 ``VERBATIM``
   All arguments to the commands will be escaped properly for the
   build tool so that the invoked command receives each argument
@@ -151,7 +157,8 @@ target is already built, the command will not execute.
                      COMMAND command1 [ARGS] [args1...]
                      [COMMAND command2 [ARGS] [args2...] ...]
                      [WORKING_DIRECTORY dir]
-                     [COMMENT comment] [VERBATIM])
+                     [COMMENT comment]
+                     [VERBATIM] [USES_TERMINAL])
 
 This defines a new command that will be associated with building the
 specified target.  When the command will happen is determined by which
diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst
index 4f8e190..8b7472d 100644
--- a/Help/command/add_custom_target.rst
+++ b/Help/command/add_custom_target.rst
@@ -9,7 +9,8 @@ Add a target with no output so it will always be built.
                     [COMMAND command2 [args2...] ...]
                     [DEPENDS depend depend depend ... ]
                     [WORKING_DIRECTORY dir]
-                    [COMMENT comment] [VERBATIM]
+                    [COMMENT comment]
+                    [VERBATIM] [USES_TERMINAL]
                     [SOURCES src1 [src2...]])
 
 Adds a target with the given name that executes the given commands.
@@ -74,6 +75,11 @@ The options are:
   is platform specific because there is no protection of
   tool-specific special characters.
 
+``USES_TERMINAL``
+  The command will be given direct access to the terminal if possible.
+  With the :generator:`Ninja` generator, this places the command in
+  the ``console`` pool.
+
 ``WORKING_DIRECTORY``
   Execute the command with the given current working directory.
   If it is a relative path it will be interpreted relative to the
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 2d19610..410f978 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -35,6 +35,7 @@ bool cmAddCustomCommandCommand
   std::vector<std::string> depends, outputs, output;
   bool verbatim = false;
   bool append = false;
+  bool uses_terminal = false;
   std::string implicit_depends_lang;
   cmCustomCommand::ImplicitDependsList implicit_depends;
 
@@ -102,6 +103,10 @@ bool cmAddCustomCommandCommand
       {
       append = true;
       }
+    else if(copy == "USES_TERMINAL")
+      {
+      uses_terminal = true;
+      }
     else if(copy == "TARGET")
       {
       doing = doing_target;
@@ -312,7 +317,7 @@ bool cmAddCustomCommandCommand
     this->Makefile->AddCustomCommandToTarget(target, no_depends,
                                              commandLines, cctype,
                                              comment, working.c_str(),
-                                             escapeOldStyle);
+                                             escapeOldStyle, uses_terminal);
     }
   else if(target.empty())
     {
@@ -321,7 +326,7 @@ bool cmAddCustomCommandCommand
                                              main_dependency,
                                              commandLines, comment,
                                              working.c_str(), false,
-                                             escapeOldStyle);
+                                             escapeOldStyle, uses_terminal);
 
     // Add implicit dependency scanning requests if any were given.
     if(!implicit_depends.empty())
@@ -346,6 +351,11 @@ bool cmAddCustomCommandCommand
         }
       }
     }
+  else if (uses_terminal)
+    {
+    this->SetError("USES_TERMINAL may not be used with SOURCE signatures");
+    return false;
+    }
   else
     {
     bool issueMessage = true;
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 64e76f3..fc4f8f1 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -48,6 +48,7 @@ bool cmAddCustomTargetCommand
   std::vector<std::string> depends;
   std::string working_directory;
   bool verbatim = false;
+  bool uses_terminal = false;
   std::string comment_buffer;
   const char* comment = 0;
   std::vector<std::string> sources;
@@ -93,6 +94,11 @@ bool cmAddCustomTargetCommand
       doing = doing_nothing;
       verbatim = true;
       }
+    else if(copy == "USES_TERMINAL")
+      {
+      doing = doing_nothing;
+      uses_terminal = true;
+      }
     else if (copy == "COMMENT")
       {
       doing = doing_comment;
@@ -221,12 +227,20 @@ bool cmAddCustomTargetCommand
       cmSystemTools::CollapseFullPath(working_directory, build_dir);
     }
 
+  if (commandLines.empty() && uses_terminal)
+    {
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+      "USES_TERMINAL may not be specified without any COMMAND");
+    return true;
+    }
+
   // Add the utility target to the makefile.
   bool escapeOldStyle = !verbatim;
   cmTarget* target =
     this->Makefile->AddUtilityCommand(targetName, excludeFromAll,
                                       working_directory.c_str(), depends,
-                                      commandLines, escapeOldStyle, comment);
+                                      commandLines, escapeOldStyle, comment,
+                                      uses_terminal);
 
   // Add additional user-specified source files to the target.
   target->AddSources(sources);
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index c161eb6..45369cc 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -22,6 +22,7 @@ cmCustomCommand::cmCustomCommand()
   this->HaveComment = false;
   this->EscapeOldStyle = true;
   this->EscapeAllowMakeVars = false;
+  this->UsesTerminal = false;
 }
 
 //----------------------------------------------------------------------------
@@ -34,7 +35,8 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
   WorkingDirectory(r.WorkingDirectory),
   EscapeAllowMakeVars(r.EscapeAllowMakeVars),
   EscapeOldStyle(r.EscapeOldStyle),
-  Backtrace(r.Backtrace)
+  Backtrace(r.Backtrace),
+  UsesTerminal(r.UsesTerminal)
 {
 }
 
@@ -56,6 +58,7 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
   this->EscapeOldStyle = r.EscapeOldStyle;
   this->ImplicitDepends = r.ImplicitDepends;
   this->Backtrace = r.Backtrace;
+  this->UsesTerminal = r.UsesTerminal;
 
   return *this;
 }
@@ -184,3 +187,15 @@ void cmCustomCommand::AppendImplicitDepends(ImplicitDependsList const& l)
   this->ImplicitDepends.insert(this->ImplicitDepends.end(),
                                l.begin(), l.end());
 }
+
+//----------------------------------------------------------------------------
+bool cmCustomCommand::GetUsesTerminal() const
+{
+  return this->UsesTerminal;
+}
+
+//----------------------------------------------------------------------------
+void cmCustomCommand::SetUsesTerminal(bool b)
+{
+  this->UsesTerminal = b;
+}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 21dbefb..283a0e4 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -79,6 +79,11 @@ public:
   void AppendImplicitDepends(ImplicitDependsList const&);
   ImplicitDependsList const& GetImplicitDepends() const;
 
+  /** Set/Get whether this custom command should be given access to the
+      real console (if possible).  */
+  bool GetUsesTerminal() const;
+  void SetUsesTerminal(bool b);
+
 private:
   std::vector<std::string> Outputs;
   std::vector<std::string> Depends;
@@ -90,6 +95,7 @@ private:
   bool EscapeOldStyle;
   cmListFileBacktrace Backtrace;
   ImplicitDependsList ImplicitDepends;
+  bool UsesTerminal;
 };
 
 #endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 8a8aadc..7e5e4e7 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -885,7 +885,8 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
                                      cmTarget::CustomCommandType type,
                                      const char* comment,
                                      const char* workingDir,
-                                     bool escapeOldStyle) const
+                                     bool escapeOldStyle,
+                                     bool uses_terminal) const
 {
   // Find the target to which to add the custom command.
   cmTargets::iterator ti = this->Targets.find(target);
@@ -941,6 +942,7 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
                      commandLines, comment, workingDir);
   cc.SetEscapeOldStyle(escapeOldStyle);
   cc.SetEscapeAllowMakeVars(true);
+  cc.SetUsesTerminal(uses_terminal);
   switch(type)
     {
     case cmTarget::PRE_BUILD:
@@ -964,7 +966,8 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
                                      const char* comment,
                                      const char* workingDir,
                                      bool replace,
-                                     bool escapeOldStyle)
+                                     bool escapeOldStyle,
+                                     bool uses_terminal)
 {
   // Make sure there is at least one output.
   if(outputs.empty())
@@ -1071,6 +1074,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
                           comment, workingDir);
     cc->SetEscapeOldStyle(escapeOldStyle);
     cc->SetEscapeAllowMakeVars(true);
+    cc->SetUsesTerminal(uses_terminal);
     file->SetCustomCommand(cc);
     this->UpdateOutputToSourceMap(outputs, file);
     }
@@ -1119,13 +1123,15 @@ cmMakefile::AddCustomCommandToOutput(const std::string& output,
                                      const char* comment,
                                      const char* workingDir,
                                      bool replace,
-                                     bool escapeOldStyle)
+                                     bool escapeOldStyle,
+                                     bool uses_terminal)
 {
   std::vector<std::string> outputs;
   outputs.push_back(output);
   return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
                                         commandLines, comment, workingDir,
-                                        replace, escapeOldStyle);
+                                        replace, escapeOldStyle,
+                                        uses_terminal);
 }
 
 //----------------------------------------------------------------------------
@@ -1242,7 +1248,8 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
                               const char* workingDirectory,
                               const std::vector<std::string>& depends,
                               const cmCustomCommandLines& commandLines,
-                              bool escapeOldStyle, const char* comment)
+                              bool escapeOldStyle, const char* comment,
+                              bool uses_terminal)
 {
   // Create a target instance for this utility.
   cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
@@ -1269,7 +1276,7 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
                                    no_main_dependency,
                                    commandLines, comment,
                                    workingDirectory, no_replace,
-                                   escapeOldStyle);
+                                   escapeOldStyle, uses_terminal);
     cmSourceFile* sf = target->AddSourceCMP0049(force);
 
     // The output is not actually created so mark it symbolic.
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 824513b..73c299e 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -174,7 +174,8 @@ public:
                                 const cmCustomCommandLines& commandLines,
                                 cmTarget::CustomCommandType type,
                                 const char* comment, const char* workingDir,
-                                bool escapeOldStyle = true) const;
+                                bool escapeOldStyle = true,
+                                bool uses_terminal = false) const;
   cmSourceFile* AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& depends,
@@ -182,7 +183,8 @@ public:
     const cmCustomCommandLines& commandLines,
     const char* comment, const char* workingDir,
     bool replace = false,
-    bool escapeOldStyle = true);
+    bool escapeOldStyle = true,
+    bool uses_terminal = false);
   cmSourceFile* AddCustomCommandToOutput(
     const std::string& output,
     const std::vector<std::string>& depends,
@@ -190,7 +192,8 @@ public:
     const cmCustomCommandLines& commandLines,
     const char* comment, const char* workingDir,
     bool replace = false,
-    bool escapeOldStyle = true);
+    bool escapeOldStyle = true,
+    bool uses_terminal = false);
   void AddCustomCommandOldStyle(const std::string& target,
                                 const std::vector<std::string>& outputs,
                                 const std::vector<std::string>& depends,
@@ -237,7 +240,8 @@ public:
                               const std::vector<std::string>& depends,
                               const cmCustomCommandLines& commandLines,
                               bool escapeOldStyle = true,
-                              const char* comment = 0);
+                              const char* comment = 0,
+                              bool uses_terminal = false);
 
   /**
    * Add a link library to the build.
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index b97cd16..e260070 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -483,3 +483,26 @@ add_custom_command(
   COMMAND ${CMAKE_COMMAND} -E touch "${gen_file}")
 
 add_library(NormDepends "${gen_file}")
+
+# Test that USES_TERMINAL is parsed correctly.
+# It seems much more difficult to test that USES_TERMINAL actually gives
+# the subprocess console access, as test output is piped through CTest,
+# and CTest itself might not be connected to the console.
+
+set(gen_file "${gen_path}/bar2.cxx")
+
+add_custom_command(
+  OUTPUT "${gen_file}"
+  DEPENDS "${gen_path}"
+  COMMAND ${CMAKE_COMMAND} -E touch "${gen_file}"
+  VERBATIM
+  USES_TERMINAL
+)
+
+add_library(UseConsole "${gen_file}")
+
+add_custom_target(UseConsoleTarget ALL
+  COMMAND ${CMAKE_COMMAND} -E echo "Custom console target."
+  VERBATIM
+  USES_TERMINAL
+)
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index a692600..d0f429a 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -6,3 +6,4 @@ run_cmake(BadArgument)
 run_cmake(NoArguments)
 run_cmake(NoOutputOrTarget)
 run_cmake(OutputAndTarget)
+run_cmake(SourceUsesTerminal)
diff --git a/Tests/RunCMake/add_custom_command/SourceUsesTerminal-result.txt b/Tests/RunCMake/add_custom_command/SourceUsesTerminal-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceUsesTerminal-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/SourceUsesTerminal-stderr.txt b/Tests/RunCMake/add_custom_command/SourceUsesTerminal-stderr.txt
new file mode 100644
index 0000000..1a76c54
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceUsesTerminal-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at SourceUsesTerminal.cmake:1 \(add_custom_command\):
+  add_custom_command USES_TERMINAL may not be used with SOURCE signatures
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/SourceUsesTerminal.cmake b/Tests/RunCMake/add_custom_command/SourceUsesTerminal.cmake
new file mode 100644
index 0000000..295fab1
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/SourceUsesTerminal.cmake
@@ -0,0 +1 @@
+add_custom_command(SOURCE t TARGET t USES_TERMINAL)
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index 4e4a8ae..a612da9 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -2,3 +2,4 @@ include(RunCMake)
 
 run_cmake(NoArguments)
 run_cmake(BadTargetName)
+run_cmake(UsesTerminalNoCommand)
diff --git a/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-result.txt b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-stderr.txt b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-stderr.txt
new file mode 100644
index 0000000..beafa7c
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at UsesTerminalNoCommand.cmake:1 \(add_custom_target\):
+  USES_TERMINAL may not be specified without any COMMAND
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand.cmake b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand.cmake
new file mode 100644
index 0000000..b0c207b
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/UsesTerminalNoCommand.cmake
@@ -0,0 +1 @@
+add_custom_target(MyTarget USES_TERMINAL)

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

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list