aboutsummaryrefslogtreecommitdiff
path: root/build/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-12-12 13:46:07 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-12-12 13:46:07 +0200
commitad4120afce8c7bc4001fc0173a0ff7611ec0198d (patch)
treeebbc31d03feda96560df437247b63206489a1139 /build/cxx
parentdd4a389117812f0d3b45473d87214d67d0cb4a3a (diff)
Implement installation of prerequisite shared libraries
Diffstat (limited to 'build/cxx')
-rw-r--r--build/cxx/install2
-rw-r--r--build/cxx/install.cxx34
-rw-r--r--build/cxx/link22
-rw-r--r--build/cxx/link.cxx80
4 files changed, 86 insertions, 52 deletions
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<exe> ())
+ {
+ // Don't install executable's prerequisite headers.
+ //
+ if (p.is_a<hxx> () || p.is_a<ixx> () || p.is_a<txx> () || p.is_a<h> ())
+ 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<exe> () &&
- (p.is_a<hxx> () || p.is_a<ixx> () || p.is_a<txx> () || p.is_a<h> ()))
- return false;
+ if ((t.is_a<exe> () || t.is_a<libso> ()) &&
+ (p.is_a<lib> () || p.is_a<libso> ()))
+ {
+ target* pt (&p.search ());
+
+ // If this is the lib{} group, pick a member which we would link.
+ //
+ if (lib* l = pt->is_a<lib> ())
+ pt = &link::link_member (*l, link::link_order (t));
- return true;
+ if (pt->is_a<libso> ()) // 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 <build/types>
#include <build/rule>
+#include <build/bin/target>
+
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<bin::exe> ()
+ ? type::e
+ : (t.is_a<bin::liba> () ? 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<exe> () ? type::e : (t.is_a<liba> () ? 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<string> (*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<target*> (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<order> 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<lib> ())
{
- // Determine the library type to link.
- //
- bool lso (true);
- const string& at (as<string> (*(*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<target*> (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);