From 35f031e3b2ed09d3c2a935e61ea621b9a6941af6 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 16 Oct 2023 10:42:52 -0400 Subject: execute_process(): Restore opening files relative to WORKING_DIRECTORY Prior to 5420639a, execute_process() would open INPUT_FILE, OUTPUT_FILE, and ERROR_FILE relative to the WORKING_DIRECTORY argument if it was provided. Restore this behavior for backwards compatibility. Fixes: #25338 --- Source/cmExecuteProcessCommand.cxx | 62 +++++++++++++++------- .../execute_process/InOutErrDirectory.cmake | 13 +++++ Tests/RunCMake/execute_process/RunCMakeTest.cmake | 5 ++ Tests/RunCMake/execute_process/StderrNoexist.cmake | 1 + Tests/RunCMake/execute_process/StdinNoexist.cmake | 1 + .../execute_process/StdouStderrNoexist.cmake | 1 + Tests/RunCMake/execute_process/StdoutNoexist.cmake | 1 + 7 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 Tests/RunCMake/execute_process/InOutErrDirectory.cmake create mode 100644 Tests/RunCMake/execute_process/StderrNoexist.cmake create mode 100644 Tests/RunCMake/execute_process/StdinNoexist.cmake create mode 100644 Tests/RunCMake/execute_process/StdouStderrNoexist.cmake create mode 100644 Tests/RunCMake/execute_process/StdoutNoexist.cmake diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 9b5f2b4..e764545 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -112,9 +112,27 @@ bool cmExecuteProcessCommand(std::vector const& args, return false; } - if (!status.GetMakefile().CanIWriteThisFile(arguments.OutputFile)) { - status.SetError("attempted to output into a file: " + - arguments.OutputFile + " into a source directory."); + std::string inputFilename = arguments.InputFile; + std::string outputFilename = arguments.OutputFile; + std::string errorFilename = arguments.ErrorFile; + if (!arguments.WorkingDirectory.empty()) { + if (!inputFilename.empty()) { + inputFilename = cmSystemTools::CollapseFullPath( + inputFilename, arguments.WorkingDirectory); + } + if (!outputFilename.empty()) { + outputFilename = cmSystemTools::CollapseFullPath( + outputFilename, arguments.WorkingDirectory); + } + if (!errorFilename.empty()) { + errorFilename = cmSystemTools::CollapseFullPath( + errorFilename, arguments.WorkingDirectory); + } + } + + if (!status.GetMakefile().CanIWriteThisFile(outputFilename)) { + status.SetError("attempted to output into a file: " + outputFilename + + " into a source directory."); cmSystemTools::SetFatalErrorOccurred(); return false; } @@ -162,20 +180,24 @@ bool cmExecuteProcessCommand(std::vector const& args, // Check the output variables. std::unique_ptr inputFile(nullptr, fclose); - if (!arguments.InputFile.empty()) { - inputFile.reset(cmsys::SystemTools::Fopen(arguments.InputFile, "rb")); - builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, - cm_fileno(inputFile.get())); + if (!inputFilename.empty()) { + inputFile.reset(cmsys::SystemTools::Fopen(inputFilename, "rb")); + if (inputFile) { + builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, + cm_fileno(inputFile.get())); + } } else { builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, cm_fileno(stdin)); } std::unique_ptr outputFile(nullptr, fclose); - if (!arguments.OutputFile.empty()) { - outputFile.reset(cmsys::SystemTools::Fopen(arguments.OutputFile, "wb")); - builder.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, - cm_fileno(outputFile.get())); + if (!outputFilename.empty()) { + outputFile.reset(cmsys::SystemTools::Fopen(outputFilename, "wb")); + if (outputFile) { + builder.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, + cm_fileno(outputFile.get())); + } } else { if (arguments.OutputVariable == arguments.ErrorVariable && !arguments.ErrorVariable.empty()) { @@ -186,14 +208,18 @@ bool cmExecuteProcessCommand(std::vector const& args, } std::unique_ptr errorFile(nullptr, fclose); - if (!arguments.ErrorFile.empty()) { - if (arguments.ErrorFile == arguments.OutputFile) { - builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, - cm_fileno(outputFile.get())); + if (!errorFilename.empty()) { + if (errorFilename == outputFilename) { + if (outputFile) { + builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, + cm_fileno(outputFile.get())); + } } else { - errorFile.reset(cmsys::SystemTools::Fopen(arguments.ErrorFile, "wb")); - builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, - cm_fileno(errorFile.get())); + errorFile.reset(cmsys::SystemTools::Fopen(errorFilename, "wb")); + if (errorFile) { + builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, + cm_fileno(errorFile.get())); + } } } else if (arguments.ErrorVariable.empty() || (!arguments.ErrorVariable.empty() && diff --git a/Tests/RunCMake/execute_process/InOutErrDirectory.cmake b/Tests/RunCMake/execute_process/InOutErrDirectory.cmake new file mode 100644 index 0000000..fe5a836 --- /dev/null +++ b/Tests/RunCMake/execute_process/InOutErrDirectory.cmake @@ -0,0 +1,13 @@ +file(MAKE_DIRECTORY dir) +file(WRITE dir/in.txt "This is a test") +execute_process(COMMAND ${PRINT_STDIN_EXE} WORKING_DIRECTORY dir INPUT_FILE in.txt OUTPUT_FILE out.txt ERROR_FILE err.txt) +if(NOT EXISTS dir/out.txt) + message(SEND_ERROR "Did not create dir/out.txt") +endif() +file(READ dir/out.txt out) +if(NOT out STREQUAL "This is a test") + message(SEND_ERROR "Did not read dir/in.txt") +endif() +if(NOT EXISTS dir/err.txt) + message(SEND_ERROR "Did not create dir/err.txt") +endif() diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake index 1f89829..1e9e10a 100644 --- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake +++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake @@ -35,6 +35,11 @@ run_cmake_command(LastCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/La run_cmake_command(LastCommandTimeout ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandTimeout.cmake) run_cmake_command(LastCommandGood ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandGood.cmake) run_cmake_command(Stdin ${CMAKE_COMMAND} -DPRINT_STDIN_EXE=${PRINT_STDIN_EXE} -P ${RunCMake_SOURCE_DIR}/Stdin.cmake) +run_cmake_command(StdinNoexist ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/StdinNoexist.cmake) +run_cmake_command(StdoutNoexist ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/StdoutNoexist.cmake) +run_cmake_command(StderrNoexist ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/StderrNoexist.cmake) +run_cmake_command(StdoutStderrNoexist ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/StderrNoexist.cmake) +run_cmake_command(InOutErrDirectory ${CMAKE_COMMAND} -DPRINT_STDIN_EXE=${PRINT_STDIN_EXE} -P ${RunCMake_SOURCE_DIR}/InOutErrDirectory.cmake) if(UNIX AND Python_EXECUTABLE) run_cmake_command(AnyCommandAbnormalExit ${CMAKE_COMMAND} -DPython_EXECUTABLE=${Python_EXECUTABLE} -P ${RunCMake_SOURCE_DIR}/AnyCommandAbnormalExit.cmake) diff --git a/Tests/RunCMake/execute_process/StderrNoexist.cmake b/Tests/RunCMake/execute_process/StderrNoexist.cmake new file mode 100644 index 0000000..632c4a2 --- /dev/null +++ b/Tests/RunCMake/execute_process/StderrNoexist.cmake @@ -0,0 +1 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true ERROR_FILE noexist/error.txt) diff --git a/Tests/RunCMake/execute_process/StdinNoexist.cmake b/Tests/RunCMake/execute_process/StdinNoexist.cmake new file mode 100644 index 0000000..6421cc8 --- /dev/null +++ b/Tests/RunCMake/execute_process/StdinNoexist.cmake @@ -0,0 +1 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true INPUT_FILE noexist/input.txt) diff --git a/Tests/RunCMake/execute_process/StdouStderrNoexist.cmake b/Tests/RunCMake/execute_process/StdouStderrNoexist.cmake new file mode 100644 index 0000000..5334cdc --- /dev/null +++ b/Tests/RunCMake/execute_process/StdouStderrNoexist.cmake @@ -0,0 +1 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true OUTPUT_FILE noexist/merged.txt ERROR_FILE noexist/merged.txt) diff --git a/Tests/RunCMake/execute_process/StdoutNoexist.cmake b/Tests/RunCMake/execute_process/StdoutNoexist.cmake new file mode 100644 index 0000000..4f5c33e --- /dev/null +++ b/Tests/RunCMake/execute_process/StdoutNoexist.cmake @@ -0,0 +1 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true OUTPUT_FILE noexist/output.txt) -- cgit v0.12