diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-04-04 10:58:36 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2019-04-04 10:58:36 +0200 |
commit | 39a17ba7ef506192218f24047f129cb635efb02b (patch) | |
tree | 454ce4d2a11554a47c7f7dc6ecb4efe9d91199fc | |
parent | 6e126ac30038502acf7016f0e76b3183f1304042 (diff) |
Add ability to disable automatic rpath, support for custom rpath-link
Specifically, the new config.bin.rpath.auto variable can be used to disable
automatic addition of prerequisite library rpaths, for example:
$ b config.bin.rpath.auto=false
Note that in this case rpath-link is still added where normally required
and for targets that support it (Linux and *BSD).
The new config.bin.rpath_link and config.bin.rpath_link.auto have the same
semantics as config.bin.rpath* but for rpath-link.
-rw-r--r-- | build2/bin/init.cxx | 47 | ||||
-rw-r--r-- | build2/cc/link-rule.cxx | 57 |
2 files changed, 81 insertions, 23 deletions
diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx index 52197d2..f334769 100644 --- a/build2/bin/init.cxx +++ b/build2/bin/init.cxx @@ -61,11 +61,25 @@ namespace build2 vp.insert<string> ("config.bin.target", true); vp.insert<string> ("config.bin.pattern", true); + // Library types to build. + // vp.insert<string> ("config.bin.lib", true); + + // Library types to use (in priority order). + // vp.insert<strings> ("config.bin.exe.lib", true); vp.insert<strings> ("config.bin.liba.lib", true); vp.insert<strings> ("config.bin.libs.lib", true); - vp.insert<dir_paths> ("config.bin.rpath", true); + + // The rpath[_link].auto flag controls automatic rpath behavior, for + // example, addition of rpaths for prerequisite libraries (see the cc + // module for an example). Default is true. + // + vp.insert<dir_paths> ("config.bin.rpath", true); + vp.insert<bool> ("config.bin.rpath.auto", true); + + vp.insert<dir_paths> ("config.bin.rpath_link", true); + vp.insert<bool> ("config.bin.rpath_link.auto", true); vp.insert<string> ("config.bin.prefix", true); vp.insert<string> ("config.bin.suffix", true); @@ -75,10 +89,16 @@ namespace build2 vp.insert<string> ("config.bin.exe.suffix", true); vp.insert<string> ("bin.lib"); + vp.insert<strings> ("bin.exe.lib"); vp.insert<strings> ("bin.liba.lib"); vp.insert<strings> ("bin.libs.lib"); + vp.insert<dir_paths> ("bin.rpath"); + vp.insert<bool> ("bin.rpath.auto"); + + vp.insert<dir_paths> ("bin.rpath_link"); + vp.insert<bool> ("bin.rpath_link.auto"); // Link whole archive. Note: non-overridable with target visibility. // @@ -183,14 +203,33 @@ namespace build2 v = *required (rs, "config.bin.libs.lib", libs_lib).first; } - // config.bin.rpath + // config.bin.rpath[_link] // - // This one is optional and we merge it into bin.rpath, if any. - // See the cxx module for details on merging. + // These ones are optional and we merge them into bin.rpath[_link], if + // any. // rs.assign ("bin.rpath") += cast_null<dir_paths> ( optional (rs, "config.bin.rpath")); + rs.assign ("bin.rpath_link") += cast_null<dir_paths> ( + optional (rs, "config.bin.rpath_link")); + + // config.bin.rpath[_link].auto + // + { + lookup l; + + rs.assign ("bin.rpath.auto") = + (l = omitted (rs, "config.bin.rpath.auto").first) + ? cast<bool> (l) + : true; + + rs.assign ("bin.rpath_link.auto") = + (l = omitted (rs, "config.bin.rpath_link.auto").first) + ? cast<bool> (l) + : true; + } + // config.bin.{lib,exe}.{prefix,suffix} // // These ones are not used very often so we will omit them from the diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx index cffd731..ebfe452 100644 --- a/build2/cc/link-rule.cxx +++ b/build2/cc/link-rule.cxx @@ -1457,20 +1457,20 @@ namespace build2 const scope& bs, action a, linfo li, - bool for_install) const + bool link) const { - // Use -rpath-link on targets that support it (Linux, *BSD). Note + // Use -rpath-link only on targets that support it (Linux, *BSD). Note // that we don't really need it for top-level libraries. // - if (for_install) + if (link) { if (tclass != "linux" && tclass != "bsd") return; } - auto imp = [for_install] (const file& l, bool la) + auto imp = [link] (const file& l, bool la) { - // If we are not installing, then we only need to rpath interface + // If we are not rpath-link'ing, then we only need to rpath interface // libraries (they will include rpath's for their implementations) // Otherwise, we have to do this recursively. In both cases we also // want to see through utility libraries. @@ -1484,7 +1484,7 @@ namespace build2 // except for some noise on the command line. // // - return (for_install ? !la : false) || l.is_a<libux> (); + return (link ? !la : false) || l.is_a<libux> (); }; // Package the data to keep within the 2-pointer small std::function @@ -1493,8 +1493,8 @@ namespace build2 struct { strings& args; - bool for_install; - } d {args, for_install}; + bool link; + } d {args, link}; auto lib = [&d, this] (const file* const* lc, const string& f, @@ -1547,7 +1547,7 @@ namespace build2 // Ok, if we are here then it means we have a non-system, shared // library and its absolute path is in f. // - string o (d.for_install ? "-Wl,-rpath-link," : "-Wl,-rpath,"); + string o (d.link ? "-Wl,-rpath-link," : "-Wl,-rpath,"); size_t p (path::traits::rfind_separator (f)); assert (p != string::npos); @@ -1574,7 +1574,7 @@ namespace build2 (la = (f = pt->is_a<libux> ())) || ( f = pt->is_a<libs> ())) { - if (!for_install && !la) + if (!link && !la) { // Top-level shared library dependency. // @@ -1613,6 +1613,9 @@ namespace build2 const file& t (xt.as<file> ()); const path& tp (t.path ()); + const scope& bs (t.base_scope ()); + const scope& rs (*bs.root_scope ()); + match_data& md (t.data<match_data> ()); // Unless the outer install rule signalled that this is update for @@ -1623,9 +1626,6 @@ namespace build2 bool for_install (*md.for_install); - const scope& bs (t.base_scope ()); - const scope& rs (*bs.root_scope ()); - ltype lt (link_type (t)); otype ot (lt.type); linfo li (link_info (bs, ot)); @@ -1682,7 +1682,7 @@ namespace build2 // assembly itself is generated later, after updating the target. Omit // it if we are updating for install. // - if (!for_install) + if (!for_install && cast_true<bool> (t["bin.rpath.auto"])) rpath_timestamp = windows_rpath_timestamp (t, bs, a, li); auto p (windows_manifest (t, rpath_timestamp != timestamp_nonexistent)); @@ -1921,12 +1921,15 @@ namespace build2 if (tclass == "windows") { // Limited emulation for Windows with no support for user-defined - // rpaths. + // rpath/rpath-link. // - auto l (t["bin.rpath"]); + lookup l; - if (l && !l->empty ()) + if ((l = t["bin.rpath"]) && !l->empty ()) fail << ctgt << " does not support rpath"; + + if ((l = t["bin.rpath_link"]) && !l->empty ()) + fail << ctgt << " does not support rpath-link"; } else { @@ -1970,11 +1973,27 @@ namespace build2 // rpath of the imported libraries (i.e., we assume they are also // installed). But we add -rpath-link for some platforms. // - rpath_libraries (sargs, t, bs, a, li, for_install); + if (cast_true<bool> (t[for_install + ? "bin.rpath_link.auto" + : "bin.rpath.auto"])) + rpath_libraries (sargs, t, bs, a, li, for_install /* link */); - if (auto l = t["bin.rpath"]) + lookup l; + + if ((l = t["bin.rpath"]) && !l->empty ()) for (const dir_path& p: cast<dir_paths> (l)) sargs.push_back ("-Wl,-rpath," + p.string ()); + + if ((l = t["bin.rpath_link"]) && !l->empty ()) + { + // Only certain targets support -rpath-link (Linux, *BSD). + // + if (tclass != "linux" && tclass != "bsd") + fail << ctgt << " does not support rpath-link"; + + for (const dir_path& p: cast<dir_paths> (l)) + sargs.push_back ("-Wl,-rpath-link," + p.string ()); + } } } |