diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-11-05 11:24:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-11-05 11:24:45 +0200 |
commit | df56d347a75151c7bd6a4d3837f62777cc0354ca (patch) | |
tree | f2c2c0e91e45cdd5e97fd38850e41798442047fe | |
parent | fa05a1a11dc42b393c99059cd0705912b48b050d (diff) |
Resolve /WN /Wall /w option overrides
Failed that, MSVC "helpfully" warns that one is overriding the other.
-rw-r--r-- | build2/cc/compile-rule.cxx | 10 | ||||
-rw-r--r-- | build2/cc/msvc.cxx | 70 |
2 files changed, 73 insertions, 7 deletions
diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx index 720b9d0..437255e 100644 --- a/build2/cc/compile-rule.cxx +++ b/build2/cc/compile-rule.cxx @@ -1448,6 +1448,9 @@ namespace build2 } } + void + msvc_sanitize_cl (cstrings&); // msvc.cxx + // Extract and inject header dependencies. Return the preprocessed source // file as well as an indication if it is usable for compilation (see // below for details). @@ -1916,6 +1919,8 @@ namespace build2 args.push_back (pp); // /C (preserve comments). args.push_back ("/WX"); // Warning as error (see above). + msvc_sanitize_cl (args); + psrc = auto_rmfile (t.path () + x_pext); if (cast<uint64_t> (rs[x_version_major]) >= 18) @@ -2984,6 +2989,9 @@ namespace build2 args.push_back ("/E"); args.push_back ("/C"); + + msvc_sanitize_cl (args); + args.push_back (langopt (md)); // Compile as. break; @@ -4331,6 +4339,8 @@ namespace build2 if (!find_option_prefixes ({"/MD", "/MT"}, args)) args.push_back ("/MD"); + msvc_sanitize_cl (args); + append_modules (env, args, mods, a, t, md); // The presence of /Zi or /ZI causes the compiler to write debug info diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index 272b48c..4f63abf 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -2,6 +2,8 @@ // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file +#include <cstring> // strcmp() + #include <build2/scope.hxx> #include <build2/target.hxx> #include <build2/context.hxx> @@ -16,7 +18,8 @@ #include <build2/cc/common.hxx> #include <build2/cc/module.hxx> -using namespace std; +using std::strcmp; + using namespace butl; namespace build2 @@ -42,6 +45,61 @@ namespace build2 return m; } + // Sanitize cl.exe options. + // + void + msvc_sanitize_cl (cstrings& args) + { + // VC is trying to be "helpful" and warn about one command line option + // overriding another. For example: + // + // cl : Command line warning D9025 : overriding '/W1' with '/W2' + // + // So we have to sanitize the command line and suppress duplicates of + // certain options. + // + // Note also that it is theoretically possible we will treat an option's + // argument as an option. Oh, well, nobody is perfect in the Microsoft + // land. + + // We want to keep the last option seen at the position (relative to + // other options) that it was encountered. If we were to iterate forward + // and keep positions of the enountered options, then we would have had + // to adjust some of them once we remove a duplicate. So instead we are + // going to iterate backwards, in which case we don't even need to keep + // positions, just flags. Note that args[0] is cl.exe itself in which we + // are conveniently not interested. + // + bool W (false); // /WN /Wall /w + + for (size_t i (args.size () - 1); i != 0; --i) + { + auto erase = [&args, &i] () + { + args.erase (args.begin () + i); + }; + + const char* a (args[i]); + + if (*a != '/' && *a != '-') // Not an option. + continue; + + ++a; + + // /WN /Wall /w + // + if ((a[0] == 'W' && digit (a[1]) && a[2] == '\0') || // WN + (a[0] == 'W' && strcmp (a + 1, "all") == 0) || // Wall + (a[0] == 'w' && a[1] == '\0')) // w + { + if (W) + erase (); + else + W = true; + } + } + } + // Sense whether this is a diagnostics line returning the postion of the // NNNN code in XNNNN and npos otherwise. // @@ -59,15 +117,13 @@ namespace build2 p != string::npos; p = ++p != n ? l.find_first_of (": ", p) : string::npos) { - auto isnum = [](char c) {return c >= '0' && c <= '9';}; - if (p > 5 && l[p - 6] == ' ' && l[p - 5] == f && - isnum (l[p - 4]) && - isnum (l[p - 3]) && - isnum (l[p - 2]) && - isnum (l[p - 1])) + digit (l[p - 4]) && + digit (l[p - 3]) && + digit (l[p - 2]) && + digit (l[p - 1])) { p -= 4; // Start of the error code. break; |