diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 14f879d03f..b32025fd4b 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -21,7 +21,9 @@ Execute one or more child processes. [COMMAND_ECHO ] [OUTPUT_STRIP_TRAILING_WHITESPACE] [ERROR_STRIP_TRAILING_WHITESPACE] - [ENCODING ]) + [ENCODING ] + [ECHO_OUTPUT_VARIABLE] + [ECHO_ERROR_VARIABLE]) Runs the given sequence of one or more commands. @@ -105,6 +107,15 @@ Options: for this encoding. In CMake 3.11.0, ``UTF-8`` was added for consistency with the `UTF-8 RFC `_ naming convention. +``ECHO_OUTPUT_VARIABLE``, ``ECHO_ERROR_VARIABLE`` + The standard output or standard error will not be exclusively redirected to + the configured variables. + + The output will be duplicated, it will be sent into the configured variables + and also on standard output or standard error. + + This is analogous to the ``tee`` Unix command. + If more than one ``OUTPUT_*`` or ``ERROR_*`` option is given for the same pipe the precedence is not specified. If no ``OUTPUT_*`` or ``ERROR_*`` options are given the output will diff --git a/Help/release/dev/execute_process.rst b/Help/release/dev/execute_process.rst new file mode 100644 index 0000000000..02e813b7e5 --- /dev/null +++ b/Help/release/dev/execute_process.rst @@ -0,0 +1,5 @@ +execute_process +--------------- + +* The :command:`execute_process` command gained the ``ECHO_OUTPUT_VARIABLE`` + and ``ECHO_ERROR_VARIABLE`` options. diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 5be5bcecfa..08a0f7e646 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -61,6 +61,8 @@ bool cmExecuteProcessCommand(std::vector const& args, bool ErrorQuiet = false; bool OutputStripTrailingWhitespace = false; bool ErrorStripTrailingWhitespace = false; + bool EchoOutputVariable = false; + bool EchoErrorVariable = false; std::string Encoding; }; @@ -83,7 +85,9 @@ bool cmExecuteProcessCommand(std::vector const& args, &Arguments::OutputStripTrailingWhitespace) .Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s, &Arguments::ErrorStripTrailingWhitespace) - .Bind("ENCODING"_s, &Arguments::Encoding); + .Bind("ENCODING"_s, &Arguments::Encoding) + .Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable) + .Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable); std::vector unparsedArguments; std::vector keywordsMissingValue; @@ -241,28 +245,32 @@ bool cmExecuteProcessCommand(std::vector const& args, while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !arguments.OutputQuiet) { - if (arguments.OutputVariable.empty()) { + if (arguments.OutputVariable.empty() || arguments.EchoOutputVariable) { processOutput.DecodeText(data, length, strdata, 1); cmSystemTools::Stdout(strdata); - } else { + } + if (!arguments.OutputVariable.empty()) { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !arguments.ErrorQuiet) { - if (arguments.ErrorVariable.empty()) { + if (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable) { processOutput.DecodeText(data, length, strdata, 2); cmSystemTools::Stderr(strdata); - } else { + } + if (!arguments.ErrorVariable.empty()) { cmExecuteProcessCommandAppend(tempError, data, length); } } } - if (!arguments.OutputQuiet && arguments.OutputVariable.empty()) { + if (!arguments.OutputQuiet && + (arguments.OutputVariable.empty() || arguments.EchoOutputVariable)) { processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { cmSystemTools::Stdout(strdata); } } - if (!arguments.ErrorQuiet && arguments.ErrorVariable.empty()) { + if (!arguments.ErrorQuiet && + (arguments.ErrorVariable.empty() || arguments.EchoErrorVariable)) { processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { cmSystemTools::Stderr(strdata); diff --git a/Tests/RunCMake/execute_process/EchoVariable-stderr.txt b/Tests/RunCMake/execute_process/EchoVariable-stderr.txt new file mode 100644 index 0000000000..d92755345f --- /dev/null +++ b/Tests/RunCMake/execute_process/EchoVariable-stderr.txt @@ -0,0 +1,3 @@ +CMake Error at [^ +]*EchoVariableOutput.cmake:2 \(message\): + Text to stderr diff --git a/Tests/RunCMake/execute_process/EchoVariable-stdout.txt b/Tests/RunCMake/execute_process/EchoVariable-stdout.txt new file mode 100644 index 0000000000..7c868bd079 --- /dev/null +++ b/Tests/RunCMake/execute_process/EchoVariable-stdout.txt @@ -0,0 +1 @@ +-- Text to stdout diff --git a/Tests/RunCMake/execute_process/EchoVariable.cmake b/Tests/RunCMake/execute_process/EchoVariable.cmake new file mode 100644 index 0000000000..99999c7486 --- /dev/null +++ b/Tests/RunCMake/execute_process/EchoVariable.cmake @@ -0,0 +1,23 @@ +execute_process( + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/EchoVariableOutput.cmake + OUTPUT_VARIABLE stdout + ERROR_QUIET + ECHO_OUTPUT_VARIABLE +) + +file(READ ${CMAKE_CURRENT_LIST_DIR}/EchoVariable-stdout.txt expected_stdout) +if (NOT stdout MATCHES "${expected_stdout}") + message(FATAL_ERROR "stdout differs from the expected stdout") +endif() + +execute_process( + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/EchoVariableOutput.cmake + ERROR_VARIABLE stderr + OUTPUT_QUIET + ECHO_ERROR_VARIABLE +) + +file(READ ${CMAKE_CURRENT_LIST_DIR}/EchoVariable-stderr.txt expected_stderr) +if (NOT stderr MATCHES "${expected_stderr}") + message(FATAL_ERROR "stderr differs from the expected stderr") +endif() diff --git a/Tests/RunCMake/execute_process/EchoVariableOutput.cmake b/Tests/RunCMake/execute_process/EchoVariableOutput.cmake new file mode 100644 index 0000000000..e636567484 --- /dev/null +++ b/Tests/RunCMake/execute_process/EchoVariableOutput.cmake @@ -0,0 +1,2 @@ +message(STATUS "Text to stdout") +message(FATAL_ERROR "Text to stderr") diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake index b203aabfde..89ad6b2078 100644 --- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake +++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake @@ -24,3 +24,5 @@ run_cmake_command(EchoCommand2 ${CMAKE_COMMAND} -P run_cmake_command(EchoCommand3 ${CMAKE_COMMAND} -DCHECK_ERROR_OUTPUT_LOCATION=TRUE -P ${RunCMake_SOURCE_DIR}/EchoCommand.cmake) + +run_cmake_command(EchoVariable ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/EchoVariable.cmake)