From 80f55f5857d340c31fcd951f645d3f337ed66a6b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 9 Jul 2016 11:26:28 +0200 Subject: Add config.bin.pattern, pass it as hint from cxx module With this change we normally no longer need to specify config.bin.ar explicitly when cross-compiling or set it to lib.exe for VC. --- build2/cxx/module.cxx | 87 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 13 deletions(-) (limited to 'build2/cxx') diff --git a/build2/cxx/module.cxx b/build2/cxx/module.cxx index aa60be9..28892cf 100644 --- a/build2/cxx/module.cxx +++ b/build2/cxx/module.cxx @@ -101,6 +101,12 @@ namespace build2 b.assign ("cxx.libs") += cast_null ( config::optional (r, "config.cxx.libs")); + // Configuration hints for the bin module. They will only be used on the + // first loading of the bin module (for this project) so we only + // populate them on our first loading. + // + variable_map bin_hints; + // config.cxx // if (first) @@ -145,6 +151,65 @@ namespace build2 r.assign ("cxx.signature") = move (ci.signature); r.assign ("cxx.checksum") = move (ci.checksum); + // While we still have the original, compiler-reported target, see if + // we can derive a binutils program pattern. + // + // BTW, for GCC we also get gcc-{ar,ranlib} which add support for the + // LTO plugin though it seems more recent GNU binutils (2.25) are able + // to load the plugin when needed automatically. So it doesn't seem we + // should bother trying to support this on our end (the way we could + // do it is by passing config.bin.{ar,ranlib} as hints). + // + string pattern; + + if (cast (r["cxx.id"]) == "msvc") + { + // If the compiler name is/starts with 'cl' (e.g., cl.exe, cl-14), + // then replace it with '*' and use it as a pattern for lib, link, + // etc. + // + if (cxx.size () > 2) + { + const string& l (cxx.leaf ().string ()); + size_t n (l.size ()); + + if (n >= 2 && + (l[0] == 'c' || l[0] == 'C') && + (l[1] == 'l' || l[1] == 'L') && + (n == 2 || l[2] == '.' || l[2] == '-')) + { + path p (cxx.directory ()); + p /= "*"; + p += l.c_str () + 2; + pattern = move (p).string (); + } + } + } + else + { + // When cross-compiling the whole toolchain is normally prefixed + // with the target triplet, e.g., x86_64-w64-mingw32-{g++,ar,ld}. + // + const string& t (ci.target); + size_t n (t.size ()); + + if (cxx.size () > n + 1) + { + const string& l (cxx.leaf ().string ()); + + if (l.size () > n + 1 && l.compare (0, n, t) == 0 && l[n] == '-') + { + path p (cxx.directory ()); + p /= t; + p += "-*"; + pattern = move (p).string (); + } + } + } + + if (!pattern.empty ()) + bin_hints.assign ("config.bin.pattern") = move (pattern); + // Split/canonicalize the target. // @@ -166,6 +231,11 @@ namespace build2 l5 ([&]{trace << "canonical target: '" << canon << "'; " << "class: " << t.class_;}); + // Pass the target we extracted from the C++ compiler as a config + // hint to the bin module. + // + bin_hints.assign ("config.bin.target") = canon; + // Enter as cxx.target.{cpu,vendor,system,version,class}. // r.assign ("cxx.target") = move (canon); @@ -189,28 +259,19 @@ namespace build2 // Initialize the bin module. Only do this if it hasn't already been // loaded so that we don't overwrite user's bin.* settings. // - const string& target (cast (r["cxx.target"])); - if (!cast_false (b["bin.loaded"])) - { - // Pass the target we extracted from the C++ compiler as a config hint - // to the bin module. - // - variable_map hints; - hints.assign ("config.bin.target") = target; - - load_module ("bin", r, b, loc, false, hints); - } + load_module ("bin", r, b, loc, false, bin_hints); // Verify bin's target matches ours. // { const string& bt (cast (r["bin.target"])); + const string& ct (cast (r["cxx.target"])); - if (bt != target) + if (bt != ct) fail (loc) << "bin and cxx module target platform mismatch" << info << "bin.target is " << bt << - info << "cxx.target is " << target; + info << "cxx.target is " << ct; } // Register target types. -- cgit v1.1