aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/cxx/compile.cxx49
-rw-r--r--build2/cxx/link.cxx45
-rw-r--r--build2/cxx/msvc.cxx43
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