execute_process: Improve stdout/stderr merging

Use the KWSys Process "MergeOutput" option to give the child process
the same pipe (or file) for both stdout and stderr.  This allows
natural merging of stdout and stderr together instead of merging
on arbitrary buffered read boundaries as before.
This commit is contained in:
Brad King 2015-05-07 14:40:38 -04:00
parent 31c218e6e1
commit f65bb82f36
11 changed files with 82 additions and 6 deletions

View File

@ -57,7 +57,8 @@ OUTPUT_VARIABLE, ERROR_VARIABLE
INPUT_FILE, OUTPUT_FILE, ERROR_FILE
The file named will be attached to the standard input of the first
process, standard output of the last process, or standard error of
all processes, respectively.
all processes, respectively. If the same file is named for both
output and error then it will be used for both.
OUTPUT_QUIET, ERROR_QUIET
The standard output or standard error results will be quietly ignored.

View File

@ -0,0 +1,5 @@
execute_process-merge-output
----------------------------
* The :command:`execute_process` command learned to support specifying
the same file for ``OUTPUT_FILE`` and ``ERROR_FILE``.

View File

@ -255,7 +255,7 @@ bool cmExecuteProcessCommand
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
// Check the output variables.
bool merge_output = (output_variable == error_variable);
bool merge_output = false;
if(!input_file.empty())
{
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str());
@ -267,8 +267,23 @@ bool cmExecuteProcessCommand
}
if(!error_file.empty())
{
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
error_file.c_str());
if (error_file == output_file)
{
merge_output = true;
}
else
{
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
error_file.c_str());
}
}
if (!output_variable.empty() && output_variable == error_variable)
{
merge_output = true;
}
if (merge_output)
{
cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
}
// Set the timeout if any.
@ -289,8 +304,7 @@ bool cmExecuteProcessCommand
while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p))
{
// Put the output in the right place.
if((p == cmsysProcess_Pipe_STDOUT && !output_quiet) ||
(p == cmsysProcess_Pipe_STDERR && !error_quiet && merge_output))
if (p == cmsysProcess_Pipe_STDOUT && !output_quiet)
{
if(output_variable.empty())
{

View File

@ -132,6 +132,7 @@ add_RunCMake_test(add_custom_command)
add_RunCMake_test(add_custom_target)
add_RunCMake_test(add_dependencies)
add_RunCMake_test(build_command)
add_RunCMake_test(execute_process)
add_RunCMake_test(export)
add_RunCMake_test(cmake_minimum_required)
add_RunCMake_test(continue)

View File

@ -0,0 +1,10 @@
^-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr$

View File

@ -0,0 +1,4 @@
foreach(i RANGE 1 5)
message(STATUS "Output on stdout")
message("Output on stderr")
endforeach()

View File

@ -0,0 +1,10 @@
^-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr$

View File

@ -0,0 +1,7 @@
execute_process(
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/MergeOutput.cmake
OUTPUT_FILE out.txt
ERROR_FILE out.txt
)
file(READ out.txt out)
message("${out}")

View File

@ -0,0 +1,10 @@
^-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr
-- Output on stdout
Output on stderr$

View File

@ -0,0 +1,6 @@
execute_process(
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/MergeOutput.cmake
OUTPUT_VARIABLE out
ERROR_VARIABLE out
)
message("${out}")

View File

@ -0,0 +1,8 @@
include(RunCMake)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(MergeOutput ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/MergeOutput.cmake)
unset(RunCMake_TEST_OUTPUT_MERGE)
run_cmake_command(MergeOutputFile ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/MergeOutputFile.cmake)
run_cmake_command(MergeOutputVars ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/MergeOutputVars.cmake)