aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-16 09:43:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-16 10:51:49 +0200
commitaf73b1603d851dcb2ce7ae84bd57df0c2f9a716d (patch)
tree2c59bbf5ecdb2b5cec2f8f656ee3f7b13bc1b97b
parentecfae2da0b23631cee3e723a562f64f8aace6879 (diff)
Add $bin.link_member() function
Given a linker output target type ("exe", "lib[as]", or "libu[eas]") return the target type of lib{} group member ("liba" or "libs") that will be picked when linking a lib{} group to this target type.
-rw-r--r--libbuild2/bin/functions.cxx68
-rw-r--r--libbuild2/bin/init.cxx16
-rw-r--r--libbuild2/bin/utility.cxx27
-rw-r--r--libbuild2/bin/utility.hxx24
-rw-r--r--libbuild2/bin/utility.ixx35
-rw-r--r--libbuild2/install/functions.cxx2
6 files changed, 138 insertions, 34 deletions
diff --git a/libbuild2/bin/functions.cxx b/libbuild2/bin/functions.cxx
new file mode 100644
index 0000000..59fcdf2
--- /dev/null
+++ b/libbuild2/bin/functions.cxx
@@ -0,0 +1,68 @@
+// file : libbuild2/bin/functions.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <libbuild2/function.hxx>
+#include <libbuild2/variable.hxx>
+
+#include <libbuild2/bin/utility.hxx>
+
+namespace build2
+{
+ namespace bin
+ {
+ void
+ functions (function_map& m)
+ {
+ function_family f (m, "bin");
+
+ // Given a linker output target type ("exe", "lib[as]", or "libu[eas]")
+ // and a lib{} target group, return the type of library member ("liba"
+ // or "libs") that will be picked when linking this library group to
+ // this target type.
+ //
+ // The lib{} target is only used to resolve the scope to lookup the
+ // bin.lib value on. As a result, it can be omitted in which case the
+ // function call scope is used (covers project-local lib{} targets).
+ //
+ // @@ TODO: support for target (note that if it's out of project, then
+ // it's imported, which means it might still be qualified.)
+ //
+ // @@ TODO: support utility libraries (see link_member()).
+ //
+ f[".link_member"] = [] (const scope* bs, names ns)
+ {
+ string t (convert<string> (move (ns)));
+
+ if (bs == nullptr)
+ fail << "bin.link_member() called out of scope";
+
+ const scope* rs (bs->root_scope ());
+
+ if (rs == nullptr)
+ fail << "bin.link_member() called out of root scope";
+
+ const target_type* tt (bs->find_target_type (t));
+
+ if (tt == nullptr)
+ fail << "unknown target type '" << t << "'";
+
+ otype ot (link_type (*tt).type);
+
+ switch (ot)
+ {
+ case otype::e:
+ case otype::a:
+ case otype::s:
+ break;
+ default:
+ fail << "target type " << t << " is not linker output";
+ }
+
+ lorder lo (link_order (*bs, ot));
+ lmembers lm (link_members (*rs));
+
+ return link_member (lm, lo).first == otype::s ? "libs" : "liba";
+ };
+ }
+ }
+}
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index a1ac61e..0d2d9b5 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -6,6 +6,7 @@
#include <map>
#include <libbuild2/scope.hxx>
+#include <libbuild2/function.hxx>
#include <libbuild2/variable.hxx>
#include <libbuild2/diagnostics.hxx>
@@ -137,6 +138,9 @@ namespace build2
return true;
}
+ void
+ functions (function_map&); // functions.cxx
+
bool
config_init (scope& rs,
scope& bs,
@@ -153,6 +157,14 @@ namespace build2
if (rs != bs)
fail (loc) << "bin.config module must be loaded in project root";
+ context& ctx (rs.ctx);
+
+ // Register the bin function family if this is the first instance of the
+ // bin modules.
+ //
+ if (!function_family::defined (ctx.functions, "bin"))
+ functions (ctx.functions);
+
// Load bin.vars.
//
load_module (rs, rs, "bin.vars", loc);
@@ -267,7 +279,7 @@ namespace build2
// config.bin.target
//
{
- const variable& var (rs.ctx.var_pool["config.bin.target"]);
+ const variable& var (ctx.var_pool["config.bin.target"]);
// We first see if the value was specified via the configuration
// mechanism.
@@ -343,7 +355,7 @@ namespace build2
// config.bin.pattern
//
{
- const variable& var (rs.ctx.var_pool["config.bin.pattern"]);
+ const variable& var (ctx.var_pool["config.bin.pattern"]);
// We first see if the value was specified via the configuration
// mechanism.
diff --git a/libbuild2/bin/utility.cxx b/libbuild2/bin/utility.cxx
index 8032b79..6b0c4de 100644
--- a/libbuild2/bin/utility.cxx
+++ b/libbuild2/bin/utility.cxx
@@ -87,29 +87,14 @@ namespace build2
group_view gv (resolve_members (a, l));
assert (gv.members != nullptr);
- lorder lo (li.order);
+ pair<otype, bool> r (
+ link_member (lmembers {l.a != nullptr, l.s != nullptr}, li.order));
- bool ls (true);
- switch (lo)
- {
- case lorder::a:
- case lorder::a_s:
- ls = false; // Fall through.
- case lorder::s:
- case lorder::s_a:
- {
- if (ls ? l.s == nullptr : l.a == nullptr)
- {
- if (lo == lorder::a_s || lo == lorder::s_a)
- ls = !ls;
- else
- fail << (ls ? "shared" : "static") << " variant of " << l
- << " is not available";
- }
- }
- }
+ if (!r.second)
+ fail << (r.first == otype::s ? "shared" : "static")
+ << " variant of " << l << " is not available";
- return ls ? static_cast<const target*> (l.s) : l.a;
+ return r.first == otype::s ? static_cast<const target*> (l.s) : l.a;
}
}
diff --git a/libbuild2/bin/utility.hxx b/libbuild2/bin/utility.hxx
index 91b51f8..5d7eed4 100644
--- a/libbuild2/bin/utility.hxx
+++ b/libbuild2/bin/utility.hxx
@@ -19,10 +19,16 @@ namespace build2
// @@ Here we conflate the term "link" to mean both linker output and
// linking of a library.
- // Linker output type from binary (exe{}, lib*{}) target.
+ // Linker output type from a target (exe{}, lib*{}).
//
ltype
- link_type (const target&);
+ link_type (const target_type&);
+
+ inline ltype
+ link_type (const target& t)
+ {
+ return link_type (t.type ());
+ }
// Library group (lib{}) members to build according to the bin.lib value.
//
@@ -39,12 +45,12 @@ namespace build2
// directory have to have the same link order.
//
LIBBUILD2_BIN_SYMEXPORT lorder
- link_order (const scope& base, otype);
+ link_order (const scope& bs, otype);
inline linfo
- link_info (const scope& base, otype ot)
+ link_info (const scope& bs, otype ot)
{
- return linfo {ot, link_order (base, ot)};
+ return linfo {ot, link_order (bs, ot)};
}
// Given the link order return the library member to link. That is, liba{}
@@ -56,6 +62,14 @@ namespace build2
LIBBUILD2_BIN_SYMEXPORT const target*
link_member (const libx&, action, linfo, bool existing = false);
+ // As above but return otype::a or otype::s as well as an indication if
+ // the member is available.
+ //
+ // @@ TODO: support utility libraries (see above version).
+ //
+ pair<otype, bool>
+ link_member (lmembers, linfo);
+
// Lookup the bin.pattern value and split it into the pattern and the
// search paths.
//
diff --git a/libbuild2/bin/utility.ixx b/libbuild2/bin/utility.ixx
index 91c919b..65dffa8 100644
--- a/libbuild2/bin/utility.ixx
+++ b/libbuild2/bin/utility.ixx
@@ -6,16 +6,43 @@ namespace build2
namespace bin
{
inline ltype
- link_type (const target& t)
+ link_type (const target_type& tt)
{
bool u (false);
otype o (
- t.is_a<exe> () || (u = t.is_a<libue> ()) ? otype::e :
- t.is_a<liba> () || (u = t.is_a<libua> ()) ? otype::a :
- t.is_a<libs> () || (u = t.is_a<libus> ()) ? otype::s :
+ tt.is_a<exe> () || (u = tt.is_a<libue> ()) ? otype::e :
+ tt.is_a<liba> () || (u = tt.is_a<libua> ()) ? otype::a :
+ tt.is_a<libs> () || (u = tt.is_a<libus> ()) ? otype::s :
static_cast<otype> (0xFF));
return ltype {o, u};
}
+
+ inline pair<otype, bool>
+ link_member (lmembers lm, lorder lo)
+ {
+ bool r (true);
+
+ bool s (true);
+ switch (lo)
+ {
+ case lorder::a:
+ case lorder::a_s:
+ s = false; // Fall through.
+ case lorder::s:
+ case lorder::s_a:
+ {
+ if (s ? !lm.s : !lm.a)
+ {
+ if (lo == lorder::a_s || lo == lorder::s_a)
+ s = !s;
+ else
+ r = false; // Not available.
+ }
+ }
+ }
+
+ return make_pair (s ? otype::s : otype::a, r);
+ }
}
}
diff --git a/libbuild2/install/functions.cxx b/libbuild2/install/functions.cxx
index d8b07a4..c780061 100644
--- a/libbuild2/install/functions.cxx
+++ b/libbuild2/install/functions.cxx
@@ -6,8 +6,6 @@
#include <libbuild2/install/utility.hxx>
-using namespace std;
-
namespace build2
{
namespace install