From ad4120afce8c7bc4001fc0173a0ff7611ec0198d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 12 Dec 2015 13:46:07 +0200 Subject: Implement installation of prerequisite shared libraries --- build/cxx/install | 2 +- build/cxx/install.cxx | 34 ++++++++++++++++------ build/cxx/link | 22 ++++++++++++++ build/cxx/link.cxx | 80 ++++++++++++++++++++++++--------------------------- 4 files changed, 86 insertions(+), 52 deletions(-) (limited to 'build/cxx') diff --git a/build/cxx/install b/build/cxx/install index 7117fb8..9df8408 100644 --- a/build/cxx/install +++ b/build/cxx/install @@ -15,7 +15,7 @@ namespace build class install: public build::install::file_rule { public: - virtual bool + virtual target* filter (action, target&, prerequisite_member) const; virtual match_result diff --git a/build/cxx/install.cxx b/build/cxx/install.cxx index e6417a6..f8c2c06 100644 --- a/build/cxx/install.cxx +++ b/build/cxx/install.cxx @@ -17,16 +17,35 @@ namespace build { using namespace bin; - bool install:: - filter (action, target& t, prerequisite_member p) const + target* install:: + filter (action a, target& t, prerequisite_member p) const { - // Don't install executable's prerequisite headers. + if (t.is_a ()) + { + // Don't install executable's prerequisite headers. + // + if (p.is_a () || p.is_a () || p.is_a () || p.is_a ()) + return nullptr; + } + + // If this is a shared library prerequisite, install it as long as it + // is in the same amalgamation as we are. // - if (t.is_a () && - (p.is_a () || p.is_a () || p.is_a () || p.is_a ())) - return false; + if ((t.is_a () || t.is_a ()) && + (p.is_a () || p.is_a ())) + { + target* pt (&p.search ()); + + // If this is the lib{} group, pick a member which we would link. + // + if (lib* l = pt->is_a ()) + pt = &link::link_member (*l, link::link_order (t)); - return true; + if (pt->is_a ()) // Can be liba{}. + return pt->in (t.weak_scope ()) ? pt : nullptr; + } + + return file_rule::filter (a, t, p); } match_result install:: @@ -39,7 +58,6 @@ namespace build // ones building this target. So first run link's match(). // match_result r (link::instance.match (a, t, hint)); - return r ? install::file_rule::match (a, t, "") : r; } diff --git a/build/cxx/link b/build/cxx/link index 5d3d29e..5a5aafa 100644 --- a/build/cxx/link +++ b/build/cxx/link @@ -12,6 +12,8 @@ #include #include +#include + namespace build { namespace cxx @@ -30,6 +32,26 @@ namespace build static link instance; + public: + enum class type {e, a, so}; + enum class order {a, so, a_so, so_a}; + + static type + link_type (target& t) + { + return t.is_a () + ? type::e + : (t.is_a () ? type::a : type::so); + } + + static order + link_order (target&); + + // Determine the library member (liba or libso) to link. + // + static target& + link_member (bin::lib&, order); + private: friend class compile; diff --git a/build/cxx/link.cxx b/build/cxx/link.cxx index f5a2e3d..9296035 100644 --- a/build/cxx/link.cxx +++ b/build/cxx/link.cxx @@ -38,16 +38,7 @@ namespace build { using namespace bin; - enum class type {e, a, so}; - enum class order {a, so, a_so, so_a}; - - static inline type - link_type (target& t) - { - return t.is_a () ? type::e : (t.is_a () ? type::a : type::so); - } - - static order + link::order link:: link_order (target& t) { const char* var; @@ -65,6 +56,40 @@ namespace build : v.size () > 1 && v[1] == "shared" ? order::a_so : order::a; } + target& link:: + link_member (bin::lib& l, order lo) + { + bool lso (true); + const string& at (as (*l["bin.lib"])); // Available types. + + switch (lo) + { + case order::a: + case order::a_so: + lso = false; // Fall through. + case order::so: + case order::so_a: + { + if (lso ? at == "static" : at == "shared") + { + if (lo == order::a_so || lo == order::so_a) + lso = !lso; + else + fail << (lso ? "shared" : "static") << " build of " << l + << " is not available"; + } + } + } + + target* r (lso ? static_cast (l.so) : l.a); + + if (r == nullptr) + r = &search (lso ? libso::static_type : liba::static_type, + prerequisite_key {nullptr, l.key (), nullptr}); + + return *r; + } + link::search_paths link:: extract_library_paths (scope& bs) { @@ -455,7 +480,7 @@ namespace build type lt (link_type (t)); bool so (lt == type::so); - optional lo; // Link-order. + order lo (link_order (t)); // Derive file name from target name. // @@ -541,38 +566,7 @@ namespace build } else if (lib* l = pt->is_a ()) { - // Determine the library type to link. - // - bool lso (true); - const string& at (as (*(*l)["bin.lib"])); - - if (!lo) - lo = link_order (t); - - switch (*lo) - { - case order::a: - case order::a_so: - lso = false; // Fall through. - case order::so: - case order::so_a: - { - if (lso ? at == "static" : at == "shared") - { - if (*lo == order::a_so || *lo == order::so_a) - lso = !lso; - else - fail << (lso ? "shared" : "static") << " build of " << *l - << " is not available"; - } - } - } - - pt = lso ? static_cast (l->so) : l->a; - - if (pt == nullptr) - pt = &search (lso ? libso::static_type : liba::static_type, - p.key ()); + pt = &link_member (*l, lo); } build::match (a, *pt); -- cgit v1.1