summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2023-03-08 08:10:27 +0100
committerJoel Rosdahl <joel@rosdahl.net>2023-03-08 10:07:12 +0100
commitd099c1804f56e7a357c8c8473cacf186da0d5d3e (patch)
treea5a9897c3dc90ae9209ae5b2133632dedc5809ca
parenta179db209ba347209682b19298f5c4d4b4d4a5c7 (diff)
downloadccache-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.cpp18
-rw-r--r--src/compopt.cpp2
-rw-r--r--unittest/test_argprocessing.cpp47
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();