diff options
-rw-r--r-- | Modules/Platform/Windows-Clang.cmake | 17 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 111 | ||||
-rw-r--r-- | Source/cmcmd.h | 3 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 30 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-stderr.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_failing_first_command-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_failing_second_command-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_no_---result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_no_---stderr.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_no_args-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CommandLine/llvm_rc_no_args-stderr.txt | 1 |
12 files changed, 169 insertions, 0 deletions
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 5eddd04..7fd5e49 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -133,6 +133,23 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" ) include(Platform/Windows-MSVC) + # Feed the preprocessed rc file to llvm-rc + if(CMAKE_RC_COMPILER_INIT STREQUAL "llvm-rc") + if(DEFINED CMAKE_C_COMPILER) + set(CMAKE_RC_PREPROCESSOR CMAKE_C_COMPILER) + elseif(DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_RC_PREPROCESSOR CMAKE_CXX_COMPILER) + endif() + if(DEFINED CMAKE_RC_PREPROCESSOR) + set(CMAKE_RC_COMPILE_OBJECT "${CMAKE_COMMAND} -E cmake_llvm_rc <OBJECT>.pp <${CMAKE_RC_PREPROCESSOR}> <DEFINES> -DRC_INVOKED <INCLUDES> <FLAGS> -clang:-MD -clang:-MF -clang:<SOURCE>.d -E <SOURCE> -- <CMAKE_RC_COMPILER> <FLAGS> /fo <OBJECT> <OBJECT>.pp") + if(CMAKE_GENERATOR STREQUAL "Ninja") + set(CMAKE_NINJA_CMCLDEPS_RC 0) + set(CMAKE_NINJA_DEP_TYPE_RC gcc) + endif() + unset(CMAKE_RC_PREPROCESSOR) + endif() + endif() + macro(__windows_compiler_clang lang) set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}") __windows_compiler_msvc(${lang}) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 67c776e..7eeb97f 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -4,6 +4,10 @@ #include <cmext/algorithm> +#include <fcntl.h> + +#include "cm_uv.h" + #include "cmAlgorithms.h" #include "cmDuration.h" #include "cmGlobalGenerator.h" @@ -17,6 +21,7 @@ #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmUVProcessChain.h" #include "cmUtils.hxx" #include "cmVersion.h" #include "cmake.h" @@ -1129,6 +1134,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return cmcmd::VisualStudioLink(args, 2); } + if (args[1] == "cmake_llvm_rc") { + return cmcmd::RunLLVMRC(args); + } + // Internal CMake color makefile support. if (args[1] == "cmake_echo_color") { return cmcmd::ExecuteEchoColor(args); @@ -1660,6 +1669,108 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name) return -1; } +int cmcmd::RunPreprocessor(const std::vector<std::string>& command, + const std::string& intermediate_file) +{ + + cmUVProcessChainBuilder builder; + + uv_fs_t fs_req; + int preprocessedFile = + uv_fs_open(nullptr, &fs_req, intermediate_file.c_str(), O_CREAT | O_RDWR, + 0644, nullptr); + uv_fs_req_cleanup(&fs_req); + + builder + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, + preprocessedFile) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR) + .AddCommand(command); + auto process = builder.Start(); + if (!process.Valid()) { + std::cerr << "Failed to start preprocessor."; + return 1; + } + if (!process.Wait()) { + std::cerr << "Failed to wait for preprocessor"; + return 1; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + return 1; + } + + return 0; +} + +int cmcmd::RunLLVMRC(std::vector<std::string> const& args) +{ + // The arguments are + // args[0] == <cmake-executable> + // args[1] == cmake_llvm_rc + // args[2] == intermediate_file + // args[3..n] == preprocess+args + // args[n+1] == -- + // args[n+2...] == llvm-rc+args + if (args.size() < 3) { + std::cerr << "Invalid cmake_llvm_rc arguments"; + return 1; + } + const std::string& intermediate_file = args[2]; + std::vector<std::string> preprocess; + std::vector<std::string> resource_compile; + std::vector<std::string>* pArgTgt = &preprocess; + for (std::string const& arg : cmMakeRange(args).advance(3)) { + if (arg == "--") { + pArgTgt = &resource_compile; + } else { + pArgTgt->push_back(arg); + } + } + if (preprocess.empty()) { + std::cerr << "Empty preprocessing command"; + return 1; + } + if (resource_compile.empty()) { + std::cerr << "Empty resource compilation command"; + return 1; + } + + auto result = RunPreprocessor(preprocess, intermediate_file); + if (result != 0) { + + cmSystemTools::RemoveFile(intermediate_file); + return result; + } + cmUVProcessChainBuilder builder; + + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR) + .AddCommand(resource_compile); + auto process = builder.Start(); + result = 0; + if (!process.Valid()) { + std::cerr << "Failed to start resource compiler."; + result = 1; + } else { + if (!process.Wait()) { + std::cerr << "Failed to wait for resource compiler"; + result = 1; + } + } + + cmSystemTools::RemoveFile(intermediate_file); + if (result != 0) { + return result; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + return 1; + } + + return 0; +} + class cmVSLink { int Type; diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 17f2f9a..5b6c813 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -31,6 +31,9 @@ protected: static int ExecuteLinkScript(std::vector<std::string> const& args); static int WindowsCEEnvironment(const char* version, const std::string& name); + static int RunPreprocessor(const std::vector<std::string>& command, + const std::string& intermediate_file); + static int RunLLVMRC(std::vector<std::string> const& args); static int VisualStudioLink(std::vector<std::string> const& args, int type); }; diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 4bdc759..087ef21 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -667,3 +667,33 @@ if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") run_cmake_command(closed_stderr sh -c "\"${CMAKE_COMMAND}\" --version 2>&-") run_cmake_command(closed_stdall sh -c "\"${CMAKE_COMMAND}\" --version <&- >&- 2>&-") endif() + +function(run_llvm_rc) + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/llvm_rc-build") + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake_command(llvm_rc_no_args ${CMAKE_COMMAND} -E cmake_llvm_rc) + run_cmake_command(llvm_rc_no_-- ${CMAKE_COMMAND} -E cmake_llvm_rc test.tmp ${CMAKE_COMMAND} -E echo "This is a test") + run_cmake_command(llvm_rc_empty_preprocessor ${CMAKE_COMMAND} -E cmake_llvm_rc test.tmp -- ${CMAKE_COMMAND} -E echo "This is a test") + run_cmake_command(llvm_rc_failing_first_command ${CMAKE_COMMAND} -E cmake_llvm_rc test.tmp ${CMAKE_COMMAND} -E false -- ${CMAKE_COMMAND} -E echo "This is a test") + run_cmake_command(llvm_rc_failing_second_command ${CMAKE_COMMAND} -E cmake_llvm_rc test.tmp ${CMAKE_COMMAND} -E echo "This is a test" -- ${CMAKE_COMMAND} -E false ) + if(EXISTS ${RunCMake_TEST_BINARY_DIR}/test.tmp) + message(SEND_ERROR "${test} - FAILED:\n" + "test.tmp was not deleted") + endif() + run_cmake_command(llvm_rc_full_run ${CMAKE_COMMAND} -E cmake_llvm_rc test.tmp ${CMAKE_COMMAND} -E echo "This is a test" -- ${CMAKE_COMMAND} -E copy test.tmp llvmrc.result ) + if(EXISTS ${RunCMake_TEST_BINARY_DIR}/test.tmp) + message(SEND_ERROR "${test} - FAILED:\n" + "test.tmp was not deleted") + endif() + file(READ ${RunCMake_TEST_BINARY_DIR}/llvmrc.result LLVMRC_RESULT) + if(NOT "${LLVMRC_RESULT}" STREQUAL "This is a test\n") + message(SEND_ERROR "${test} - FAILED:\n" + "llvmrc.result was not created") + endif() + # file(REMOVE ${RunCMake_TEST_BINARY_DIR}/llvmrc.result) + unset(LLVMRC_RESULT) +endfunction() +run_llvm_rc() diff --git a/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-result.txt b/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-stderr.txt b/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-stderr.txt new file mode 100644 index 0000000..cb69366 --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_empty_preprocessor-stderr.txt @@ -0,0 +1 @@ +Empty preprocessing command diff --git a/Tests/RunCMake/CommandLine/llvm_rc_failing_first_command-result.txt b/Tests/RunCMake/CommandLine/llvm_rc_failing_first_command-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_failing_first_command-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/llvm_rc_failing_second_command-result.txt b/Tests/RunCMake/CommandLine/llvm_rc_failing_second_command-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_failing_second_command-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/llvm_rc_no_---result.txt b/Tests/RunCMake/CommandLine/llvm_rc_no_---result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_no_---result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/llvm_rc_no_---stderr.txt b/Tests/RunCMake/CommandLine/llvm_rc_no_---stderr.txt new file mode 100644 index 0000000..9c140b7 --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_no_---stderr.txt @@ -0,0 +1 @@ +Empty resource compilation command diff --git a/Tests/RunCMake/CommandLine/llvm_rc_no_args-result.txt b/Tests/RunCMake/CommandLine/llvm_rc_no_args-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_no_args-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/llvm_rc_no_args-stderr.txt b/Tests/RunCMake/CommandLine/llvm_rc_no_args-stderr.txt new file mode 100644 index 0000000..d66b547 --- /dev/null +++ b/Tests/RunCMake/CommandLine/llvm_rc_no_args-stderr.txt @@ -0,0 +1 @@ +Invalid cmake_llvm_rc arguments |