aboutsummaryrefslogtreecommitdiff
path: root/build2/bin/guess.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-05-20 23:25:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-06-11 19:06:40 +0200
commit4218bfe7668d55e36814d6bdcec2da40454025c1 (patch)
tree1abe3f38109ba83755adf7307414dbbd1e1a9eb8 /build2/bin/guess.cxx
parent9f56941794837ec63b8732d8d0cae4659528e714 (diff)
Initial VC++ support (static libraries only)
Diffstat (limited to 'build2/bin/guess.cxx')
-rw-r--r--build2/bin/guess.cxx174
1 files changed, 97 insertions, 77 deletions
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<string> (ar, "--version", f, false, false, &cs);
+ arr = run<guess_result> (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<string> (ar, f, false, true, &cs);
+ arr = run<guess_result> (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<string> (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<guess_result> (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<string> (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<guess_result> (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)};
}
}
}