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>]
[OUTPUT_QUIET]
[ERROR_QUIET]
[COMMAND_ECHO <where>]
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE]
[ENCODING <name>])
@@ -77,6 +78,10 @@ Options:
``OUTPUT_QUIET``, ``ERROR_QUIET``
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>``
On Windows, the encoding that is used to decode output from the process.
Ignored on other platforms.

View File

@@ -158,6 +158,7 @@ Variables that Change Behavior
/variable/CMAKE_ECLIPSE_VERSION
/variable/CMAKE_ERROR_DEPRECATED
/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
/variable/CMAKE_EXECUTE_PROCESS_COMMAND_ECHO
/variable/CMAKE_EXPORT_COMPILE_COMMANDS
/variable/CMAKE_EXPORT_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 <algorithm>
#include <ctype.h> /* isspace */
#include <iostream>
#include <stdio.h>
#include "cmAlgorithms.h"
#include "cmArgumentParser.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmProcessOutput.h"
#include "cmSystemTools.h"
@@ -47,6 +49,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
std::string OutputFile;
std::string ErrorFile;
std::string Timeout;
std::string CommandEcho;
bool OutputQuiet = false;
bool ErrorQuiet = false;
bool OutputStripTrailingWhitespace = false;
@@ -57,6 +60,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
static auto const parser =
cmArgumentParser<Arguments>{}
.Bind("COMMAND"_s, &Arguments::Commands)
.Bind("COMMAND_ECHO"_s, &Arguments::CommandEcho)
.Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
.Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable)
.Bind("RESULT_VARIABLE"_s, &Arguments::ResultVariable)
@@ -117,7 +121,6 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
}
// Create a process instance.
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
cmsysProcess_New(), cmsysProcess_Delete);
@@ -171,6 +174,51 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
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.
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)
run_cmake_command(ExitValues ${CMAKE_COMMAND} -DEXIT_CODE_EXE=${EXIT_CODE_EXE} -P ${RunCMake_SOURCE_DIR}/ExitValues.cmake)
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)