execute_process: Add options for modified environment

This commit is contained in:
Daniel Pfeifer
2026-03-05 08:48:42 +01:00
parent bfe5392276
commit d7ab03d093
11 changed files with 76 additions and 0 deletions

View File

@@ -22,6 +22,8 @@ Execute one or more child processes.
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE]
[ENCODING <name>]
[ENVIRONMENT <variable=value>...]
[ENVIRONMENT_MODIFICATION <env-mod-op>...]
[ECHO_OUTPUT_VARIABLE]
[ECHO_ERROR_VARIABLE]
[COMMAND_ERROR_IS_FATAL <ANY|LAST|NONE>])
@@ -187,6 +189,27 @@ Options:
`UTF-8 RFC <https://datatracker.ietf.org/doc/html/rfc3629>`_
naming convention.
``ENVIRONMENT <variable=value>...``
.. versionadded:: 4.4
Add environment variable definitions to the environment of the child
processes. Each entry must be of the form ``NAME=value`` and is interpreted
as setting ``NAME`` to ``value`` for the duration of the
``execute_process()`` call.
These entries are processed in order. If the same variable name is given
multiple times, the last value wins.
``ENVIRONMENT_MODIFICATION <env-mod-op>...``
.. versionadded:: 4.4
Apply one or more :prop_test:`ENVIRONMENT_MODIFICATION` operations to the
environment of the child processes. Each operation is applied in the given
order, and failures to parse an operation are treated as errors.
Environment modifications are applied after ``ENVIRONMENT`` entries, if both
options are specified.
``COMMAND_ERROR_IS_FATAL <ANY|LAST|NONE>``
.. versionadded:: 3.19

View File

@@ -0,0 +1,6 @@
execute_process-environment
---------------------------
* The :command:`execute_process` command learned the
``ENVIRONMENT`` and ``ENVIRONMENT_MODIFICATION`` options to run child
processes with a modified environment.

View File

@@ -27,6 +27,8 @@
#include "cmsys/String.h"
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmEnvironment.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
@@ -94,6 +96,8 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
bool EchoOutputVariable = false;
bool EchoErrorVariable = false;
cm::optional<std::string> Encoding;
ArgumentParser::MaybeEmpty<std::vector<std::string>> Environment;
ArgumentParser::MaybeEmpty<std::vector<std::string>> EnvModification;
std::string CommandErrorIsFatal;
};
@@ -117,6 +121,8 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
.Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s,
&Arguments::ErrorStripTrailingWhitespace)
.Bind("ENCODING"_s, &Arguments::Encoding)
.Bind("ENVIRONMENT"_s, &Arguments::Environment)
.Bind("ENVIRONMENT_MODIFICATION"_s, &Arguments::EnvModification)
.Bind("ECHO_OUTPUT_VARIABLE"_s, &Arguments::EchoOutputVariable)
.Bind("ECHO_ERROR_VARIABLE"_s, &Arguments::EchoErrorVariable)
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
@@ -213,6 +219,23 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
builder.SetWorkingDirectory(arguments.WorkingDirectory);
}
if (!arguments.Environment.empty() || !arguments.EnvModification.empty()) {
#ifndef CMAKE_BOOTSTRAP
auto diff = cmEnvironmentModification{};
if (!diff.Add(arguments.EnvModification)) {
return false;
}
auto env = cmEnvironment{ cmSystemTools::GetEnvironmentVariables() };
env.Update(arguments.Environment);
diff.ApplyTo(env);
builder.SetEnvironment(env.GetVariables());
#else
status.SetError(
"does not support environment modification in bootstrap builds");
return false;
#endif
}
// Check the output variables.
std::unique_ptr<FILE, int (*)(FILE*)> inputFile(nullptr, fclose);
if (!inputFilename.empty()) {

View File

@@ -0,0 +1 @@
CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value

View File

@@ -0,0 +1,5 @@
execute_process(
COMMAND ${CMAKE_COMMAND} -E environment
ENVIRONMENT
"CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value"
)

View File

@@ -0,0 +1 @@
CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=kaesekuchen

View File

@@ -0,0 +1,6 @@
set(ENV{CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT} "kaese")
execute_process(
COMMAND ${CMAKE_COMMAND} -E environment
ENVIRONMENT_MODIFICATION
"CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=string_append:kuchen"
)

View File

@@ -0,0 +1 @@
CMake Error: Error: Unrecognized environment manipulation argument: invalid

View File

@@ -0,0 +1,5 @@
execute_process(
COMMAND ${CMAKE_COMMAND} -E environment
ENVIRONMENT_MODIFICATION
"CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=invalid:value"
)

View File

@@ -19,6 +19,10 @@ if(TEST_ENCODING_EXE)
run_cmake_script(EncodingUTF8 -DTEST_ENCODING_EXE=${TEST_ENCODING_EXE})
endif()
run_cmake(Environment)
run_cmake(EnvironmentModification)
run_cmake(EnvironmentModificationError)
if(EXIT_CODE_EXE)
run_cmake_command(ExitValues ${CMAKE_COMMAND} -DEXIT_CODE_EXE=${EXIT_CODE_EXE} -P ${RunCMake_SOURCE_DIR}/ExitValues.cmake)
endif()