فهرست منبع

Merge topic 'add-execute_process-command-echo'

044dcf9f8d execute_process: Add option to echo command lines
d350fb6889 execute_process: Manage KWSys Process lifetime with unique_ptr

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3165
Brad King 6 سال پیش
والد
کامیت
60b28de5c8

+ 5 - 0
Help/command/execute_process.rst

@@ -18,6 +18,7 @@ Execute one or more child processes.
                   [ERROR_FILE <file>]
                   [ERROR_FILE <file>]
                   [OUTPUT_QUIET]
                   [OUTPUT_QUIET]
                   [ERROR_QUIET]
                   [ERROR_QUIET]
+                  [COMMAND_ECHO <where>]
                   [OUTPUT_STRIP_TRAILING_WHITESPACE]
                   [OUTPUT_STRIP_TRAILING_WHITESPACE]
                   [ERROR_STRIP_TRAILING_WHITESPACE]
                   [ERROR_STRIP_TRAILING_WHITESPACE]
                   [ENCODING <name>])
                   [ENCODING <name>])
@@ -77,6 +78,10 @@ Options:
 ``OUTPUT_QUIET``, ``ERROR_QUIET``
 ``OUTPUT_QUIET``, ``ERROR_QUIET``
  The standard output or standard error results will be quietly ignored.
  The standard output or standard error results will be quietly ignored.
 
 
+``COMMAND_ECHO <where>``
+ The command being run will be echo'ed to ``<where>`` with ``<where>``
+ being set to ``STDERR``|``STDOUT``|``NONE``.
+
 ``ENCODING <name>``
 ``ENCODING <name>``
  On Windows, the encoding that is used to decode output from the process.
  On Windows, the encoding that is used to decode output from the process.
  Ignored on other platforms.
  Ignored on other platforms.

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -159,6 +159,7 @@ Variables that Change Behavior
    /variable/CMAKE_ECLIPSE_VERSION
    /variable/CMAKE_ECLIPSE_VERSION
    /variable/CMAKE_ERROR_DEPRECATED
    /variable/CMAKE_ERROR_DEPRECATED
    /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
    /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
+   /variable/CMAKE_EXECUTE_PROCESS_COMMAND_ECHO
    /variable/CMAKE_EXPORT_COMPILE_COMMANDS
    /variable/CMAKE_EXPORT_COMPILE_COMMANDS
    /variable/CMAKE_EXPORT_PACKAGE_REGISTRY
    /variable/CMAKE_EXPORT_PACKAGE_REGISTRY
    /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY
    /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY

+ 6 - 0
Help/release/dev/add-execute_process-command-echo.rst

@@ -0,0 +1,6 @@
+add-execute_process-command-echo
+--------------------------------
+
+* The :command:`execute_process` command gained a `COMMAND_ECHO` option
+  and supporting :variable:`CMAKE_EXECUTE_PROCESS_COMMAND_ECHO` variable
+  to enable echoing of the command-line string before execution.

+ 6 - 0
Help/variable/CMAKE_EXECUTE_PROCESS_COMMAND_ECHO.rst

@@ -0,0 +1,6 @@
+CMAKE_EXECUTE_PROCESS_COMMAND_ECHO
+----------------------------------
+
+If this variable is set to ``STDERR``|``STDOUT``|``NONE`` then commands in
+:command:`execute_process` calls will be printed to either stderr or stdout
+or not at all.

+ 52 - 5
Source/cmExecuteProcessCommand.cxx

@@ -6,11 +6,13 @@
 #include "cmsys/Process.h"
 #include "cmsys/Process.h"
 #include <algorithm>
 #include <algorithm>
 #include <ctype.h> /* isspace */
 #include <ctype.h> /* isspace */
+#include <iostream>
 #include <stdio.h>
 #include <stdio.h>
 
 
 #include "cmAlgorithms.h"
 #include "cmAlgorithms.h"
 #include "cmArgumentParser.h"
 #include "cmArgumentParser.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
+#include "cmMessageType.h"
 #include "cmProcessOutput.h"
 #include "cmProcessOutput.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 
 
@@ -47,6 +49,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
     std::string OutputFile;
     std::string OutputFile;
     std::string ErrorFile;
     std::string ErrorFile;
     std::string Timeout;
     std::string Timeout;
+    std::string CommandEcho;
     bool OutputQuiet = false;
     bool OutputQuiet = false;
     bool ErrorQuiet = false;
     bool ErrorQuiet = false;
     bool OutputStripTrailingWhitespace = false;
     bool OutputStripTrailingWhitespace = false;
@@ -57,6 +60,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
   static auto const parser =
   static auto const parser =
     cmArgumentParser<Arguments>{}
     cmArgumentParser<Arguments>{}
       .Bind("COMMAND"_s, &Arguments::Commands)
       .Bind("COMMAND"_s, &Arguments::Commands)
+      .Bind("COMMAND_ECHO"_s, &Arguments::CommandEcho)
       .Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
       .Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
       .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable)
       .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable)
       .Bind("RESULT_VARIABLE"_s, &Arguments::ResultVariable)
       .Bind("RESULT_VARIABLE"_s, &Arguments::ResultVariable)
@@ -117,9 +121,10 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
       return false;
       return false;
     }
     }
   }
   }
-
   // Create a process instance.
   // Create a process instance.
-  cmsysProcess* cp = cmsysProcess_New();
+  std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
+    cmsysProcess_New(), cmsysProcess_Delete);
+  cmsysProcess* cp = cp_ptr.get();
 
 
   // Set the command sequence.
   // Set the command sequence.
   for (std::vector<std::string> const& cmd : arguments.Commands) {
   for (std::vector<std::string> const& cmd : arguments.Commands) {
@@ -169,6 +174,51 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
     cmsysProcess_SetTimeout(cp, timeout);
     cmsysProcess_SetTimeout(cp, timeout);
   }
   }
 
 
+  bool echo_stdout = false;
+  bool echo_stderr = false;
+  bool echo_output_from_variable = true;
+  std::string echo_output =
+    this->Makefile->GetSafeDefinition("CMAKE_EXECUTE_PROCESS_COMMAND_ECHO");
+  if (!arguments.CommandEcho.empty()) {
+    echo_output_from_variable = false;
+    echo_output = arguments.CommandEcho;
+  }
+
+  if (!echo_output.empty()) {
+    if (echo_output == "STDERR") {
+      echo_stderr = true;
+    } else if (echo_output == "STDOUT") {
+      echo_stdout = true;
+    } else if (echo_output != "NONE") {
+      std::string error;
+      if (echo_output_from_variable) {
+        error = "CMAKE_EXECUTE_PROCESS_COMMAND_ECHO set to '";
+      } else {
+        error = " called with '";
+      }
+      error += echo_output;
+      error += "' expected STDERR|STDOUT|NONE";
+      if (!echo_output_from_variable) {
+        error += " for COMMAND_ECHO.";
+      }
+      this->Makefile->IssueMessage(MessageType::FATAL_ERROR, error);
+      return true;
+    }
+  }
+  if (echo_stdout || echo_stderr) {
+    std::string command;
+    for (auto& cmd : arguments.Commands) {
+      command += "'";
+      command += cmJoin(cmd, "' '");
+      command += "'";
+      command += "\n";
+    }
+    if (echo_stdout) {
+      std::cout << command;
+    } else if (echo_stderr) {
+      std::cerr << command;
+    }
+  }
   // Start the process.
   // Start the process.
   cmsysProcess_Execute(cp);
   cmsysProcess_Execute(cp);
 
 
@@ -297,9 +347,6 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
     }
     }
   }
   }
 
 
-  // Delete the process instance.
-  cmsysProcess_Delete(cp);
-
   return true;
   return true;
 }
 }
 
 

+ 1 - 0
Tests/RunCMake/execute_process/EchoCommand-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/execute_process/EchoCommand-stderr.txt

@@ -0,0 +1,5 @@
+.*cmake.*-E' 'echo' '--   2 COMMAND_ECHO STDERR'
+.*cmake.*-E' 'echo' '--   4 COMMAND_ECHO STDERR'
+.*cmake.*-E' 'echo' '--   8 COMMAND_ECHO STDOUT COMMAND_ECHO STDERR'
+CMake Error at .*EchoCommand.cmake:.* \(execute_process\):
+   CMAKE_EXECUTE_PROCESS_COMMAND_ECHO set to 'BAD' expected STDERR|STDOUT|NONE$

+ 12 - 0
Tests/RunCMake/execute_process/EchoCommand-stdout.txt

@@ -0,0 +1,12 @@
+.*cmake.*-E' 'echo' '--   1 COMMAND_ECHO STDOUT'
+--   1 COMMAND_ECHO STDOUT
+--   2 COMMAND_ECHO STDERR
+.*cmake.* '-E' 'echo' '--   3 COMMAND_ECHO STDOUT'
+--   3 COMMAND_ECHO STDOUT
+--   4 COMMAND_ECHO STDERR
+.*cmake.* '-E' 'echo' '--   5 COMMAND_ECHO STDOUT'
+--   5 COMMAND_ECHO STDOUT
+--   6 COMMAND_ECHO NONE
+.*cmake.* '-E' 'echo' '--   7 COMMAND_ECHO STDERR COMMAND_ECHO STDOUT'
+--   7 COMMAND_ECHO STDERR COMMAND_ECHO STDOUT
+--   8 COMMAND_ECHO STDOUT COMMAND_ECHO STDERR$

+ 41 - 0
Tests/RunCMake/execute_process/EchoCommand.cmake

@@ -0,0 +1,41 @@
+if(CHECK_ERROR_OUTPUT_LOCATION)
+  execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+    "--   1 COMMAND_ECHO " COMMAND_ECHO  )
+endif()
+# test COMMAND_ECHO STDOUT
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   1 COMMAND_ECHO STDOUT" COMMAND_ECHO STDOUT )
+# test COMMAND_ECHO STDERR
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   2 COMMAND_ECHO STDERR" COMMAND_ECHO STDERR )
+# test CMAKE_EXECUTE_PROCESS_COMMAND_ECHO STDOUT
+set(CMAKE_EXECUTE_PROCESS_COMMAND_ECHO STDOUT)
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   3 COMMAND_ECHO STDOUT" )
+# test CMAKE_EXECUTE_PROCESS_COMMAND_ECHO STDERR
+set(CMAKE_EXECUTE_PROCESS_COMMAND_ECHO STDERR)
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   4 COMMAND_ECHO STDERR" )
+# make sure local will override global settings
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   5 COMMAND_ECHO STDOUT" COMMAND_ECHO STDOUT )
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   6 COMMAND_ECHO NONE" COMMAND_ECHO NONE)
+# test both and make sure override works
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   7 COMMAND_ECHO STDERR COMMAND_ECHO STDOUT" COMMAND_ECHO STDERR
+  COMMAND_ECHO STDOUT)
+execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+  "--   8 COMMAND_ECHO STDOUT COMMAND_ECHO STDERR" COMMAND_ECHO STDOUT
+  COMMAND_ECHO STDERR)
+
+# check for bad arguments to global and local
+if(CHECK_GLOBAL)
+  # make sure a non STDERR or STDOUT value is an error
+  set(CMAKE_EXECUTE_PROCESS_COMMAND_ECHO BAD)
+  execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+    "--   9 - 1 CMAKE_EXECUTE_PROCESS_COMMAND_ECHO BAD" )
+else()
+  execute_process(COMMAND ${CMAKE_COMMAND} -E echo
+    "--   9 - 2 COMMAND_ECHO BAD" COMMAND_ECHO BAD)
+endif()

+ 1 - 0
Tests/RunCMake/execute_process/EchoCommand2-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/execute_process/EchoCommand2-stderr.txt

@@ -0,0 +1,5 @@
+.*cmake.*-E' 'echo' '--   2 COMMAND_ECHO STDERR'
+.*cmake.*-E' 'echo' '--   4 COMMAND_ECHO STDERR'
+.*cmake.*-E' 'echo' '--   8 COMMAND_ECHO STDOUT COMMAND_ECHO STDERR'
+CMake Error at .*EchoCommand.cmake:.* \(execute_process\):
+    called with 'BAD' expected STDERR|STDOUT|NONE for COMMAND_ECHO.$

+ 12 - 0
Tests/RunCMake/execute_process/EchoCommand2-stdout.txt

@@ -0,0 +1,12 @@
+.*cmake.*-E' 'echo' '--   1 COMMAND_ECHO STDOUT'
+--   1 COMMAND_ECHO STDOUT
+--   2 COMMAND_ECHO STDERR
+.*cmake.* '-E' 'echo' '--   3 COMMAND_ECHO STDOUT'
+--   3 COMMAND_ECHO STDOUT
+--   4 COMMAND_ECHO STDERR
+.*cmake.* '-E' 'echo' '--   5 COMMAND_ECHO STDOUT'
+--   5 COMMAND_ECHO STDOUT
+--   6 COMMAND_ECHO NONE
+.*cmake.* '-E' 'echo' '--   7 COMMAND_ECHO STDERR COMMAND_ECHO STDOUT'
+--   7 COMMAND_ECHO STDERR COMMAND_ECHO STDOUT
+--   8 COMMAND_ECHO STDOUT COMMAND_ECHO STDERR$

+ 1 - 0
Tests/RunCMake/execute_process/EchoCommand3-result.txt

@@ -0,0 +1 @@
+1

+ 2 - 0
Tests/RunCMake/execute_process/EchoCommand3-stderr.txt

@@ -0,0 +1,2 @@
+CMake Error at .*EchoCommand.cmake:.*\(execute_process\):
+  execute_process called with no value for COMMAND_ECHO.

+ 8 - 0
Tests/RunCMake/execute_process/RunCMakeTest.cmake

@@ -16,3 +16,11 @@ endif()
 if(EXIT_CODE_EXE)
 if(EXIT_CODE_EXE)
   run_cmake_command(ExitValues ${CMAKE_COMMAND} -DEXIT_CODE_EXE=${EXIT_CODE_EXE} -P ${RunCMake_SOURCE_DIR}/ExitValues.cmake)
   run_cmake_command(ExitValues ${CMAKE_COMMAND} -DEXIT_CODE_EXE=${EXIT_CODE_EXE} -P ${RunCMake_SOURCE_DIR}/ExitValues.cmake)
 endif()
 endif()
+
+run_cmake_command(EchoCommand ${CMAKE_COMMAND} -DCHECK_GLOBAL=TRUE
+  -P ${RunCMake_SOURCE_DIR}/EchoCommand.cmake)
+run_cmake_command(EchoCommand2 ${CMAKE_COMMAND} -P
+  ${RunCMake_SOURCE_DIR}/EchoCommand.cmake)
+run_cmake_command(EchoCommand3 ${CMAKE_COMMAND}
+  -DCHECK_ERROR_OUTPUT_LOCATION=TRUE -P
+  ${RunCMake_SOURCE_DIR}/EchoCommand.cmake)