aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-12-01 10:01:24 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-12-01 10:01:24 +0200
commitaf55babfc0c01abbd0a074b0d2ed86598d6bf628 (patch)
tree51d02bae14667636cd50dbf5b1e9bfe36dce8985
parentf8de93520fd604a3771a2af3ca9564f6085d8baa (diff)
Fix corner case in distributing via obj{}, libul{} groups
-rw-r--r--libbuild2/bin/init.cxx12
-rw-r--r--libbuild2/bin/rule.cxx71
-rw-r--r--libbuild2/bin/rule.hxx14
-rw-r--r--libbuild2/bin/target.hxx8
4 files changed, 102 insertions, 3 deletions
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index d7c5b5a..78119cb 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -605,6 +605,18 @@ namespace build2
if (rs.find_module ("dist"))
{
+ // Note that without custom dist rules in setups along the follwing
+ // lines the source file will be unreachable by dist:
+ //
+ // lib{foo}: obj{foo}
+ // obja{foo}: cxx{foo}
+ // objs{foo}: cxx{foo}
+ //
+ r.insert<obj> (dist_id, 0, "bin.obj", obj_);
+ r.insert<bmi> (dist_id, 0, "bin.bmi", obj_);
+ r.insert<hbmi> (dist_id, 0, "bin.hbmi", obj_);
+ r.insert<libul> (dist_id, 0, "bin.libul", libul_);
+
r.insert<lib> (dist_id, 0, "bin.lib", lib_);
}
}
diff --git a/libbuild2/bin/rule.cxx b/libbuild2/bin/rule.cxx
index 27c9b4b..c7147bf 100644
--- a/libbuild2/bin/rule.cxx
+++ b/libbuild2/bin/rule.cxx
@@ -17,11 +17,29 @@ namespace build2
{
namespace bin
{
+ // Search for an existing (declared real) member and match it if found.
+ //
+ static void
+ dist_match (action a, target& t, const target_type& tt)
+ {
+ if (const target* m = search_existing (t.ctx, tt, t.dir, t.out, t.name))
+ {
+ // Only a real target declaration can have prerequisites (which is
+ // the reason we are doing this).
+ //
+ if (m->decl == target_decl::real)
+ match_sync (a, *m);
+ }
+ }
+
// obj_rule
//
bool obj_rule::
match (action a, target& t) const
{
+ if (a.meta_operation () == dist_id)
+ return true;
+
const char* n (t.dynamic_type->name); // Ignore derived type.
fail << diag_doing (a, t) << " target group" <<
@@ -30,7 +48,43 @@ namespace build2
}
recipe obj_rule::
- apply (action, target&) const {return empty_recipe;}
+ apply (action a, target& t) const
+ {
+ // We only get here for dist.
+ //
+ const target_type* ett (nullptr);
+ const target_type* att (nullptr);
+ const target_type* stt (nullptr);
+
+ if (t.is_a<obj> ())
+ {
+ ett = &obje::static_type;
+ att = &obja::static_type;
+ stt = &objs::static_type;
+ }
+ else if (t.is_a<bmi> ())
+ {
+ ett = &bmie::static_type;
+ att = &bmia::static_type;
+ stt = &bmis::static_type;
+ }
+ else if (t.is_a<hbmi> ())
+ {
+ ett = &hbmie::static_type;
+ att = &hbmia::static_type;
+ stt = &hbmis::static_type;
+ }
+ else
+ assert (false);
+
+ dist_match (a, t, *ett);
+ dist_match (a, t, *att);
+ dist_match (a, t, *stt);
+
+ // Delegate to the default dist rule to match prerequisites.
+ //
+ return dist::rule::apply (a, t);
+ }
// libul_rule
//
@@ -43,6 +97,16 @@ namespace build2
recipe libul_rule::
apply (action a, target& t) const
{
+ if (a.meta_operation () == dist_id)
+ {
+ dist_match (a, t, libua::static_type);
+ dist_match (a, t, libus::static_type);
+
+ // Delegate to the default dist rule to match prerequisites.
+ //
+ return dist::rule::apply (a, t);
+ }
+
// Pick one of the members. First looking for the one already matched.
//
const target* m (nullptr);
@@ -113,6 +177,11 @@ namespace build2
// The whole logic is pretty much as if we had our two group members as
// our prerequisites.
//
+ // Note also that unlike the obj and libul rules above, we don't need to
+ // delegate to the default dist rule since any group prerequisites will be
+ // matched by one of the members (the key difference here is that unlike
+ // those rules, we insert and match members unconditionally).
+ //
bool lib_rule::
match (action a, target& xt) const
{
diff --git a/libbuild2/bin/rule.hxx b/libbuild2/bin/rule.hxx
index b403433..9dd1d14 100644
--- a/libbuild2/bin/rule.hxx
+++ b/libbuild2/bin/rule.hxx
@@ -9,6 +9,8 @@
#include <libbuild2/rule.hxx>
+#include <libbuild2/dist/rule.hxx>
+
#include <libbuild2/bin/export.hxx>
namespace build2
@@ -18,7 +20,10 @@ namespace build2
// "Fail rule" for obj{} and [h]bmi{} that issues diagnostics if someone
// tries to build these groups directly.
//
- class obj_rule: public simple_rule
+ // Note that for dist it acts as a pass-through to all existing (declared)
+ // members.
+ //
+ class obj_rule: public dist::rule
{
public:
obj_rule () {}
@@ -39,7 +44,10 @@ namespace build2
// falling back to making our own based on bin.lib and bin.exe.lib. Note
// that for update this rule always returns target_state::unchanged.
//
- class libul_rule: public simple_rule
+ // Note also that for dist it acts as a pass-through to all existing
+ // (declared) members.
+ //
+ class libul_rule: public dist::rule
{
public:
explicit
@@ -54,6 +62,8 @@ namespace build2
// Pass-through to group members rule, similar to alias.
//
+ // Note that for dist it always passes to both members.
+ //
class LIBBUILD2_BIN_SYMEXPORT lib_rule: public simple_rule
{
public:
diff --git a/libbuild2/bin/target.hxx b/libbuild2/bin/target.hxx
index 3ecabce..9685e39 100644
--- a/libbuild2/bin/target.hxx
+++ b/libbuild2/bin/target.hxx
@@ -71,6 +71,8 @@ namespace build2
static const target_type static_type;
};
+ // Note: this is a "choice" target group.
+ //
class LIBBUILD2_BIN_SYMEXPORT obj: public target
{
public:
@@ -219,6 +221,8 @@ namespace build2
static const target_type static_type;
};
+ // Note: this is a "choice" target group (similar to obj{}).
+ //
class LIBBUILD2_BIN_SYMEXPORT bmi: public target
{
public:
@@ -232,6 +236,8 @@ namespace build2
static const target_type static_type;
};
+ // Note: this is a "choice" target group (similar to bmi{} and obj{}).
+ //
class LIBBUILD2_BIN_SYMEXPORT hbmi: public target
{
public:
@@ -340,6 +346,8 @@ namespace build2
static const target_type static_type;
};
+ // Note: this is a "choice" target group.
+ //
// @@ Ideally this shouldn't derive from mtime_target (via libx). Maybe
// get rid of libx?
//