From e3297045467e7bb6389237e9ace2815abef61159 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 5 Jun 2023 13:11:19 -0400 Subject: cmUVProcessChain: Add support for SetExternalStream(Stream_INPUT) --- Source/cmUVProcessChain.cxx | 27 ++++++++++++++++++++++----- Tests/CMakeLib/CMakeLists.txt | 1 + Tests/CMakeLib/testUVProcessChain.cxx | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx index a9e57e6..cf4475b 100644 --- a/Source/cmUVProcessChain.cxx +++ b/Source/cmUVProcessChain.cxx @@ -64,6 +64,7 @@ struct cmUVProcessChain::InternalData cm::uv_loop_ptr Loop; + StreamData InputStreamData; StreamData OutputStreamData; StreamData ErrorStreamData; cm::uv_pipe_ptr TempOutputPipe; @@ -134,9 +135,6 @@ cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream( { switch (stdio) { case Stream_INPUT: - // FIXME - break; - case Stream_OUTPUT: case Stream_ERROR: { auto& streamData = this->Stdio[stdio]; @@ -184,6 +182,25 @@ bool cmUVProcessChain::InternalData::Prepare( { this->Builder = builder; + auto const& input = + this->Builder->Stdio[cmUVProcessChainBuilder::Stream_INPUT]; + auto& inputData = this->InputStreamData; + switch (input.Type) { + case cmUVProcessChainBuilder::None: + inputData.Stdio.flags = UV_IGNORE; + break; + + case cmUVProcessChainBuilder::Builtin: { + // FIXME + break; + } + + case cmUVProcessChainBuilder::External: + inputData.Stdio.flags = UV_INHERIT_FD; + inputData.Stdio.data.fd = input.FileDescriptor; + break; + } + auto const& error = this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR]; auto& errorData = this->ErrorStreamData; @@ -328,10 +345,10 @@ void cmUVProcessChain::InternalData::SpawnProcess( } std::array stdio; - stdio[0] = uv_stdio_container_t(); if (first) { - stdio[0].flags = UV_IGNORE; + stdio[0] = this->InputStreamData.Stdio; } else { + stdio[0] = uv_stdio_container_t(); stdio[0].flags = UV_INHERIT_STREAM; stdio[0].data.stream = process.InputPipe; } diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 5c14de2..b22d76d 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -63,6 +63,7 @@ if(WIN32) endif() configure_file(testXMLParser.h.in testXMLParser.h @ONLY) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/testUVProcessChainInput.txt" "HELLO WORLD!") create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS}) add_executable(CMakeLibTests ${CMakeLib_TEST_SRCS}) diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx index e0a67e9..f3024dc 100644 --- a/Tests/CMakeLib/testUVProcessChain.cxx +++ b/Tests/CMakeLib/testUVProcessChain.cxx @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -615,6 +616,33 @@ bool testUVProcessChainSpawnFail(const char* helperCommand) return true; } +bool testUVProcessChainInputFile(const char* helperCommand) +{ + std::unique_ptr f( + fopen("testUVProcessChainInput.txt", "rb"), fclose); + + cmUVProcessChainBuilder builder; + builder.AddCommand({ helperCommand, "dedup" }) + .SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, fileno(f.get())) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT); + + auto chain = builder.Start(); + + if (!chain.Wait()) { + std::cout << "Wait() timed out" << std::endl; + return false; + } + + std::string output = getInput(*chain.OutputStream()); + if (output != "HELO WRD!") { + std::cout << "Output was \"" << output << "\", expected \"HELO WRD!\"" + << std::endl; + return false; + } + + return true; +} + int testUVProcessChain(int argc, char** const argv) { if (argc < 2) { @@ -657,5 +685,10 @@ int testUVProcessChain(int argc, char** const argv) return -1; } + if (!testUVProcessChainInputFile(argv[1])) { + std::cout << "While executing testUVProcessChainInputFile().\n"; + return -1; + } + return 0; } -- cgit v0.12