From ea03f508420845fef72fef06ba4c9a7dacbca5fe Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 22 Oct 2020 23:06:17 +0200 Subject: llvm_rc: add llvm_rc option filter to correctly pick up all options Fixes: #21315 --- Modules/Platform/Windows-Clang.cmake | 4 ++- Source/cmcmd.cxx | 46 +++++++++++++++++++++++++-- Tests/RunCMake/CMakeLists.txt | 3 +- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 2 +- Tests/RunCMake/pseudo_llvm-rc.c | 30 +++++++++++++++++ 5 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/pseudo_llvm-rc.c diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 2261c90..6275043 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -112,7 +112,9 @@ macro(__enable_llvm_rc_preprocessing clang_option_prefix) endif() if(DEFINED CMAKE_RC_PREPROCESSOR) set(CMAKE_DEPFILE_FLAGS_RC "${clang_option_prefix}-MD ${clang_option_prefix}-MF ${clang_option_prefix}") - set(CMAKE_RC_COMPILE_OBJECT " -E cmake_llvm_rc .pp <${CMAKE_RC_PREPROCESSOR}> -DRC_INVOKED -E -- ++ -I /fo .pp") + # The are passed to the preprocess and the resource compiler to pick + # up the eventual -D / -C options passed through the CMAKE_RC_FLAGS. + set(CMAKE_RC_COMPILE_OBJECT " -E cmake_llvm_rc .pp <${CMAKE_RC_PREPROCESSOR}> -DRC_INVOKED -E -- ++ -I /fo .pp") if(CMAKE_GENERATOR MATCHES "Ninja") set(CMAKE_NINJA_CMCLDEPS_RC 0) set(CMAKE_NINJA_DEP_TYPE_RC gcc) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index ea1f968..f094085 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -58,6 +58,7 @@ #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" #include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include "cmsys/Terminal.h" int cmcmd_cmake_ninja_depends(std::vector::const_iterator argBeg, @@ -1711,7 +1712,6 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name) int cmcmd::RunPreprocessor(const std::vector& command, const std::string& intermediate_file) { - cmUVProcessChainBuilder builder; uv_fs_t fs_req; @@ -1743,7 +1743,6 @@ int cmcmd::RunPreprocessor(const std::vector& command, return 1; } - return 0; } @@ -1761,19 +1760,56 @@ int cmcmd::RunLLVMRC(std::vector const& args) std::cerr << "Invalid cmake_llvm_rc arguments"; return 1; } + const std::string& intermediate_file = args[3]; const std::string& source_file = args[2]; std::vector preprocess; std::vector resource_compile; std::vector* pArgTgt = &preprocess; + + static const cmsys::RegularExpression llvm_rc_only_single_arg("^[-/](N|Y)"); + static const cmsys::RegularExpression llvm_rc_only_double_arg( + "^[-/](C|LN|L)(.)?"); + static const cmsys::RegularExpression common_double_arg( + "^[-/](D|U|I|FO|fo|Fo)(.)?"); + bool acceptNextArg = false; + bool skipNextArg = false; for (std::string const& arg : cmMakeRange(args).advance(4)) { + if (skipNextArg) { + skipNextArg = false; + continue; + } // We use ++ as seperator between the preprocessing step definition and the // rc compilation step becase we need to prepend a -- to seperate the // source file properly from other options when using clang-cl for // preprocessing. if (arg == "++") { pArgTgt = &resource_compile; + skipNextArg = false; + acceptNextArg = true; } else { + cmsys::RegularExpressionMatch match; + if (!acceptNextArg) { + if (common_double_arg.find(arg.c_str(), match)) { + acceptNextArg = match.match(2).empty(); + } else { + if (llvm_rc_only_single_arg.find(arg.c_str(), match)) { + if (pArgTgt == &preprocess) { + continue; + } + } else if (llvm_rc_only_double_arg.find(arg.c_str(), match)) { + if (pArgTgt == &preprocess) { + skipNextArg = match.match(2).empty(); + continue; + } + acceptNextArg = match.match(2).empty(); + } else if (pArgTgt == &resource_compile) { + continue; + } + } + } else { + acceptNextArg = false; + } if (arg.find("SOURCE_DIR") != std::string::npos) { std::string sourceDirArg = arg; cmSystemTools::ReplaceString( @@ -1793,10 +1829,14 @@ int cmcmd::RunLLVMRC(std::vector const& args) std::cerr << "Empty resource compilation command"; return 1; } + // Since we might have skipped the last argument to llvm-rc + // we need to make sure the llvm-rc source file is present in the commandline + if (resource_compile.back() != intermediate_file) { + resource_compile.push_back(intermediate_file); + } auto result = RunPreprocessor(preprocess, intermediate_file); if (result != 0) { - cmSystemTools::RemoveFile(intermediate_file); return result; } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 38ab553..9fc5b69 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -565,7 +565,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)" endif() -add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}) +add_executable(pseudo_llvm-rc pseudo_llvm-rc.c) +add_RunCMake_test(CommandLine -DLLVM_RC=$ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}) add_RunCMake_test(CommandLineTar) if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG)) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 76ca898..555cd7f 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -789,7 +789,7 @@ function(run_llvm_rc) "test.tmp was not deleted") endif() file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir") - run_cmake_command(llvm_rc_full_run ${CMAKE_COMMAND} -E cmake_llvm_rc ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/source_file test.tmp ${CMAKE_COMMAND} -E echo "This is a test" ++ ${CMAKE_COMMAND} -E copy test.tmp SOURCE_DIR/llvmrc.result ) + run_cmake_command(llvm_rc_full_run ${CMAKE_COMMAND} -E cmake_llvm_rc ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/source_file test.tmp ${CMAKE_COMMAND} -E echo "This is a test" ++ ${LLVM_RC} -bad /FO SOURCE_DIR/llvmrc.result test.tmp ) if(EXISTS ${RunCMake_TEST_BINARY_DIR}/ExpandSourceDir/test.tmp) message(SEND_ERROR "${test} - FAILED:\n" "test.tmp was not deleted") diff --git a/Tests/RunCMake/pseudo_llvm-rc.c b/Tests/RunCMake/pseudo_llvm-rc.c new file mode 100644 index 0000000..7acb2a3 --- /dev/null +++ b/Tests/RunCMake/pseudo_llvm-rc.c @@ -0,0 +1,30 @@ +#include +#include + +int main(int argc, char* argv[]) +{ + FILE* source; + FILE* target; + int i; + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "-bad") == 0) { + fprintf(stdout, "stdout from bad command line arg '-bad'\n"); + fprintf(stderr, "stderr from bad command line arg '-bad'\n"); + return 1; + } + } + source = fopen(argv[argc - 1], "rb"); + if (source == NULL) { + return 1; + } + target = fopen(argv[argc - 2], "wb"); + if (target != NULL) { + char buffer[500]; + size_t n = fread(buffer, 1, sizeof(buffer), source); + fwrite(buffer, 1, n, target); + fclose(source); + fclose(target); + return 0; + } + return 1; +} -- cgit v0.12