diff options
-rw-r--r-- | build2/cxx/compile.cxx | 49 | ||||
-rw-r--r-- | build2/cxx/link.cxx | 45 | ||||
-rw-r--r-- | build2/cxx/msvc.cxx | 43 |
3 files changed, 119 insertions, 18 deletions
diff --git a/build2/cxx/compile.cxx b/build2/cxx/compile.cxx index c737ce7..5e7a1b2 100644 --- a/build2/cxx/compile.cxx +++ b/build2/cxx/compile.cxx @@ -7,6 +7,7 @@ #include <map> #include <limits> // numeric_limits #include <cstdlib> // exit() +#include <iostream> // cerr #include <butl/path-map> @@ -1211,7 +1212,7 @@ namespace build2 // we need to copy the diagnostics for the user to see. // if (!is.eof () && cid == "msvc" && bad_error) - *diag_stream << is.rdbuf (); + cerr << is.rdbuf (); is.close (); @@ -1248,6 +1249,11 @@ namespace build2 } } + // Filter cl.exe noise (msvc.cxx). + // + void + msvc_filter_cl (ifdstream&, const path& src); + target_state compile:: perform_update (action a, target& xt) { @@ -1406,19 +1412,38 @@ namespace build2 try { - // @@ VC prints file name being compiled to stdout as the first - // line, would be good to weed it out (but check if it is - // always printed, for example if the file does not exist). - // Seems always. The same story with link.exe when creating - // the DLL. + // VC cl.exe sends diagnostics to stdout. It also prints the file name + // being compiled as the first line. So for cl.exe we redirect stdout + // to a pipe, filter that noise out, and send the rest to stderr. // - - // VC++ cl.exe sends diagnostics to stdout. To fix this (and any other - // insane compilers that may want to do something like this) we are - // going to always redirect stdout to stderr. For sane compilers this - // should be harmless. + // For other compilers redirect stdout to stderr, in case any of them + // tries to pull off something similar. For sane compilers this should + // be harmless. // - process pr (args.data (), 0, 2); + bool filter (cid == "msvc"); + + process pr (args.data (), 0, (filter ? -1 : 2)); + + if (filter) + { + try + { + ifdstream is (pr.in_ofd, fdstream_mode::text, ifdstream::badbit); + + msvc_filter_cl (is, rels); + + // If anything remains in the stream, send it all to stderr. Note + // that the eos check is important: if the stream is at eos, this + // and all subsequent writes to cerr will fail (and you won't see + // a thing). + // + if (is.peek () != ifdstream::traits_type::eof ()) + cerr << is.rdbuf (); + + is.close (); + } + catch (const ifdstream::failure&) {} // Assume exits with error. + } if (!pr.wait ()) throw failed (); diff --git a/build2/cxx/link.cxx b/build2/cxx/link.cxx index 9ee84ce..1624f5d 100644 --- a/build2/cxx/link.cxx +++ b/build2/cxx/link.cxx @@ -4,7 +4,8 @@ #include <build2/cxx/link> -#include <cstdlib> // exit() +#include <cstdlib> // exit() +#include <iostream> // cerr #include <butl/path-map> @@ -1079,6 +1080,11 @@ namespace build2 const char* msvc_machine (const string& cpu); // msvc.cxx + // Filter link.exe noise (msvc.cxx). + // + void + msvc_filter_link (ifdstream&, const file&, otype); + target_state link:: perform_update (action a, target& xt) { @@ -1686,12 +1692,39 @@ namespace build2 try { - // VC++ (cl.exe, lib.exe, and link.exe) sends diagnostics to stdout. - // To fix this (and any other insane compilers that may want to do - // something like this) we are going to always redirect stdout to - // stderr. For sane compilers this should be harmless. + // VC tools (both lib.exe and link.exe) send diagnostics to stdout. + // Also, link.exe likes to print various gratuitous messages. So for + // link.exe we redirect stdout to a pipe, filter that noise out, and + // send the rest to stderr. + // + // For lib.exe (and any other insane compiler that may try to pull off + // something like this) we are going to redirect stdout to stderr. For + // sane compilers this should be harmless. // - process pr (args.data (), 0, 2); + bool filter (cid == "msvc" && lt != otype::a); + + process pr (args.data (), 0, (filter ? -1 : 2)); + + if (filter) + { + try + { + ifdstream is (pr.in_ofd, fdstream_mode::text, ifdstream::badbit); + + msvc_filter_link (is, t, lt); + + // If anything remains in the stream, send it all to stderr. Note + // that the eos check is important: if the stream is at eos, this + // and all subsequent writes to cerr will fail (and you won't see + // a thing). + // + if (is.peek () != ifdstream::traits_type::eof ()) + cerr << is.rdbuf (); + + is.close (); + } + catch (const ifdstream::failure&) {} // Assume exits with error. + } if (!pr.wait ()) throw failed (); diff --git a/build2/cxx/msvc.cxx b/build2/cxx/msvc.cxx index 294ac03..dcf7fee 100644 --- a/build2/cxx/msvc.cxx +++ b/build2/cxx/msvc.cxx @@ -2,6 +2,8 @@ // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file +#include <iostream> // cerr + #include <build2/scope> #include <build2/target> #include <build2/context> @@ -37,6 +39,47 @@ namespace build2 return m; } + // Filter cl.exe and link.exe noise. + // + void + msvc_filter_cl (ifdstream& is, const path& src) + { + // While it appears VC always prints the source name (event if the + // file does not exist), let's do a sanity check. + // + string l; + if (getline (is, l) && l != src.leaf ().string ()) + cerr << l << endl; + } + + void + msvc_filter_link (ifdstream& is, const file& t, otype lt) + { + // Filter lines until we encounter something we don't recognize. We also + // have to assume the messages can be translated. + // + for (string l; getline (is, l); ) + { + // " Creating library foo\foo.dll.lib and object foo\foo.dll.exp" + // + if (lt == otype::s && l.compare (0, 3, " ") == 0) + { + path imp (static_cast<file*> (t.member)->path ().leaf ()); + + if (l.find (imp.string ()) != string::npos && + l.find (imp.base ().string () + ".exp") != string::npos) + continue; + } + + // /INCREMENTAL causes linker to sometimes issue messages but now I + // can't quite reproduce it. + // + + cerr << l << endl; + break; + } + } + // Extract system library search paths from MSVC. // void |