[Cmake-commits] CMake branch, next, updated. v3.2.0-875-gf377a02

Brad King brad.king at kitware.com
Fri Mar 6 15:26:51 EST 2015


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  f377a0273265f61a1fd056e63ab106020262827e (commit)
       via  d678084c293c0d82aeb426647aa97f1f6bd80f3e (commit)
      from  87f2a8a78ae564a0b964f5e2bb8b19778066811f (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=f377a0273265f61a1fd056e63ab106020262827e
commit f377a0273265f61a1fd056e63ab106020262827e
Merge: 87f2a8a d678084
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Mar 6 15:26:50 2015 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Fri Mar 6 15:26:50 2015 -0500

    Merge topic 'custom-command-multiple-outputs' into next
    
    d678084c Makefile: Use witness for multiple custom command outputs (#15116)


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d678084c293c0d82aeb426647aa97f1f6bd80f3e
commit d678084c293c0d82aeb426647aa97f1f6bd80f3e
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Mar 6 14:35:28 2015 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Mar 6 15:19:25 2015 -0500

    Makefile: Use witness for multiple custom command outputs (#15116)
    
    In commit v3.2.0-rc1~272^2~2 (Makefile: Fix rebuild with multiple custom
    command outputs, 2014-12-05) we changed the generated makefile pattern
    for multiple outputs from
    
      out1: depends...
              commands...
      out2: out1
    
    to
    
      out1 out2: depends...
              commands...
    
    This was based on the incorrect assumption that make tools would treat
    this as a combined output rule and run the command(s) exactly once for
    them.  It turns out that instead this new pattern is equivalent to
    
      out1: depends...
              commands...
      out2: depends...
              commands...
    
    so the commands may be run more than once.
    
    Some documents suggest using a "dedicated witness" stamp file:
    
      stamp: depends...
              rm -f stamp
              touch stamp.tmp
              commands...
              mv stamp.tmp stamp
      out1 out2: stamp
    
    However, if the commands fail the error message will refer to the stamp
    instead of any of the real outputs, which may be confusing to readers.
    Also, this approach seems to have the same behavior of the original
    approach that motiviated the above commit: multiple invocations are
    needed to bring consumers of the outputs up to date.
    
    Instead we can return to the original approach but add an explicit
    touch to each extra output rule:
    
      out1: depends...
              commands...
      out2: out1
              touch -c out2
    
    This causes make tools to recognize that all outputs have changed and
    therefore to execute any commands that consume them.

diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 950d440..6c20952 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -49,7 +49,6 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator()
   lg->SetUnixCD(false);
   lg->SetMakeCommandEscapeTargetTwice(true);
   lg->SetBorlandMakeCurlyHack(true);
-  lg->SetNoMultiOutputMultiDepRules(true);
   return lg;
 }
 
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index dfa6cc9..9213ad6 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -92,7 +92,6 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
   this->SkipAssemblySourceRules = false;
   this->MakeCommandEscapeTargetTwice = false;
   this->BorlandMakeCurlyHack = false;
-  this->NoMultiOutputMultiDepRules = false;
 }
 
 //----------------------------------------------------------------------------
@@ -600,7 +599,6 @@ const std::string &cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
   return this->HomeRelativeOutputPath;
 }
 
-
 //----------------------------------------------------------------------------
 void
 cmLocalUnixMakefileGenerator3
@@ -619,30 +617,6 @@ cmLocalUnixMakefileGenerator3
                          comment);
     return;
     }
-  std::vector<std::string> outputs(1, target);
-  this->WriteMakeRule(os, comment,
-                      outputs, depends, commands,
-                      symbolic, in_help);
-}
-
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteMakeRule(std::ostream& os,
-                const char* comment,
-                const std::vector<std::string>& outputs,
-                const std::vector<std::string>& depends,
-                const std::vector<std::string>& commands,
-                bool symbolic,
-                bool in_help)
-{
-  // Make sure there is an output.
-  if(outputs.empty())
-    {
-    cmSystemTools::Error("No outputs for WriteMakeRule! called with comment: ",
-                         comment);
-    return;
-    }
 
   std::string replace;
 
@@ -661,17 +635,7 @@ cmLocalUnixMakefileGenerator3
     }
 
   // Construct the left hand side of the rule.
-  std::string tgt;
-  {
-  const char* sep = "";
-  for (std::vector<std::string>::const_iterator i = outputs.begin();
-       i != outputs.end(); ++i)
-    {
-    tgt += sep;
-    tgt += this->Convert(*i,HOME_OUTPUT,MAKERULE);
-    sep = " ";
-    }
-  }
+  std::string tgt = this->Convert(target, HOME_OUTPUT, MAKERULE);
 
   const char* space = "";
   if(tgt.size() == 1)
@@ -697,19 +661,6 @@ cmLocalUnixMakefileGenerator3
     // No dependencies.  The commands will always run.
     os << cmMakeSafe(tgt) << space << ":\n";
     }
-  else if(this->NoMultiOutputMultiDepRules && outputs.size() >= 2)
-    {
-    // Borland make does not understand multiple dependency rules when
-    // there are multiple outputs, so write them all on one line.
-    os << cmMakeSafe(tgt) << space << ":";
-    for(std::vector<std::string>::const_iterator dep = depends.begin();
-        dep != depends.end(); ++dep)
-      {
-      replace = this->Convert(*dep, HOME_OUTPUT, MAKERULE);
-      os << " " << cmMakeSafe(replace);
-      }
-    os << "\n";
-    }
   else
     {
     // Split dependencies into multiple rule lines.  This allows for
@@ -738,8 +689,7 @@ cmLocalUnixMakefileGenerator3
   // Add the output to the local help if requested.
   if(in_help)
     {
-    this->LocalHelp.insert(this->LocalHelp.end(),
-                           outputs.begin(), outputs.end());
+    this->LocalHelp.push_back(target);
     }
 }
 
@@ -1758,8 +1708,6 @@ cmLocalUnixMakefileGenerator3
 //----------------------------------------------------------------------------
 void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
 {
-  // Nothing populates multiple output pairs anymore, but we need to
-  // honor it when working in a build tree generated by an older CMake.
   cmMakefile* mf = this->Makefile;
 
   // Get the string listing the multiple output pairs.
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 7c8e27f..4f2e4a0 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -61,13 +61,6 @@ public:
                      const std::vector<std::string>& commands,
                      bool symbolic,
                      bool in_help = false);
-  void WriteMakeRule(std::ostream& os,
-                     const char* comment,
-                     const std::vector<std::string>& outputs,
-                     const std::vector<std::string>& depends,
-                     const std::vector<std::string>& commands,
-                     bool symbolic,
-                     bool in_help = false);
 
   // write the main variables used by the makefiles
   void WriteMakeVariables(std::ostream& makefileStream);
@@ -161,9 +154,6 @@ public:
   void SetBorlandMakeCurlyHack(bool b)
     { this->BorlandMakeCurlyHack = b; }
 
-  void SetNoMultiOutputMultiDepRules(bool b)
-    { this->NoMultiOutputMultiDepRules = b; }
-
   // used in writing out Cmake files such as WriteDirectoryInformation
   static void WriteCMakeArgument(std::ostream& os, const char* s);
 
@@ -348,7 +338,6 @@ private:
   bool PassMakeflags;
   bool MakeCommandEscapeTargetTwice;
   bool BorlandMakeCurlyHack;
-  bool NoMultiOutputMultiDepRules;
   //==========================================================================
 
   std::string HomeRelativeOutputPath;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index cdda36c..e55f651 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -765,9 +765,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
     }
 
   // Write the build rule.
-  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
-                                      outputs, depends, commands, false);
-
+  this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+                      depends, commands, false);
 
   // Write the main driver rule to build everything in this target.
   this->WriteTargetDriverRule(targetFullPath, relink);
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 7ed0c10..973e0dc 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -766,8 +766,8 @@ cmMakefileTargetGenerator
     }
 
   // Write the rule.
-  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
-                                      outputs, depends, commands, false);
+  this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+                      depends, commands, false);
 
   bool do_preprocess_rules = lang_has_preprocessor &&
     this->LocalGenerator->GetCreatePreprocessedSourceRules();
@@ -988,6 +988,51 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
                                       depends, commands, true);
 }
 
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteMakeRule(
+  std::ostream& os,
+  const char* comment,
+  const std::vector<std::string>& outputs,
+  const std::vector<std::string>& depends,
+  const std::vector<std::string>& commands,
+  bool symbolic,
+  bool in_help)
+{
+  if (outputs.size() == 0)
+    {
+    return;
+    }
+
+  // We always attach the actual commands to the first output.
+  this->LocalGenerator->WriteMakeRule(os, comment, outputs[0], depends,
+                                      commands, symbolic, in_help);
+
+  // For single outputs, we are done.
+  if (outputs.size() == 1)
+    {
+    return;
+    }
+
+  // For multiple outputs, make the extra ones depend on the first one.
+  std::vector<std::string> const output_depends(1, outputs[0]);
+  for (std::vector<std::string>::const_iterator o = outputs.begin()+1;
+       o != outputs.end(); ++o)
+    {
+    // Touch the extra output so "make" knows that it was updated,
+    // but only if the output was acually created.
+    std::string const out = this->Convert(*o, cmLocalGenerator::HOME_OUTPUT,
+                                          cmLocalGenerator::SHELL);
+    std::vector<std::string> output_commands(
+      1,"@$(CMAKE_COMMAND) -E touch_nocreate " + out);
+    this->LocalGenerator->WriteMakeRule(os, 0, *o, output_depends,
+                                        output_commands, symbolic, in_help);
+
+    // At build time, remove the first output if this one does not exist
+    // so that make will rerun the real commands that create this one.
+    MultipleOutputPairsType::value_type p(*o, outputs[0]);
+    this->MultipleOutputPairs.insert(p);
+    }
+}
 
 //----------------------------------------------------------------------------
 void cmMakefileTargetGenerator::WriteTargetDependRules()
@@ -1008,6 +1053,25 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
   this->LocalGenerator->
     WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
 
+  // Store multiple output pairs in the depend info file.
+  if(!this->MultipleOutputPairs.empty())
+    {
+    *this->InfoFileStream
+      << "\n"
+      << "# Pairs of files generated by the same build rule.\n"
+      << "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
+    for(MultipleOutputPairsType::const_iterator pi =
+          this->MultipleOutputPairs.begin();
+        pi != this->MultipleOutputPairs.end(); ++pi)
+      {
+      *this->InfoFileStream
+        << "  " << this->LocalGenerator->EscapeForCMake(pi->first)
+        << " "  << this->LocalGenerator->EscapeForCMake(pi->second)
+        << "\n";
+      }
+    *this->InfoFileStream << "  )\n\n";
+    }
+
   // Store list of targets linked directly or transitively.
   {
   *this->InfoFileStream
@@ -1234,9 +1298,8 @@ void cmMakefileTargetGenerator
       symbolic = sf->GetPropertyAsBool("SYMBOLIC");
       }
     }
-  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
-                                      outputs, depends, commands,
-                                      symbolic);
+  this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+                      depends, commands, symbolic);
 
   // If the rule has changed make sure the output is rebuilt.
   if(!symbolic)
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index e31e086..f62c51d 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -222,6 +222,16 @@ protected:
   // Set of extra output files to be driven by the build.
   std::set<std::string> ExtraFiles;
 
+  typedef std::map<std::string, std::string> MultipleOutputPairsType;
+  MultipleOutputPairsType MultipleOutputPairs;
+  void WriteMakeRule(std::ostream& os,
+                     const char* comment,
+                     const std::vector<std::string>& outputs,
+                     const std::vector<std::string>& depends,
+                     const std::vector<std::string>& commands,
+                     bool symbolic,
+                     bool in_help = false);
+
   // Target name info.
   std::string TargetNameOut;
   std::string TargetNameSO;

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

Summary of changes:
 Source/cmGlobalBorlandMakefileGenerator.cxx |    1 -
 Source/cmLocalUnixMakefileGenerator3.cxx    |   56 +-------------------
 Source/cmLocalUnixMakefileGenerator3.h      |   11 ----
 Source/cmMakefileLibraryTargetGenerator.cxx |    5 +-
 Source/cmMakefileTargetGenerator.cxx        |   73 +++++++++++++++++++++++++--
 Source/cmMakefileTargetGenerator.h          |   10 ++++
 6 files changed, 82 insertions(+), 74 deletions(-)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list