From d7ab03d09312e0214d1dd143fbe778b28ca5a85f Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Thu, 5 Mar 2026 08:48:42 +0100 Subject: [PATCH] execute_process: Add options for modified environment --- Help/command/execute_process.rst | 23 +++++++++++++++++++ .../dev/execute_process-environment.rst | 6 +++++ Source/cmExecuteProcessCommand.cxx | 23 +++++++++++++++++++ .../execute_process/Environment-stdout.txt | 1 + .../execute_process/Environment.cmake | 5 ++++ .../EnvironmentModification-stdout.txt | 1 + .../EnvironmentModification.cmake | 6 +++++ .../EnvironmentModificationError-result.txt | 1 + .../EnvironmentModificationError-stderr.txt | 1 + .../EnvironmentModificationError.cmake | 5 ++++ .../execute_process/RunCMakeTest.cmake | 4 ++++ 11 files changed, 76 insertions(+) create mode 100644 Help/release/dev/execute_process-environment.rst create mode 100644 Tests/RunCMake/execute_process/Environment-stdout.txt create mode 100644 Tests/RunCMake/execute_process/Environment.cmake create mode 100644 Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt create mode 100644 Tests/RunCMake/execute_process/EnvironmentModification.cmake create mode 100644 Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt create mode 100644 Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt create mode 100644 Tests/RunCMake/execute_process/EnvironmentModificationError.cmake diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 37f2b42c2b..429be729d9 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -22,6 +22,8 @@ Execute one or more child processes. [OUTPUT_STRIP_TRAILING_WHITESPACE] [ERROR_STRIP_TRAILING_WHITESPACE] [ENCODING ] + [ENVIRONMENT ...] + [ENVIRONMENT_MODIFICATION ...] [ECHO_OUTPUT_VARIABLE] [ECHO_ERROR_VARIABLE] [COMMAND_ERROR_IS_FATAL ]) @@ -187,6 +189,27 @@ Options: `UTF-8 RFC `_ naming convention. +``ENVIRONMENT ...`` + .. 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 ...`` + .. 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 `` .. versionadded:: 3.19 diff --git a/Help/release/dev/execute_process-environment.rst b/Help/release/dev/execute_process-environment.rst new file mode 100644 index 0000000000..d14bc4bbaa --- /dev/null +++ b/Help/release/dev/execute_process-environment.rst @@ -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. diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 63dcb6079a..d5e9a3a1b0 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -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 const& args, bool EchoOutputVariable = false; bool EchoErrorVariable = false; cm::optional Encoding; + ArgumentParser::MaybeEmpty> Environment; + ArgumentParser::MaybeEmpty> EnvModification; std::string CommandErrorIsFatal; }; @@ -117,6 +121,8 @@ bool cmExecuteProcessCommand(std::vector 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 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 inputFile(nullptr, fclose); if (!inputFilename.empty()) { diff --git a/Tests/RunCMake/execute_process/Environment-stdout.txt b/Tests/RunCMake/execute_process/Environment-stdout.txt new file mode 100644 index 0000000000..747b1ab370 --- /dev/null +++ b/Tests/RunCMake/execute_process/Environment-stdout.txt @@ -0,0 +1 @@ +CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value diff --git a/Tests/RunCMake/execute_process/Environment.cmake b/Tests/RunCMake/execute_process/Environment.cmake new file mode 100644 index 0000000000..86273b5dd7 --- /dev/null +++ b/Tests/RunCMake/execute_process/Environment.cmake @@ -0,0 +1,5 @@ +execute_process( + COMMAND ${CMAKE_COMMAND} -E environment + ENVIRONMENT + "CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=expected_value" + ) diff --git a/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt b/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt new file mode 100644 index 0000000000..eb07dc9e8d --- /dev/null +++ b/Tests/RunCMake/execute_process/EnvironmentModification-stdout.txt @@ -0,0 +1 @@ +CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=kaesekuchen diff --git a/Tests/RunCMake/execute_process/EnvironmentModification.cmake b/Tests/RunCMake/execute_process/EnvironmentModification.cmake new file mode 100644 index 0000000000..cd23fd39ad --- /dev/null +++ b/Tests/RunCMake/execute_process/EnvironmentModification.cmake @@ -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" + ) diff --git a/Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt b/Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/execute_process/EnvironmentModificationError-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt b/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt new file mode 100644 index 0000000000..a3d4c09b9e --- /dev/null +++ b/Tests/RunCMake/execute_process/EnvironmentModificationError-stderr.txt @@ -0,0 +1 @@ +CMake Error: Error: Unrecognized environment manipulation argument: invalid diff --git a/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake b/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake new file mode 100644 index 0000000000..9a9a7ede56 --- /dev/null +++ b/Tests/RunCMake/execute_process/EnvironmentModificationError.cmake @@ -0,0 +1,5 @@ +execute_process( + COMMAND ${CMAKE_COMMAND} -E environment + ENVIRONMENT_MODIFICATION + "CMAKE_TEST_RUNCMAKE_EXECUTE_PROCESS_ENVIRONMENT=invalid:value" + ) diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake index 973ff1201a..3137d66761 100644 --- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake +++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake @@ -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()