diff options
author | Joel Rosdahl <joel@rosdahl.net> | 2023-03-08 08:10:27 +0100 |
---|---|---|
committer | Joel Rosdahl <joel@rosdahl.net> | 2023-03-08 10:07:12 +0100 |
commit | d099c1804f56e7a357c8c8473cacf186da0d5d3e (patch) | |
tree | a5a9897c3dc90ae9209ae5b2133632dedc5809ca | |
parent | a179db209ba347209682b19298f5c4d4b4d4a5c7 (diff) | |
download | ccache-d099c1804f56e7a357c8c8473cacf186da0d5d3e.tar.gz |
feat: Support overriding MSVC /Z* options
MSVC options /Zi and /ZI are too hard since they produce separate PDB
files. /Z7 is OK, but if the command line contains /Zi or /ZI followed
by /Z7, MSVC will use the latter (with a warning) but ccache will still
consider the command line too hard.
This commit makes ccache understand that only the last /Z* option will
be used and thus accepts the command line if the last /Z* option is /Z7.
Closes #1239.
-rw-r--r-- | src/argprocessing.cpp | 18 | ||||
-rw-r--r-- | src/compopt.cpp | 2 | ||||
-rw-r--r-- | unittest/test_argprocessing.cpp | 47 |
3 files changed, 63 insertions, 4 deletions
diff --git a/src/argprocessing.cpp b/src/argprocessing.cpp index 792c57f7..bad2dadd 100644 --- a/src/argprocessing.cpp +++ b/src/argprocessing.cpp @@ -71,8 +71,9 @@ struct ArgumentProcessingState bool found_md_or_mmd_opt = false; bool found_Wa_a_opt = false; - std::string explicit_language; // As specified with -x. - std::string input_charset_option; // -finput-charset=... + std::string explicit_language; // As specified with -x. + std::string input_charset_option; // -finput-charset=... + std::string last_seen_msvc_z_option; // /Z7, /Zi or /ZI // Is the dependency file set via -Wp,-M[M]D,target or -MFtarget? OutputDepOrigin output_dep_origin = OutputDepOrigin::none; @@ -607,6 +608,12 @@ process_option_arg(const Context& ctx, return Statistic::none; } + if (config.is_compiler_group_msvc() && util::starts_with(arg, "-Z")) { + state.last_seen_msvc_z_option = args[i]; + state.common_args.push_back(args[i]); + return Statistic::none; + } + // These options require special handling, because they behave differently // with gcc -E, when the output file is not specified. if ((arg == "-MD" || arg == "-MMD") && !config.is_compiler_group_msvc()) { @@ -1160,6 +1167,13 @@ process_args(Context& ctx) return Statistic::unsupported_compiler_option; } + if (!state.last_seen_msvc_z_option.empty() + && state.last_seen_msvc_z_option.substr(2) != "7") { + // /Zi and /ZI are unsupported, but /Z7 is fine. + LOG("Compiler option {} is unsupported", state.last_seen_msvc_z_option); + return Statistic::unsupported_compiler_option; + } + // Don't try to second guess the compiler's heuristics for stdout handling. if (args_info.output_obj == "-") { LOG_RAW("Output file is -"); diff --git a/src/compopt.cpp b/src/compopt.cpp index e5415fac..a7ec8b22 100644 --- a/src/compopt.cpp +++ b/src/compopt.cpp @@ -96,8 +96,6 @@ const CompOpt compopts[] = { {"-Xpreprocessor", AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG}, {"-Yc", TAKES_ARG | TOO_HARD}, // msvc {"-Yu", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH}, // msvc - {"-ZI", TOO_HARD}, // msvc - {"-Zi", TOO_HARD}, // msvc {"-all_load", AFFECTS_COMP}, {"-analyze", TOO_HARD}, // Clang {"-arch", TAKES_ARG}, diff --git a/unittest/test_argprocessing.cpp b/unittest/test_argprocessing.cpp index be070d8f..bf98b090 100644 --- a/unittest/test_argprocessing.cpp +++ b/unittest/test_argprocessing.cpp @@ -699,4 +699,51 @@ TEST_CASE("MSVC options" CHECK(result.compiler_args.to_string() == "cl.exe /foobar -c"); } +TEST_CASE("MSVC debug information format options") +{ + TestContext test_context; + Context ctx; + ctx.config.set_compiler_type(CompilerType::msvc); + util::write_file("foo.c", ""); + + SUBCASE("Only /Z7") + { + ctx.orig_args = Args::from_string("cl.exe /c foo.c /Z7"); + const ProcessArgsResult result = process_args(ctx); + REQUIRE(!result.error); + CHECK(result.preprocessor_args.to_string() == "cl.exe /Z7"); + CHECK(result.compiler_args.to_string() == "cl.exe /Z7 -c"); + } + + SUBCASE("Only /Zi") + { + ctx.orig_args = Args::from_string("cl.exe /c foo.c /Zi"); + const ProcessArgsResult result = process_args(ctx); + CHECK(result.error == Statistic::unsupported_compiler_option); + } + + SUBCASE("Only /ZI") + { + ctx.orig_args = Args::from_string("cl.exe /c foo.c /ZI"); + const ProcessArgsResult result = process_args(ctx); + CHECK(result.error == Statistic::unsupported_compiler_option); + } + + SUBCASE("/Z7 + /Zi") + { + ctx.orig_args = Args::from_string("cl.exe /Z7 /c foo.c /Zi"); + const ProcessArgsResult result = process_args(ctx); + CHECK(result.error == Statistic::unsupported_compiler_option); + } + + SUBCASE("/Zi + /Z7") + { + ctx.orig_args = Args::from_string("cl.exe /Zi /c foo.c /Z7"); + const ProcessArgsResult result = process_args(ctx); + REQUIRE(!result.error); + CHECK(result.preprocessor_args.to_string() == "cl.exe /Zi /Z7"); + CHECK(result.compiler_args.to_string() == "cl.exe /Zi /Z7 -c"); + } +} + TEST_SUITE_END(); |