From fdc21950905d64b2ca1df5a0b2622022beffe922 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 11 Dec 2014 09:45:26 +0200 Subject: Improve diagnostics and error handling g++-4.9 -std=c++14 -g -I.. -o bd bd.cxx target.cxx native.cxx rule.cxx cxx/rule.cxx cxx/target.cxx process.cxx timestamp.cxx path.cxx --- build/cxx/rule | 2 +- build/cxx/rule.cxx | 55 +++++++++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 26 deletions(-) (limited to 'build/cxx') diff --git a/build/cxx/rule b/build/cxx/rule index 85352b7..4900180 100644 --- a/build/cxx/rule +++ b/build/cxx/rule @@ -28,7 +28,7 @@ namespace build update (target&); private: - bool + void inject_prerequisites (obj&, const cxx&) const; }; diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx index 31c27dc..ccc9bb5 100644 --- a/build/cxx/rule.cxx +++ b/build/cxx/rule.cxx @@ -14,6 +14,7 @@ #include #include +#include using namespace std; @@ -63,11 +64,7 @@ namespace build // Inject additional prerequisites. // - // @@ If this failed, saying that the rule did not match is - // not quite correct. - // - if (!inject_prerequisites (o, *s)) - return recipe (); + inject_prerequisites (o, *s); return recipe (&update); } @@ -114,12 +111,12 @@ namespace build return r; } - bool compile:: + void compile:: inject_prerequisites (obj& o, const cxx& s) const { const char* args[] = { "g++-4.9", - "-std=c++11", + "-std=c++14", "-I..", "-M", "-MG", // Treat missing headers as generated. @@ -130,7 +127,6 @@ namespace build try { process pr (args, false, false, true); - bool r (true); __gnu_cxx::stdio_filebuf fb (pr.in_ofd, ios_base::in); istream is (&fb); @@ -142,27 +138,24 @@ namespace build if (is.fail () && !is.eof ()) { - cerr << "warning: io error while parsing output" << endl; - r = false; - break; + cerr << "error: io error while parsing g++ -M output" << endl; + throw error (); } size_t p (0); if (first) { - // Empty output usually means the wait() call below will return + // Empty output should mean the wait() call below will return // false. // if (l.empty ()) - { - r = false; break; - } - first = false; assert (l[0] == '*' && l[1] == ':' && l[2] == ' '); next (l, (p = 3)); // Skip the source file. + + first = false; } while (p != l.size ()) @@ -185,20 +178,24 @@ namespace build } } - //@@ Any diagnostics if wait() returns false. Or do we assume - // the child process issued something? + // We assume the child process issued some diagnostics. // - return pr.wait () && r; + if (!pr.wait ()) + throw error (); } catch (const process_error& e) { - cerr << "warning: unable to execute '" << args[0] << "': " << + cerr << "error: unable to execute '" << args[0] << "': " << e.what () << endl; + // In a multi-threaded program that fork()'ed but did not exec(), + // it is unwise to try to do any kind of cleanup (like unwinding + // the stack and running destructors). + // if (e.child ()) exit (1); - return false; + throw error (); } } @@ -243,7 +240,7 @@ namespace build const char* args[] = { "g++-4.9", - "-std=c++11", + "-std=c++14", "-I..", "-c", "-o", o.path ().string ().c_str (), @@ -272,8 +269,12 @@ namespace build cerr << "error: unable to execute '" << args[0] << "': " << e.what () << endl; + // In a multi-threaded program that fork()'ed but did not exec(), + // it is unwise to try to do any kind of cleanup (like unwinding + // the stack and running destructors). + // if (e.child ()) - throw; // Let caller terminate us quickly without causing a scene. + exit (1); return target_state::failed; } @@ -356,7 +357,7 @@ namespace build if (!u) return target_state::uptodate; - vector args {"g++-4.9", "-std=c++11", "-o"}; + vector args {"g++-4.9", "-std=c++14", "-o"}; args.push_back (e.path ().string ().c_str ()); @@ -390,8 +391,12 @@ namespace build cerr << "error: unable to execute '" << args[0] << "': " << e.what () << endl; + // In a multi-threaded program that fork()'ed but did not exec(), + // it is unwise to try to do any kind of cleanup (like unwinding + // the stack and running destructors). + // if (e.child ()) - throw; // Let caller terminate us quickly without causing a scene. + exit (1); return target_state::failed; } -- cgit v1.1