execute_process: Add option to echo command lines

Add COMMAND_ECHO option to the execute_process command. This will allow
execute_process to show the command it will run. Also add a cmake variable
CMAKE_EXECUTE_PROCESS_COMMAND_ECHO. Both the option and the variable can
be set to one of the following: STDERR|STDOUT|NONE. The command will be
printed to stderr or stdout or not at all.

Fixes: #18933
This commit is contained in:
Bill Hoffman
2019-03-29 16:39:44 -04:00
committed by Brad King
parent d350fb6889
commit 044dcf9f8d
15 changed files with 155 additions and 1 deletions

View File

@@ -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.

View File

@@ -158,6 +158,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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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,7 +121,6 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
return false; return false;
} }
} }
// Create a process instance. // Create a process instance.
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr( std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
cmsysProcess_New(), cmsysProcess_Delete); cmsysProcess_New(), cmsysProcess_Delete);
@@ -171,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);

View File

@@ -0,0 +1 @@
1

View File

@@ -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$

View File

@@ -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$

View File

@@ -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()

View File

@@ -0,0 +1 @@
1

View File

@@ -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.$

View File

@@ -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$

View File

@@ -0,0 +1 @@
1

View File

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

View File

@@ -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)