From e58957d6491a08ec212958457c29a14eec787279 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 11 Mar 2016 16:24:37 +0200 Subject: Implement --config-{guess,sub} options --- build2/cxx/guess.cxx | 139 +++++++++------------------------------------------ 1 file changed, 23 insertions(+), 116 deletions(-) (limited to 'build2/cxx/guess.cxx') diff --git a/build2/cxx/guess.cxx b/build2/cxx/guess.cxx index 1f5fc62..90bf693 100644 --- a/build2/cxx/guess.cxx +++ b/build2/cxx/guess.cxx @@ -5,10 +5,6 @@ #include #include // strlen() -#include // cerr - -#include -#include #include @@ -85,90 +81,6 @@ namespace build2 return ""; } - // Start a process redirecting STDOUT and STDERR to a pipe. - // - static process - start (const char* const* args) - { - if (verb >= 3) - print_process (args); - - try - { - return process (args, 0, -1, 1); - } - catch (const process_error& e) - { - if (e.child ()) - { - // Note: run() below relies on this exact message. - // - cerr << "unable to execute " << args[0] << ": " << e.what () << endl; - exit (1); - } - else - error << "unable to execute " << args[0] << ": " << e.what (); - - throw failed (); - } - }; - - // Run the compiler with the specified option and then call the predicate - // function on each line of the output until it returns a non-empty object - // T (tested with T::empty()) which is then returned to the caller. - // - // The predicate can move the value out of the passed string but only in - // case of a match (so that any diagnostics lines are left intact). - // - // If checksum is not NULL, then feed it the content of each line. - // - template - static T - run (const char* const* args, T (*f) (string&), sha256* checksum = nullptr) - try - { - process pr (start (args)); - ifdstream is (pr.in_ofd); - - T r; - - string l; // Last line of output. - while (is.peek () != ifdstream::traits_type::eof () && getline (is, l)) - { - trim (l); - - if (checksum != nullptr) - checksum->append (l); - - if (r.empty ()) - r = f (l); - } - - is.close (); // Don't block. - - if (!pr.wait ()) - { - // While we want to suppress all the compiler errors because we may be - // trying unsupported options, one error that we want to let through - // is the inability to execute the compiler itself. We cannot reserve - // a special exit status to signal this so we will just have to - // compare the output. This particular situation will result in a - // single error line printed by start() above. - // - if (l.compare (0, 18, "unable to execute ") == 0) - fail << l; - - r = T (); - } - - return r; - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e.what (); - throw failed (); - } - // Guess the compiler type and variant by running it. If the pre argument // is not empty, then only "confirm" the pre-guess. Return empty result if // unable to guess. @@ -190,7 +102,6 @@ namespace build2 tracer trace ("cxx::guess"); guess_result r; - const char* args[] = {cxx.string ().c_str (), nullptr, nullptr}; // Start with -v. This will cover gcc and clang. // @@ -282,8 +193,10 @@ namespace build2 // sha256 cs; - args[1] = "-v"; - r = run (args, f, &cs); + // Suppress all the compiler errors because we may be trying an + // unsupported option. + // + r = run (cxx, "-v", f, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -310,8 +223,7 @@ namespace build2 return guess_result (); }; - args[1] = "--version"; - r = run (args, f); + r = run (cxx, "--version", f, false); } // Finally try to run it without any options to detect msvc. @@ -343,8 +255,7 @@ namespace build2 return guess_result (); }; - args[1] = nullptr; - r = run (args, f); + r = run (cxx, f, false); } if (!r.empty ()) @@ -446,24 +357,24 @@ namespace build2 // multi-arch support), then use the result. Otherwise, fallback to // -dumpmachine (older gcc or not multi-arch). // - cstrings targs {cxx.string ().c_str (), "-print-multiarch"}; - append_options (targs, coptions); - targs.push_back (nullptr); + cstrings args {cxx.string ().c_str (), "-print-multiarch"}; + append_options (args, coptions); + args.push_back (nullptr); // The output of both -print-multiarch and -dumpmachine is a single line // containing just the target triplet. // - auto f = [] (string& l) {return string (move (l));}; + auto f = [] (string& l) {return move (l);}; - string t (run (targs.data (), f)); + string t (run (args.data (), f, false)); if (t.empty ()) { l5 ([&]{trace << cxx << " doesn's support -print-multiarch, " << "falling back to -dumpmachine";}); - targs[1] = "-dumpmachine"; - t = run (targs.data (), f); + args[1] = "-dumpmachine"; + t = run (args.data (), f); } if (t.empty ()) @@ -549,16 +460,14 @@ namespace build2 // Unlike gcc, clang doesn't have -print-multiarch. Its -dumpmachine, // however, respects the compile options (e.g., -m32). // - cstrings targs {cxx.string ().c_str (), "-dumpmachine"}; - append_options (targs, coptions); - targs.push_back (nullptr); + cstrings args {cxx.string ().c_str (), "-dumpmachine"}; + append_options (args, coptions); + args.push_back (nullptr); // The output of -dumpmachine is a single line containing just the // target triplet. // - auto f = [] (string& l) {return string (move (l));}; - - string t (run (targs.data (), f)); + string t (run (args.data (), [] (string& l) {return move (l);})); if (t.empty ()) fail << "unable to extract target architecture from " << cxx @@ -611,8 +520,7 @@ namespace build2 : string (); }; - const char* vargs[] = {cxx.string ().c_str (), "-V", nullptr}; - s = run (vargs, f); + s = run (cxx, "-V", f); if (s.empty ()) fail << "unable to extract signature from " << cxx << " -V output"; @@ -695,11 +603,11 @@ namespace build2 // "Intel(R)" "64" // "Intel(R)" "MIC" (-dumpmachine says: x86_64-k1om-linux) // - cstrings targs {cxx.string ().c_str (), "-V"}; - append_options (targs, coptions); - targs.push_back (nullptr); + cstrings args {cxx.string ().c_str (), "-V"}; + append_options (args, coptions); + args.push_back (nullptr); - string t (run (targs.data (), f)); + string t (run (args.data (), f)); if (t.empty ()) fail << "unable to extract target architecture from " << cxx @@ -741,8 +649,7 @@ namespace build2 // on which we are running), who knows what will happen in the future. // So instead we are going to use -dumpmachine and substitute the CPU. // - vargs[1] = "-dumpmachine"; - t = run (vargs, [] (string& l) {return string (move (l));}); + t = run (cxx, "-dumpmachine", [] (string& l) {return move (l);}); if (t.empty ()) fail << "unable to extract target architecture from " << cxx -- cgit v1.1