From 48e2e4140b8e5aacdfd107a1215f21c9632c81c8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 22 Aug 2016 12:55:21 +0200 Subject: Cache process_path, use fallback search directory for binutils --- build2/bin/guess | 10 +++++-- build2/bin/guess.cxx | 81 +++++++++++++++++++++++++++++--------------------- build2/bin/init.cxx | 83 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 111 insertions(+), 63 deletions(-) (limited to 'build2/bin') diff --git a/build2/bin/guess b/build2/bin/guess index 540e644..bcf9732 100644 --- a/build2/bin/guess +++ b/build2/bin/guess @@ -30,10 +30,12 @@ namespace build2 // struct ar_info { + process_path ar_path; string ar_id; string ar_signature; string ar_checksum; + process_path ranlib_path; string ranlib_id; string ranlib_signature; string ranlib_checksum; @@ -43,7 +45,7 @@ namespace build2 // attemplated and the returned ranlib_* members will be left empty. // ar_info - guess_ar (const path& ar, const path* ranlib); + guess_ar (const path& ar, const path* ranlib, const dir_path& fallback); // ld information. // @@ -67,13 +69,14 @@ namespace build2 // struct ld_info { + process_path path; string id; string signature; string checksum; }; ld_info - guess_ld (const path& ld); + guess_ld (const path& ld, const dir_path& fallback); // rc information. // @@ -90,13 +93,14 @@ namespace build2 // struct rc_info { + process_path path; string id; string signature; string checksum; }; rc_info - guess_rc (const path& rc); + guess_rc (const path& rc, const dir_path& fallback); } } diff --git a/build2/bin/guess.cxx b/build2/bin/guess.cxx index de91db3..13f3933 100644 --- a/build2/bin/guess.cxx +++ b/build2/bin/guess.cxx @@ -18,17 +18,26 @@ namespace build2 string signature; string checksum; + guess_result () = default; + guess_result (string&& i, string&& s) + : id (move (i)), signature (move (s)) {} + bool empty () const {return id.empty ();} }; ar_info - guess_ar (const path& ar, const path* rl) + guess_ar (const path& ar, const path* rl, const dir_path& fallback) { tracer trace ("bin::guess_ar"); guess_result arr, rlr; + process_path arp (run_search (ar, true, fallback)); + process_path rlp (rl != nullptr + ? run_search (*rl, true, fallback) + : process_path ()); + // Binutils, LLVM, and FreeBSD ar/ranlib all recognize the --version // option. While Microsoft's lib.exe doesn't support --version, it only // issues a warning and exits with zero status, printing its usual @@ -43,23 +52,23 @@ namespace build2 // "GNU ar ". // if (l.compare (0, 7, "GNU ar ") == 0) - return guess_result {"gnu", move (l), ""}; + return guess_result ("gnu", move (l)); // LLVM ar --version output has a line that starts with // "LLVM version ". // if (l.compare (0, 13, "LLVM version ") == 0) - return guess_result {"llvm", move (l), ""}; + return guess_result ("llvm", move (l)); // FreeBSD ar --verison output starts with "BSD ar ". // if (l.compare (0, 7, "BSD ar ") == 0) - return guess_result {"bsd", move (l), ""}; + return guess_result ("bsd", move (l)); // Microsoft lib.exe output starts with "Microsoft (R) ". // if (l.compare (0, 14, "Microsoft (R) ") == 0) - return guess_result {"msvc", move (l), ""}; + return guess_result ("msvc", move (l)); return guess_result (); }; @@ -69,7 +78,7 @@ namespace build2 // (yes, it goes to stdout) but that seems harmless. // sha256 cs; - arr = run (ar, "--version", f, false, false, &cs); + arr = run (arp, "--version", f, false, false, &cs); if (!arr.empty ()) arr.checksum = cs.string (); @@ -85,14 +94,14 @@ namespace build2 auto f = [] (string& l) -> guess_result { return l.find (" ar ") != string::npos - ? guess_result {"generic", move (l), ""} + ? guess_result ("generic", move (l)) : guess_result (); }; // Redirect STDERR to STDOUT and ignore exit status. // sha256 cs; - arr = run (ar, f, false, true, &cs); + arr = run (arp, f, false, true, &cs); if (!arr.empty ()) { @@ -116,24 +125,24 @@ namespace build2 // "GNU ranlib ". // if (l.compare (0, 11, "GNU ranlib ") == 0) - return guess_result {"gnu", move (l), ""}; + return guess_result ("gnu", move (l)); // "LLVM version ". // if (l.compare (0, 13, "LLVM version ") == 0) - return guess_result {"llvm", move (l), ""}; + return guess_result ("llvm", move (l)); // On FreeBSD we get "ranlib" rather than "BSD ranlib" for some // reason. Which means we can't really call it 'bsd' for sure. // //if (l.compare (0, 7, "ranlib ") == 0) - // return guess_result {"bsd", move (l), ""}; + // return guess_result ("bsd", move (l)); return guess_result (); }; sha256 cs; - rlr = run (*rl, "--version", f, false, false, &cs); + rlr = run (rlp, "--version", f, false, false, &cs); if (!rlr.empty ()) rlr.checksum = cs.string (); @@ -146,14 +155,14 @@ namespace build2 auto f = [] (string& l) -> guess_result { return l.find ("ranlib") != string::npos - ? guess_result {"generic", move (l), ""} + ? guess_result ("generic", move (l)) : guess_result (); }; // Redirect STDERR to STDOUT and ignore exit status. // sha256 cs; - rlr = run (*rl, f, false, true, &cs); + rlr = run (rlp, f, false, true, &cs); if (!rlr.empty ()) { @@ -167,17 +176,19 @@ namespace build2 } return ar_info { - move (arr.id), move (arr.signature), move (arr.checksum), - move (rlr.id), move (rlr.signature), move (rlr.checksum)}; + move (arp), move (arr.id), move (arr.signature), move (arr.checksum), + move (rlp), move (rlr.id), move (rlr.signature), move (rlr.checksum)}; } ld_info - guess_ld (const path& ld) + guess_ld (const path& ld, const dir_path& fallback) { tracer trace ("bin::guess_ld"); guess_result r; + process_path pp (run_search (ld, true, fallback)); + // Binutils ld recognizes the --version option. Microsoft's link.exe // doesn't support --version (nor any other way to get the version // without the error exist status) but it will still print its banner. @@ -194,16 +205,16 @@ namespace build2 // Microsoft link.exe output starts with "Microsoft (R) ". // if (l.compare (0, 14, "Microsoft (R) ") == 0) - return guess_result {"msvc", move (l), ""}; + return guess_result ("msvc", move (l)); // Binutils ld.bfd --version output has a line that starts with // "GNU ld " while ld.gold -- "GNU gold". // if (l.compare (0, 7, "GNU ld ") == 0) - return guess_result {"gnu", move (l), ""}; + return guess_result ("gnu", move (l)); if (l.compare (0, 9, "GNU gold ") == 0) - return guess_result {"gold", move (l), ""}; + return guess_result ("gold", move (l)); return guess_result (); }; @@ -213,7 +224,7 @@ namespace build2 // but that seems harmless. // sha256 cs; - r = run (ld, "--version", f, false, true, &cs); + r = run (pp, "--version", f, false, true, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -231,20 +242,20 @@ namespace build2 // @(#)PROGRAM:ld PROJECT:ld64-242.2 // if (l.find ("PROJECT:ld64") != string::npos) - return guess_result {"ld64", move (l), ""}; + return guess_result ("ld64", move (l)); // Old ld has "cctools" in the first line, for example: // // Apple Computer, Inc. version cctools-622.9~2 // if (l.find ("cctools") != string::npos) - return guess_result {"cctools", move (l), ""}; + return guess_result ("cctools", move (l)); return guess_result (); }; sha256 cs; - r = run (ld, "-v", f, false, false, &cs); + r = run (pp, "-v", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -262,7 +273,7 @@ namespace build2 // LLVM Linker Version: 3.7 // if (l.compare (0, 19, "LLVM Linker Version") == 0) - return guess_result {"llvm", move (l), ""}; + return guess_result ("llvm", move (l)); return guess_result (); }; @@ -271,7 +282,7 @@ namespace build2 // option. // sha256 cs; - r = run (ld, "-version", f, false, false, &cs); + r = run (pp, "-version", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -280,16 +291,19 @@ namespace build2 if (r.empty ()) fail << "unable to guess " << ld << " signature"; - return ld_info {move (r.id), move (r.signature), move (r.checksum)}; + return ld_info { + move (pp), move (r.id), move (r.signature), move (r.checksum)}; } rc_info - guess_rc (const path& rc) + guess_rc (const path& rc, const dir_path& fallback) { tracer trace ("bin::guess_rc"); guess_result r; + process_path pp (run_search (rc, true, fallback)); + // Binutils windres recognizes the --version option. // { @@ -299,7 +313,7 @@ namespace build2 // "GNU windres ". // if (l.compare (0, 12, "GNU windres ") == 0) - return guess_result {"gnu", move (l), ""}; + return guess_result ("gnu", move (l)); return guess_result (); }; @@ -308,7 +322,7 @@ namespace build2 // option. // sha256 cs; - r = run (rc, "--version", f, false, false, &cs); + r = run (pp, "--version", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -322,13 +336,13 @@ namespace build2 auto f = [] (string& l) -> guess_result { if (l.compare (0, 14, "Microsoft (R) ") == 0) - return guess_result {"msvc", move (l), ""}; + return guess_result ("msvc", move (l)); return guess_result (); }; sha256 cs; - r = run (rc, "/?", f, false, false, &cs); + r = run (pp, "/?", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -337,7 +351,8 @@ namespace build2 if (r.empty ()) fail << "unable to guess " << rc << " signature"; - return rc_info {move (r.id), move (r.signature), move (r.checksum)}; + return rc_info { + move (pp), move (r.id), move (r.signature), move (r.checksum)}; } } } diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx index 424a729..125bc7d 100644 --- a/build2/bin/init.cxx +++ b/build2/bin/init.cxx @@ -273,8 +273,12 @@ namespace build2 { const string& s (cast (*v)); - if (s.find ('*') == string::npos) + if (s.empty () || + (!path::traits::is_separator (s.back ()) && + s.find ('*') == string::npos)) + { fail << "missing '*' in binutils pattern '" << s << "'"; + } r.assign ("bin.pattern") = s; new_val = new_val || p.second; // False for a hinted value. @@ -428,8 +432,11 @@ namespace build2 { auto& v (var_pool); - v.insert ("config.bin.ar", true); - v.insert ("config.bin.ranlib", true); + v.insert ("bin.rc.path"); + v.insert ("bin.ranlib.path"); + + v.insert ("config.bin.ar", true); + v.insert ("config.bin.ranlib", true); } // Configure. @@ -456,6 +463,11 @@ namespace build2 const string& tsys (cast (r["bin.target.system"])); const char* ar_d (tsys == "win32-msvc" ? "lib" : "ar"); + // This can be either a pattern or a fallback search directory. + // + const string* pat (cast_null (r["bin.pattern"])); + bool fb (pat != nullptr && path::traits::is_separator (pat->back ())); + // Don't save the default value to config.build so that if the user // changes, say, the C++ compiler (which hinted the pattern), then // ar will automatically change as well. @@ -464,7 +476,7 @@ namespace build2 config::required ( r, "config.bin.ar", - path (apply_pattern (ar_d, cast_null (r["bin.pattern"]))), + path (apply_pattern (ar_d, fb ? nullptr : pat)), false, config::save_commented)); @@ -482,7 +494,8 @@ namespace build2 if (ranlib != nullptr && ranlib->empty ()) // @@ BC LT [null]. ranlib = nullptr; - ar_info ari (guess_ar (ar, ranlib)); + ar_info ari ( + guess_ar (ar, ranlib, fb ? dir_path (*pat) : dir_path ())); // If this is a new value (e.g., we are configuring), then print the // report at verbosity level 2 and up (-v). @@ -492,7 +505,7 @@ namespace build2 diag_record dr (text); dr << "bin.ar " << project (r) << '@' << r.out_path () << '\n' - << " ar " << ar << '\n' + << " ar " << ari.ar_path << '\n' << " id " << ari.ar_id << '\n' << " signature " << ari.ar_signature << '\n' << " checksum " << ari.ar_checksum; @@ -500,23 +513,25 @@ namespace build2 if (ranlib != nullptr) { dr << '\n' - << " ranlib " << *ranlib << '\n' + << " ranlib " << ari.ranlib_path << '\n' << " id " << ari.ranlib_id << '\n' << " signature " << ari.ranlib_signature << '\n' << " checksum " << ari.ranlib_checksum; } } - r.assign ("bin.ar.id") = move (ari.ar_id); - r.assign ("bin.ar.signature") = move (ari.ar_signature); - r.assign ("bin.ar.checksum") = move (ari.ar_checksum); + r.assign ("bin.ar.path") = move (ari.ar_path); + r.assign ("bin.ar.id") = move (ari.ar_id); + r.assign ("bin.ar.signature") = move (ari.ar_signature); + r.assign ("bin.ar.checksum") = move (ari.ar_checksum); if (ranlib != nullptr) { - r.assign ("bin.ranlib.id") = move (ari.ranlib_id); - r.assign ("bin.ranlib.signature") = + r.assign ("bin.ranlib.path") = move (ari.ranlib_path); + r.assign ("bin.ranlib.id") = move (ari.ranlib_id); + r.assign ("bin.ranlib.signature") = move (ari.ranlib_signature); - r.assign ("bin.ranlib.checksum") = + r.assign ("bin.ranlib.checksum") = move (ari.ranlib_checksum); } } @@ -570,7 +585,8 @@ namespace build2 { auto& v (var_pool); - v.insert ("config.bin.ld", true); + v.insert ("bin.ld.path"); + v.insert ("config.bin.ld", true); } // Configure. @@ -584,16 +600,21 @@ namespace build2 const string& tsys (cast (r["bin.target.system"])); const char* ld_d (tsys == "win32-msvc" ? "link" : "ld"); + // This can be either a pattern or a fallback search directory. + // + const string* pat (cast_null (r["bin.pattern"])); + bool fb (pat != nullptr && path::traits::is_separator (pat->back ())); + auto p ( config::required ( r, "config.bin.ld", - path (apply_pattern (ld_d, cast_null (r["bin.pattern"]))), + path (apply_pattern (ld_d, fb ? nullptr : pat)), false, config::save_commented)); const path& ld (cast (p.first)); - ld_info ldi (guess_ld (ld)); + ld_info ldi (guess_ld (ld, fb ? dir_path (*pat) : dir_path ())); // If this is a new value (e.g., we are configuring), then print the // report at verbosity level 2 and up (-v). @@ -601,15 +622,16 @@ namespace build2 if (verb >= (p.second ? 2 : 3)) { text << "bin.ld " << project (r) << '@' << r.out_path () << '\n' - << " ld " << ld << '\n' + << " ld " << ldi.path << '\n' << " id " << ldi.id << '\n' << " signature " << ldi.signature << '\n' << " checksum " << ldi.checksum; } - r.assign ("bin.ld.id") = move (ldi.id); - r.assign ("bin.ld.signature") = move (ldi.signature); - r.assign ("bin.ld.checksum") = move (ldi.checksum); + r.assign ("bin.ld.path") = move (ldi.path); + r.assign ("bin.ld.id") = move (ldi.id); + r.assign ("bin.ld.signature") = move (ldi.signature); + r.assign ("bin.ld.checksum") = move (ldi.checksum); } return true; @@ -674,7 +696,8 @@ namespace build2 { auto& v (var_pool); - v.insert ("config.bin.rc", true); + v.insert ("bin.rc.path"); + v.insert ("config.bin.rc", true); } // Configure. @@ -688,16 +711,21 @@ namespace build2 const string& tsys (cast (r["bin.target.system"])); const char* rc_d (tsys == "win32-msvc" ? "rc" : "windres"); + // This can be either a pattern or a fallback search directory. + // + const string* pat (cast_null (r["bin.pattern"])); + bool fb (pat != nullptr && path::traits::is_separator (pat->back ())); + auto p ( config::required ( r, "config.bin.rc", - path (apply_pattern (rc_d, cast_null (r["bin.pattern"]))), + path (apply_pattern (rc_d, fb ? nullptr : pat)), false, config::save_commented)); const path& rc (cast (p.first)); - rc_info rci (guess_rc (rc)); + rc_info rci (guess_rc (rc, fb ? dir_path (*pat) : dir_path ())); // If this is a new value (e.g., we are configuring), then print the // report at verbosity level 2 and up (-v). @@ -705,15 +733,16 @@ namespace build2 if (verb >= (p.second ? 2 : 3)) { text << "bin.rc " << project (r) << '@' << r.out_path () << '\n' - << " rc " << rc << '\n' + << " rc " << rci.path << '\n' << " id " << rci.id << '\n' << " signature " << rci.signature << '\n' << " checksum " << rci.checksum; } - r.assign ("bin.rc.id") = move (rci.id); - r.assign ("bin.rc.signature") = move (rci.signature); - r.assign ("bin.rc.checksum") = move (rci.checksum); + r.assign ("bin.rc.path") = move (rci.path); + r.assign ("bin.rc.id") = move (rci.id); + r.assign ("bin.rc.signature") = move (rci.signature); + r.assign ("bin.rc.checksum") = move (rci.checksum); } return true; -- cgit v1.1