Browse Source

ENH: Added APPEND option to ADD_CUSTOM_COMMAND to allow extra dependencies to be connected later. This is useful to create one rule and then have a macro add things to it later. This addresses bug#2151.

Brad King 19 years ago
parent
commit
2dfa2ba888

+ 35 - 0
Source/cmAddCustomCommandCommand.cxx

@@ -18,6 +18,8 @@
 
 #include "cmTarget.h"
 
+#include "cmSourceFile.h"
+
 // cmAddCustomCommandCommand
 bool cmAddCustomCommandCommand::InitialPass(
   std::vector<std::string> const& args)
@@ -37,6 +39,7 @@ bool cmAddCustomCommandCommand::InitialPass(
   const char* comment = 0;
   std::vector<std::string> depends, outputs, output;
   bool verbatim = false;
+  bool append = false;
 
   // Accumulate one command line at a time.
   cmCustomCommandLine currentLine;
@@ -96,6 +99,10 @@ bool cmAddCustomCommandCommand::InitialPass(
       {
       verbatim = true;
       }
+    else if(copy == "APPEND")
+      {
+      append = true;
+      }
     else if(copy == "TARGET")
       {
       doing = doing_target;
@@ -210,6 +217,11 @@ bool cmAddCustomCommandCommand::InitialPass(
       "Wrong syntax. A TARGET and OUTPUT can not both be specified.");
     return false;
     }
+  if(append && output.empty())
+    {
+    this->SetError("given APPEND option with no OUTPUT.");
+    return false;
+    }
 
   // Make sure the output names and locations are safe.
   if(!this->CheckOutputs(output) || !this->CheckOutputs(outputs))
@@ -217,6 +229,29 @@ bool cmAddCustomCommandCommand::InitialPass(
     return false;
     }
 
+  // Check for an append request.
+  if(append)
+    {
+    // Lookup an existing command.
+    if(cmSourceFile* sf =
+       this->Makefile->GetSourceFileWithOutput(output[0].c_str()))
+      {
+      if(cmCustomCommand* cc = sf->GetCustomCommand())
+        {
+        cc->AppendCommands(commandLines);
+        cc->AppendDepends(depends);
+        return true;
+        }
+      }
+
+    // No command for this output exists.
+    cmOStringStream e;
+    e << "given APPEND option with output \"" << output[0].c_str()
+      << "\" which is not already a custom command output.";
+    this->SetError(e.str().c_str());
+    return false;
+    }
+
   // Choose which mode of the command to use.
   bool escapeOldStyle = !verbatim;
   if(source.empty() && output.empty())

+ 10 - 2
Source/cmAddCustomCommandCommand.h

@@ -72,7 +72,7 @@ public:
       "                     [MAIN_DEPENDENCY depend]\n"
       "                     [DEPENDS [depends...]]\n"
       "                     [WORKING_DIRECTORY dir]\n"
-      "                     [COMMENT comment] [VERBATIM])\n"
+      "                     [COMMENT comment] [VERBATIM] [APPEND])\n"
       "This defines a new command that can be executed during the build "
       "process. The outputs named should be listed as source files in the "
       "target for which they are to be generated. "
@@ -104,7 +104,15 @@ public:
       "Studio 7 or later. For all other generators PRE_BUILD "
       "will be treated as PRE_LINK. "
       "If WORKING_DIRECTORY is specified the command will be executed "
-      "in the directory given.\n"
+      "in the directory given."
+      "\n"
+      "If APPEND is specified the COMMAND and DEPENDS option values "
+      "are appended to the custom command for the first output specified. "
+      "There must have already been a previous call to this command with "
+      "the same output. The COMMENT, WORKING_DIRECTORY, and MAIN_DEPENDENCY "
+      "options are currently ignored when APPEND is given, "
+      "but may be used in the future."
+      "\n"
       "If VERBATIM is given then all the arguments to the commands will be "
       "passed exactly as specified no matter the build tool used. "
       "Note that one level of escapes is still used by the CMake language "

+ 20 - 0
Source/cmCustomCommand.cxx

@@ -94,6 +94,26 @@ const char* cmCustomCommand::GetComment() const
   return this->HaveComment? this->Comment.c_str() : no_comment;
 }
 
+//----------------------------------------------------------------------------
+void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
+{
+  for(cmCustomCommandLines::const_iterator i=commandLines.begin();
+      i != commandLines.end(); ++i)
+    {
+    this->CommandLines.push_back(*i);
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
+{
+  for(std::vector<std::string>::const_iterator i=depends.begin();
+      i != depends.end(); ++i)
+    {
+    this->Depends.push_back(*i);
+    }
+}
+
 //----------------------------------------------------------------------------
 bool cmCustomCommand::GetEscapeOldStyle() const
 {

+ 6 - 0
Source/cmCustomCommand.h

@@ -53,6 +53,12 @@ public:
   /** Get the comment string for the command.  */
   const char* GetComment() const;
 
+  /** Append to the list of command lines.  */
+  void AppendCommands(const cmCustomCommandLines& commandLines);
+
+  /** Append to the list of dependencies.  */
+  void AppendDepends(const std::vector<std::string>& depends);
+
   /** Set/Get whether old-style escaping should be used.  */
   bool GetEscapeOldStyle() const;
   void SetEscapeOldStyle(bool b);

+ 3 - 1
Tests/CustomCommand/CMakeLists.txt

@@ -68,10 +68,12 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/doc1.dvi
   )
 
 ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/doc1.h
-  DEPENDS ${PROJECT_BINARY_DIR}/doc1.dvi
   COMMAND ${CMAKE_COMMAND} -E echo " Copying doc1.dvi to doc1temp.h."
   COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc1.dvi
                                    ${PROJECT_BINARY_DIR}/doc1temp.h
+  )
+ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/doc1.h APPEND
+  DEPENDS ${PROJECT_BINARY_DIR}/doc1.dvi
   COMMAND ${CMAKE_COMMAND} -E echo " Copying doc1temp.h to doc1.h."
   COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc1temp.h
                                    ${PROJECT_BINARY_DIR}/doc1.h