mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-22 06:59:01 -06:00
Merge topic 'execute_process-fatal-error'
116a427eb1 execute_process: add options for fatal errors on subprocess failure
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5243
This commit is contained in:
@@ -23,7 +23,8 @@ Execute one or more child processes.
|
||||
[ERROR_STRIP_TRAILING_WHITESPACE]
|
||||
[ENCODING <name>]
|
||||
[ECHO_OUTPUT_VARIABLE]
|
||||
[ECHO_ERROR_VARIABLE])
|
||||
[ECHO_ERROR_VARIABLE]
|
||||
[COMMAND_ERROR_IS_FATAL <ANY|LAST>])
|
||||
|
||||
Runs the given sequence of one or more commands.
|
||||
|
||||
@@ -116,6 +117,11 @@ Options:
|
||||
|
||||
This is analogous to the ``tee`` Unix command.
|
||||
|
||||
``COMMAND_ERROR_IS_FATAL <ANY|LAST>``
|
||||
``COMMAND_ERROR_IS_FATAL ANY`` option stops processing if any command fails.
|
||||
``COMMAND_ERROR_IS_FATAL LAST`` option stops processing if the last command
|
||||
in the command list fails.
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
execute-process-command-error-is-fatal
|
||||
--------------------------------------
|
||||
|
||||
* The :command:`execute_process` command gained a ``COMMAND_ERROR_IS_FATAL``
|
||||
option to specify a fatal error.
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
@@ -63,6 +65,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
bool EchoOutputVariable = false;
|
||||
bool EchoErrorVariable = false;
|
||||
std::string Encoding;
|
||||
std::string CommandErrorIsFatal;
|
||||
};
|
||||
|
||||
static auto const parser =
|
||||
@@ -86,7 +89,8 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
&Arguments::ErrorStripTrailingWhitespace)
|
||||
.Bind("ENCODING"_s, &Arguments::Encoding)
|
||||
.Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable)
|
||||
.Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable);
|
||||
.Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable)
|
||||
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
|
||||
|
||||
std::vector<std::string> unparsedArguments;
|
||||
std::vector<std::string> keywordsMissingValue;
|
||||
@@ -131,6 +135,14 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arguments.CommandErrorIsFatal.empty()) {
|
||||
if (arguments.CommandErrorIsFatal != "ANY"_s &&
|
||||
arguments.CommandErrorIsFatal != "LAST"_s) {
|
||||
status.SetError("COMMAND_ERROR_IS_FATAL option can be ANY or LAST");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Create a process instance.
|
||||
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
|
||||
cmsysProcess_New(), cmsysProcess_Delete);
|
||||
@@ -363,6 +375,50 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.CommandErrorIsFatal == "ANY"_s) {
|
||||
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
|
||||
std::vector<int> failedIndexes;
|
||||
for (int i = 0; i < static_cast<int>(arguments.Commands.size()); ++i) {
|
||||
if (cmsysProcess_GetStateByIndex(cp, i) ==
|
||||
kwsysProcess_StateByIndex_Exited) {
|
||||
int exitCode = cmsysProcess_GetExitValueByIndex(cp, i);
|
||||
if (exitCode) {
|
||||
failedIndexes.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!failedIndexes.empty()) {
|
||||
std::ostringstream oss;
|
||||
oss << "failed command indexes: ";
|
||||
for (auto i = 0u; i < failedIndexes.size(); i++) {
|
||||
if (i == failedIndexes.size() - 1) {
|
||||
oss << failedIndexes[i] + 1;
|
||||
} else {
|
||||
oss << failedIndexes[i] + 1 << ", ";
|
||||
}
|
||||
}
|
||||
status.SetError(oss.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.CommandErrorIsFatal == "LAST"_s) {
|
||||
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
|
||||
int lastIndex = static_cast<int>(arguments.Commands.size() - 1);
|
||||
if (cmsysProcess_GetStateByIndex(cp, lastIndex) ==
|
||||
kwsysProcess_StateByIndex_Exited) {
|
||||
int exitCode = cmsysProcess_GetExitValueByIndex(cp, lastIndex);
|
||||
if (exitCode) {
|
||||
status.SetError("last command failed");
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*AnyCommandError.cmake:1 \(execute_process\):
|
||||
execute_process failed command indexes: 2, 3, 4
|
||||
8
Tests/RunCMake/execute_process/AnyCommandError.cmake
Normal file
8
Tests/RunCMake/execute_process/AnyCommandError.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
1
Tests/RunCMake/execute_process/CommandError-result.txt
Normal file
1
Tests/RunCMake/execute_process/CommandError-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
2
Tests/RunCMake/execute_process/CommandError-stderr.txt
Normal file
2
Tests/RunCMake/execute_process/CommandError-stderr.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*CommandError.cmake:1 \(execute_process\):
|
||||
execute_process COMMAND_ERROR_IS_FATAL option can be ANY or LAST
|
||||
3
Tests/RunCMake/execute_process/CommandError.cmake
Normal file
3
Tests/RunCMake/execute_process/CommandError.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND_ERROR_IS_FATAL ALL
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at .*LastCommandError.cmake:1 \(execute_process\):
|
||||
execute_process last command failed
|
||||
8
Tests/RunCMake/execute_process/LastCommandError.cmake
Normal file
8
Tests/RunCMake/execute_process/LastCommandError.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND ${CMAKE_COMMAND} -E true
|
||||
COMMAND ${CMAKE_COMMAND} -E false
|
||||
COMMAND_ERROR_IS_FATAL LAST
|
||||
)
|
||||
@@ -26,3 +26,7 @@ run_cmake_command(EchoCommand3 ${CMAKE_COMMAND}
|
||||
${RunCMake_SOURCE_DIR}/EchoCommand.cmake)
|
||||
|
||||
run_cmake_command(EchoVariable ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/EchoVariable.cmake)
|
||||
|
||||
run_cmake_command(AnyCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/AnyCommandError.cmake)
|
||||
run_cmake_command(LastCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandError.cmake)
|
||||
run_cmake_command(CommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/CommandError.cmake)
|
||||
|
||||
Reference in New Issue
Block a user