aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/cc/install-rule.cxx16
-rw-r--r--libbuild2/install/rule.cxx119
-rw-r--r--libbuild2/install/rule.hxx17
3 files changed, 127 insertions, 25 deletions
diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx
index 0a5fb57..d3fa522 100644
--- a/libbuild2/cc/install-rule.cxx
+++ b/libbuild2/cc/install-rule.cxx
@@ -680,7 +680,8 @@ namespace build2
}
}
- return alias_rule::apply (a, t, me);
+ return alias_rule::apply_impl (
+ a, t, me, me.cur_options != match_extra::all_options /* reapply */);
}
void libux_install_rule::
@@ -692,11 +693,8 @@ namespace build2
<< ' ' << me.cur_options
<< ' ' << me.new_options; // @@ TMP
- // If we are rematched with the buildtime option, propagate it to our
- // prerequisite libraries.
- //
- // @@ Also libux?
- //
+ me.cur_options |= me.new_options;
+
if ((me.new_options & lib::option_install_buildtime) != 0)
{
for (const target* pt: t.prerequisite_targets[a])
@@ -705,11 +703,9 @@ namespace build2
pt->is_a<libua> () || pt->is_a<libus> ()))
rematch_sync (a, *pt, match_extra::all_options);
}
- }
-
- // @@ TODO: match additional prerequisites if required.
- me.cur_options |= me.new_options;
+ alias_rule::reapply_impl (a, t, me);
+ }
}
}
}
diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx
index 63d58a7..29888ae 100644
--- a/libbuild2/install/rule.cxx
+++ b/libbuild2/install/rule.cxx
@@ -93,8 +93,23 @@ namespace build2
recipe alias_rule::
apply (action a, target& t, match_extra& me) const
{
+ return apply_impl (a, t, me);
+ }
+
+ recipe alias_rule::
+ apply (action, target&) const
+ {
+ assert (false); // Never called.
+ return nullptr;
+ }
+
+ recipe alias_rule::
+ apply_impl (action a, target& t, match_extra& me, bool reapply) const
+ {
tracer trace ("install::alias_rule::apply");
+ assert (!reapply || a.operation () != update_id);
+
// Pass-through to our installable prerequisites.
//
// @@ Shouldn't we do match in parallel (here and below)?
@@ -105,6 +120,8 @@ namespace build2
auto pms (group_prerequisite_members (a, t, members_mode::never));
for (auto i (pms.begin ()), e (pms.end ()); i != e; ++i)
{
+ // NOTE: see essentially the same logic in reapply_impl() below.
+ //
const prerequisite& p (i->prerequisite);
// Ignore excluded.
@@ -131,12 +148,14 @@ namespace build2
pair<const target*, uint64_t> fr (filter (*is, a, t, i, me));
const target* pt (fr.first);
+ uint64_t options (fr.second);
+
+ lookup l;
+
if (pt == nullptr)
{
l5 ([&]{trace << "ignoring " << p << " (filtered out)";});
- continue;
}
-
// Check if this prerequisite is explicitly "not installable", that
// is, there is the 'install' variable and its value is false.
//
@@ -148,38 +167,108 @@ namespace build2
//
// Note: not the same as lookup_install() above.
//
- auto l ((*pt)[var_install (*p.scope.root_scope ())]);
- if (l && cast<path> (l).string () == "false")
+ else if ((l = (*pt)[var_install (*p.scope.root_scope ())]) &&
+ cast<path> (l).string () == "false")
{
l5 ([&]{trace << "ignoring " << *pt << " (not installable)";});
- continue;
+ pt = nullptr;
}
-
- uint64_t options (fr.second);
-
// If this is not a file-based target (e.g., a target group such as
// libu{}) then ignore it if there is no rule to install.
//
- if (pt->is_a<file> ())
+ else if (pt->is_a<file> ())
+ {
match_sync (a, *pt, options);
+ }
else if (!try_match_sync (a, *pt, options).first)
{
l5 ([&]{trace << "ignoring " << *pt << " (no rule)";});
pt = nullptr;
}
- if (pt != nullptr)
- pts.push_back (prerequisite_target (pt, pi));
+ if (pt != nullptr || reapply)
+ {
+ // Use auxiliary data for a NULL entry to distinguish between
+ // filtered out (1) and ignored for other reasons (0).
+ //
+ pts.push_back (
+ prerequisite_target (pt, pi, fr.first == nullptr ? 1 : 0));
+ }
}
return default_recipe;
}
- recipe alias_rule::
- apply (action, target&) const
+ void alias_rule::
+ reapply_impl (action a, target& t, match_extra& me) const
{
- assert (false); // Never called.
- return nullptr;
+ tracer trace ("install::alias_rule::reapply");
+
+ assert (a.operation () != update_id);
+
+ optional<const scope*> is;
+
+ // Iterate over prerequisites and prerequisite targets in parallel.
+ //
+ auto& pts (t.prerequisite_targets[a]);
+ size_t j (0), n (pts.size ()), en (0);
+
+ auto pms (group_prerequisite_members (a, t, members_mode::never));
+ for (auto i (pms.begin ()), e (pms.end ());
+ i != e && j != n;
+ ++i, ++j, ++en)
+ {
+ // The same logic as in apply() above except that we skip
+ // prerequisites that were not filtered out.
+ //
+ const prerequisite& p (i->prerequisite);
+
+ include_type pi (include (a, t, p));
+ if (!pi)
+ continue;
+
+ if (p.proj)
+ continue;
+
+ prerequisite_target& pto (pts[j]);
+
+ if (pto.target != nullptr || pto.data == 0)
+ continue;
+
+ if (!is)
+ is = a.operation () != update_id ? install_scope (t) : nullptr;
+
+ pair<const target*, uint64_t> fr (filter (*is, a, t, i, me));
+
+ const target* pt (fr.first);
+ uint64_t options (fr.second);
+
+ lookup l;
+
+ if (pt == nullptr)
+ {
+ l5 ([&]{trace << "ignoring " << p << " (filtered out)";});
+ }
+ else if ((l = (*pt)[var_install (*p.scope.root_scope ())]) &&
+ cast<path> (l).string () == "false")
+ {
+ l5 ([&]{trace << "ignoring " << *pt << " (not installable)";});
+ pt = nullptr;
+ }
+ else if (pt->is_a<file> ())
+ {
+ match_sync (a, *pt, options);
+ }
+ else if (!try_match_sync (a, *pt, options).first)
+ {
+ l5 ([&]{trace << "ignoring " << *pt << " (no rule)";});
+ pt = nullptr;
+ }
+
+ pto = prerequisite_target (pt, pi, fr.first == nullptr ? 1 : 0);
+ }
+
+ assert (en == n); // Did not call apply() with true for reapply?
}
// group_rule
diff --git a/libbuild2/install/rule.hxx b/libbuild2/install/rule.hxx
index 04ac9a7..b023af5 100644
--- a/libbuild2/install/rule.hxx
+++ b/libbuild2/install/rule.hxx
@@ -56,6 +56,23 @@ namespace build2
virtual recipe
apply (action, target&, match_extra&) const override;
+ // Implementation of apply().
+ //
+ // If the implementation may call reapply_impl(), then the reapply
+ // argument to apply_impl() must be true. Note that in this case, the
+ // *_impl() functions use the prerequisite_target::data member for own
+ // housekeeping.
+ //
+ recipe
+ apply_impl (action, target&, match_extra&, bool reapply = false) const;
+
+ // Implementation of reapply() that re-tries prerequisites that have
+ // been filtered out during the reapply() call. Note that currently not
+ // supported for update, only for install/uninstall.
+ //
+ void
+ reapply_impl (action, target&, match_extra&) const;
+
alias_rule () {}
static const alias_rule instance;