From 4218bfe7668d55e36814d6bdcec2da40454025c1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 20 May 2016 23:25:45 +0200 Subject: Initial VC++ support (static libraries only) --- build2/bin/guess | 10 +++ build2/bin/guess.cxx | 174 ++++++++++++++++++++++++++++---------------------- build2/bin/module.cxx | 4 ++ 3 files changed, 111 insertions(+), 77 deletions(-) (limited to 'build2/bin') diff --git a/build2/bin/guess b/build2/bin/guess index 005235d..a80539e 100644 --- a/build2/bin/guess +++ b/build2/bin/guess @@ -14,6 +14,14 @@ namespace build2 { // ar/ranlib information. // + // Currently recognized ar/ranlib and their ids: + // + // gnu GNU binutils + // llvm LLVM + // bsd FreeBSD (and maybe other BSDs) + // msvc Microsoft's lib.exe + // generic Generic/unrecognized + // // The signature is normally the --version/-V line. // // The checksum is used to detect ar/ranlib changes. It is calculated in @@ -22,9 +30,11 @@ namespace build2 // struct bin_info { + string ar_id; string ar_signature; string ar_checksum; + string ranlib_id; string ranlib_signature; string ranlib_checksum; }; diff --git a/build2/bin/guess.cxx b/build2/bin/guess.cxx index 1cdb40d..d036f81 100644 --- a/build2/bin/guess.cxx +++ b/build2/bin/guess.cxx @@ -12,48 +12,67 @@ namespace build2 { namespace bin { + struct guess_result + { + string id; + string signature; + string checksum; + + bool + empty () const {return id.empty ();} + }; + bin_info - guess (const path& ar, const path& ranlib) + guess (const path& ar, const path& rl) { tracer trace ("bin::guess"); - bin_info r; - string& as (r.ar_signature); + guess_result arr, rlr; // Binutils, LLVM, and FreeBSD ar/ranlib all recognize the --version - // option, so start with that. + // option. While Microsoft's lib.exe doesn't support --version, it only + // issues a warning and exits with zero status, printing its usual + // banner before that (running lib.exe without any options result in + // non-zero exit status -- go figure). So we are going to start with + // that. // { - auto f = [] (string& l) -> string + auto f = [] (string& l) -> guess_result { // Binutils ar --version output has a line that starts with // "GNU ar ". // if (l.compare (0, 7, "GNU ar ") == 0) - return 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 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 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 string (); + return guess_result (); }; // Suppress all the errors because we may be trying an unsupported - // option. + // option. Note that in case of lib.exe we will hash the warning + // (yes, it goes to stdout) but that seems harmless. // sha256 cs; - as = run (ar, "--version", f, false, false, &cs); + arr = run (ar, "--version", f, false, false, &cs); - if (!as.empty ()) - r.ar_checksum = cs.string (); + if (!arr.empty ()) + arr.checksum = cs.string (); } // On Mac OS X (and probably also older BSDs) ar/ranlib doesn't have an @@ -61,94 +80,95 @@ namespace build2 // it dumps usage and exist with an error status. So we will have to use // that. // - if (as.empty ()) + if (arr.empty ()) { - auto f = [] (string& l) -> string + auto f = [] (string& l) -> guess_result { - return l.find (" ar ") == string::npos ? string () : move (l); + return l.find (" ar ") != string::npos + ? guess_result {"generic", move (l), ""} + : guess_result (); }; // Redirect STDERR to STDOUT and ignore exit status. // sha256 cs; - as = run (ar, f, false, true, &cs); + arr = run (ar, f, false, true, &cs); - if (!as.empty ()) + if (!arr.empty ()) { - l4 ([&]{trace << "generic ar signature '" << as << "'";}); - - r.ar_signature = "Generic ar"; - r.ar_checksum = cs.string (); + l4 ([&]{trace << "generic ar '" << arr.signature << "'";}); + arr.checksum = cs.string (); } } - if (as.empty ()) + if (arr.empty ()) fail << "unable to guess " << ar << " signature"; // Now repeat pretty much the same steps for ranlib if requested. // - if (ranlib.empty ()) - return r; - - string& rs (r.ranlib_signature); - - // Binutils, LLVM, and FreeBSD. - // + if (!rl.empty ()) { - auto f = [] (string& l) -> string - { - // "GNU ranlib ". - // - if (l.compare (0, 11, "GNU ranlib ") == 0) - return move (l); - - // "LLVM version ". - // - if (l.compare (0, 13, "LLVM version ") == 0) - return move (l); - - // "ranlib " (note: not "BSD ranlib " for some reason). - // - if (l.compare (0, 7, "ranlib ") == 0) - return move (l); - - return string (); - }; - - sha256 cs; - rs = run (ranlib, "--version", f, false, false, &cs); - - if (!rs.empty ()) - r.ranlib_checksum = cs.string (); - } - - // Mac OS X (and probably also older BSDs). - // - if (rs.empty ()) - { - auto f = [] (string& l) -> string + // Binutils, LLVM, and FreeBSD. + // { - return l.find ("ranlib") == string::npos ? string () : move (l); - }; + auto f = [] (string& l) -> guess_result + { + // "GNU ranlib ". + // + if (l.compare (0, 11, "GNU ranlib ") == 0) + return guess_result {"gnu", move (l), ""}; + + // "LLVM version ". + // + if (l.compare (0, 13, "LLVM version ") == 0) + 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 (); + }; + + sha256 cs; + rlr = run (rl, "--version", f, false, false, &cs); + + if (!rlr.empty ()) + rlr.checksum = cs.string (); + } - // Redirect STDERR to STDOUT and ignore exit status. + // Mac OS X (and probably also older BSDs). // - sha256 cs; - rs = run (ranlib, f, false, true, &cs); - - if (!rs.empty ()) + if (rlr.empty ()) { - l4 ([&]{trace << "generic ranlib signature '" << rs << "'";}); - - r.ranlib_signature = "Generic ranlib"; - r.ranlib_checksum = cs.string (); + auto f = [] (string& l) -> guess_result + { + return l.find ("ranlib") != string::npos + ? guess_result {"generic", move (l), ""} + : guess_result (); + }; + + // Redirect STDERR to STDOUT and ignore exit status. + // + sha256 cs; + rlr = run (rl, f, false, true, &cs); + + if (!rlr.empty ()) + { + l4 ([&]{trace << "generic ranlib '" << rlr.signature << "'";}); + rlr.checksum = cs.string (); + } } - } - if (rs.empty ()) - fail << "unable to guess " << ranlib << " signature"; + if (rlr.empty ()) + fail << "unable to guess " << rl << " signature"; + } - return r; + return bin_info { + move (arr.id), move (arr.signature), move (arr.checksum), + move (rlr.id), move (rlr.signature), move (rlr.checksum)}; } } } diff --git a/build2/bin/module.cxx b/build2/bin/module.cxx index 866bab2..edb3c53 100644 --- a/build2/bin/module.cxx +++ b/build2/bin/module.cxx @@ -185,22 +185,26 @@ namespace build2 //@@ Print project out root or name? See cxx. text << ar << ":\n" + << " id " << bi.ar_id << "\n" << " signature " << bi.ar_signature << "\n" << " checksum " << bi.ar_checksum; if (!ranlib.empty ()) { text << ranlib << ":\n" + << " id " << bi.ranlib_id << "\n" << " signature " << bi.ranlib_signature << "\n" << " checksum " << bi.ranlib_checksum; } } + r.assign ("bin.ar.id") = move (bi.ar_id); r.assign ("bin.ar.signature") = move (bi.ar_signature); r.assign ("bin.ar.checksum") = move (bi.ar_checksum); if (!ranlib.empty ()) { + r.assign ("bin.ranlib.id") = move (bi.ranlib_id); r.assign ("bin.ranlib.signature") = move (bi.ranlib_signature); r.assign ("bin.ranlib.checksum") = move (bi.ranlib_checksum); -- cgit v1.1