aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/install
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/install')
-rw-r--r--libbuild2/install/rule.cxx164
-rw-r--r--libbuild2/install/rule.hxx96
2 files changed, 164 insertions, 96 deletions
diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx
index 4dd11e8..7e086a8 100644
--- a/libbuild2/install/rule.cxx
+++ b/libbuild2/install/rule.cxx
@@ -71,24 +71,27 @@ namespace build2
return true;
}
- const target* alias_rule::
+ pair<const target*, uint64_t> alias_rule::
filter (const scope* is,
- action a, const target& t, prerequisite_iterator& i) const
+ action a, const target& t, prerequisite_iterator& i,
+ match_extra& me) const
{
assert (i->member == nullptr);
- return filter (is, a, t, i->prerequisite);
+ return filter (is, a, t, i->prerequisite, me);
}
- const target* alias_rule::
+ pair<const target*, uint64_t> alias_rule::
filter (const scope* is,
- action, const target& t, const prerequisite& p) const
+ action, const target& t, const prerequisite& p,
+ match_extra&) const
{
const target& pt (search (t, p));
- return is == nullptr || pt.in (*is) ? &pt : nullptr;
+ return make_pair (is == nullptr || pt.in (*is) ? &pt : nullptr,
+ match_extra::all_options);
}
recipe alias_rule::
- apply (action a, target& t) const
+ apply (action a, target& t, match_extra& me) const
{
tracer trace ("install::alias_rule::apply");
@@ -125,7 +128,9 @@ namespace build2
if (!is)
is = a.operation () != update_id ? install_scope (t) : nullptr;
- const target* pt (filter (*is, a, t, i));
+ pair<const target*, uint64_t> fr (filter (*is, a, t, i, me));
+
+ const target* pt (fr.first);
if (pt == nullptr)
{
l5 ([&]{trace << "ignoring " << p << " (filtered out)";});
@@ -150,12 +155,14 @@ namespace build2
continue;
}
+ 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> ())
- match_sync (a, *pt);
- else if (!try_match_sync (a, *pt).first)
+ match_sync (a, *pt, options);
+ else if (!try_match_sync (a, *pt, options).first)
{
l5 ([&]{trace << "ignoring " << *pt << " (no rule)";});
pt = nullptr;
@@ -168,39 +175,11 @@ namespace build2
return default_recipe;
}
- // fsdir_rule
- //
- const fsdir_rule fsdir_rule::instance;
-
- bool fsdir_rule::
- match (action, target&) const
+ recipe alias_rule::
+ apply (action, target&) const
{
- // We always match.
- //
- // Note that we are called both as the outer part during the update-for-
- // un/install pre-operation and as the inner part during the un/install
- // operation itself.
- //
- return true;
- }
-
- recipe fsdir_rule::
- apply (action a, target& t) const
- {
- // If this is outer part of the update-for-un/install, delegate to the
- // default fsdir rule. Otherwise, this is a noop (we don't install
- // fsdir{}).
- //
- // For now we also assume we don't need to do anything for prerequisites
- // (the only sensible prerequisite of fsdir{} is another fsdir{}).
- //
- if (a.operation () == update_id)
- {
- match_inner (a, t);
- return inner_recipe;
- }
- else
- return noop_recipe;
+ assert (false); // Never called.
+ return nullptr;
}
// group_rule
@@ -220,10 +199,13 @@ namespace build2
return &m;
}
- const target* group_rule::
+ pair<const target*, uint64_t> group_rule::
filter (const scope* is,
- action, const target& t, const prerequisite& p) const
+ action, const target& t, const prerequisite& p,
+ match_extra&) const
{
+ pair<const target*, uint64_t> r (nullptr, match_extra::all_options);
+
// The same logic as in file_rule::filter() below.
//
if (p.is_a<exe> ())
@@ -232,15 +214,18 @@ namespace build2
if (p.vars.empty () ||
cast_empty<path> (p.vars[var_install (rs)]).string () != "true")
- return nullptr;
+ return r;
}
const target& pt (search (t, p));
- return is == nullptr || pt.in (*is) ? &pt : nullptr;
+ if (is == nullptr || pt.in (*is))
+ r.first = &pt;
+
+ return r;
}
recipe group_rule::
- apply (action a, target& t) const
+ apply (action a, target& t, match_extra& me) const
{
tracer trace ("install::group_rule::apply");
@@ -298,7 +283,7 @@ namespace build2
// Delegate to the base rule.
//
- return alias_rule::apply (a, t);
+ return alias_rule::apply (a, t, me);
}
@@ -315,18 +300,22 @@ namespace build2
return true;
}
- const target* file_rule::
+ pair<const target*, uint64_t> file_rule::
filter (const scope* is,
- action a, const target& t, prerequisite_iterator& i) const
+ action a, const target& t, prerequisite_iterator& i,
+ match_extra& me) const
{
assert (i->member == nullptr);
- return filter (is, a, t, i->prerequisite);
+ return filter (is, a, t, i->prerequisite, me);
}
- const target* file_rule::
+ pair<const target*, uint64_t> file_rule::
filter (const scope* is,
- action, const target& t, const prerequisite& p) const
+ action, const target& t, const prerequisite& p,
+ match_extra&) const
{
+ pair<const target*, uint64_t> r (nullptr, match_extra::all_options);
+
// See also group_rule::filter() with identical semantics.
//
if (p.is_a<exe> ())
@@ -340,22 +329,32 @@ namespace build2
//
if (p.vars.empty () ||
cast_empty<path> (p.vars[var_install (rs)]).string () != "true")
- return nullptr;
+ return r;
}
const target& pt (search (t, p));
- return is == nullptr || pt.in (*is) ? &pt : nullptr;
+ if (is == nullptr || pt.in (*is))
+ r.first = &pt;
+
+ return r;
}
recipe file_rule::
- apply (action a, target& t) const
+ apply (action a, target& t, match_extra& me) const
{
- recipe r (apply_impl (a, t));
+ recipe r (apply_impl (a, t, me));
return r != nullptr ? move (r) : noop_recipe;
}
recipe file_rule::
- apply_impl (action a, target& t) const
+ apply (action, target&) const
+ {
+ assert (false); // Never called.
+ return nullptr;
+ }
+
+ recipe file_rule::
+ apply_impl (action a, target& t, match_extra& me) const
{
tracer trace ("install::file_rule::apply");
@@ -438,8 +437,9 @@ namespace build2
if (!is)
is = a.operation () != update_id ? install_scope (t) : nullptr;
- const target* pt (filter (*is, a, t, i));
+ pair<const target*, uint64_t> fr (filter (*is, a, t, i, me));
+ const target* pt (fr.first);
if (pt == nullptr)
{
l5 ([&]{trace << "ignoring " << p << " (filtered out)";});
@@ -458,6 +458,8 @@ namespace build2
continue;
}
+ uint64_t options (fr.second);
+
if (pt->is_a<file> ())
{
// If the matched rule returned noop_recipe, then the target state
@@ -466,10 +468,15 @@ namespace build2
// when updating static installable content (headers, documentation,
// etc).
//
- if (match_sync (a, *pt, unmatch::unchanged).first)
+ // Regarding options, the expectation here is that they are not used
+ // for the update operation. And for install/uninstall, if they are
+ // used, then they don't effect whether the target is unchanged. All
+ // feels reasonable.
+ //
+ if (match_sync (a, *pt, unmatch::unchanged, options).first)
pt = nullptr;
}
- else if (!try_match_sync (a, *pt).first)
+ else if (!try_match_sync (a, *pt, options).first)
{
l5 ([&]{trace << "ignoring " << *pt << " (no rule)";});
pt = nullptr;
@@ -1566,5 +1573,40 @@ namespace build2
return r;
}
+
+ // fsdir_rule
+ //
+ const fsdir_rule fsdir_rule::instance;
+
+ bool fsdir_rule::
+ match (action, target&) const
+ {
+ // We always match.
+ //
+ // Note that we are called both as the outer part during the update-for-
+ // un/install pre-operation and as the inner part during the un/install
+ // operation itself.
+ //
+ return true;
+ }
+
+ recipe fsdir_rule::
+ apply (action a, target& t) const
+ {
+ // If this is outer part of the update-for-un/install, delegate to the
+ // default fsdir rule. Otherwise, this is a noop (we don't install
+ // fsdir{}).
+ //
+ // For now we also assume we don't need to do anything for prerequisites
+ // (the only sensible prerequisite of fsdir{} is another fsdir{}).
+ //
+ if (a.operation () == update_id)
+ {
+ match_inner (a, t);
+ return inner_recipe;
+ }
+ else
+ return noop_recipe;
+ }
}
}
diff --git a/libbuild2/install/rule.hxx b/libbuild2/install/rule.hxx
index b319071..3f30757 100644
--- a/libbuild2/install/rule.hxx
+++ b/libbuild2/install/rule.hxx
@@ -25,42 +25,43 @@ namespace build2
match (action, target&) const override;
// Return NULL if this prerequisite should be ignored and pointer to its
- // target otherwise.
+ // target otherwise. In the latter case, return the match options that
+ // should be used for this prerequisite (use match_extra::all_options
+ // and not 0 if no match options are needed).
//
// The default implementation ignores prerequsites that are outside of
// the installation scope (see install_scope() for details).
//
+ // The default implementation always returns match_extra::all_options.
+ // The match_extra argument is not used by the default implementation.
+ //
// The prerequisite is passed as an iterator allowing the filter to
// "see" inside groups.
//
using prerequisite_iterator =
prerequisite_members_range<group_prerequisites>::iterator;
- virtual const target*
+ virtual pair<const target*, uint64_t>
filter (const scope*,
- action, const target&, prerequisite_iterator&) const;
+ action, const target&, prerequisite_iterator&,
+ match_extra&) const;
- virtual const target*
- filter (const scope*, action, const target&, const prerequisite&) const;
+ virtual pair<const target*, uint64_t>
+ filter (const scope*,
+ action, const target&, const prerequisite&,
+ match_extra&) const;
+ // Note: rule::apply() override (with match_extra).
+ //
virtual recipe
- apply (action, target&) const override;
+ apply (action, target&, match_extra&) const override;
alias_rule () {}
static const alias_rule instance;
- };
-
- class fsdir_rule: public simple_rule
- {
- public:
- virtual bool
- match (action, target&) const override;
+ private:
virtual recipe
- apply (action, target&) const override;
-
- fsdir_rule () {}
- static const fsdir_rule instance;
+ apply (action, target&) const override; // Dummy simple_rule override.
};
// In addition to the alias rule's semantics, this rule sees through to
@@ -89,19 +90,17 @@ namespace build2
filter (action, const target&, const target& group_member) const;
// Return NULL if this prerequisite should be ignored and pointer to its
- // target otherwise.
- //
- // The same semantics as in file_rule below.
+ // target otherwise. The same semantics as in file_rule below.
//
- using alias_rule::filter; // "Unhide" to make Clang happy.
-
- virtual const target*
+ virtual pair<const target*, uint64_t>
filter (const scope*,
- action, const target&,
- const prerequisite&) const override;
+ action, const target&, const prerequisite&,
+ match_extra&) const override;
+
+ using alias_rule::filter; // "Unhide" to make Clang happy.
virtual recipe
- apply (action, target&) const override;
+ apply (action, target&, match_extra&) const override;
group_rule (bool sto): see_through_only (sto) {}
static const group_rule instance;
@@ -118,7 +117,9 @@ namespace build2
match (action, target&) const override;
// Return NULL if this prerequisite should be ignored and pointer to its
- // target otherwise.
+ // target otherwise. In the latter case, return the match options that
+ // should be used for this prerequisite (use match_extra::all_options
+ // and not 0 if no match options are needed).
//
// The default implementation ignores prerequsites that are outside of
// the installation scope (see install_scope() for details). It also
@@ -130,27 +131,35 @@ namespace build2
//
// exe{foo}: exe{bar}: install = true # foo runs bar
//
+ // The default implementation always returns match_extra::all_options.
+ // The match_extra argument is not used by the default implementation.
+ //
// The prerequisite is passed as an iterator allowing the filter to
// "see" inside groups.
//
using prerequisite_iterator =
prerequisite_members_range<group_prerequisites>::iterator;
- virtual const target*
+ virtual pair<const target*, uint64_t>
filter (const scope*,
- action, const target&, prerequisite_iterator&) const;
+ action, const target&, prerequisite_iterator&,
+ match_extra&) const;
- virtual const target*
- filter (const scope*, action, const target&, const prerequisite&) const;
+ virtual pair<const target*, uint64_t>
+ filter (const scope*,
+ action, const target&, const prerequisite&,
+ match_extra&) const;
+ // Note: rule::apply() override (with match_extra).
+ //
virtual recipe
- apply (action, target&) const override;
+ apply (action, target&, match_extra&) const override;
- // Implementation of apply() that returns empty_recipe if the target is
- // not installable.
+ // Implementation of apply() that returns empty_recipe (i.e., NULL) if
+ // the target is not installable.
//
recipe
- apply_impl (action, target&) const;
+ apply_impl (action, target&, match_extra&) const;
static target_state
perform_update (action, const target&);
@@ -288,6 +297,23 @@ namespace build2
static const file_rule instance;
file_rule () {}
+
+ private:
+ virtual recipe
+ apply (action, target&) const override; // Dummy simple_rule override.
+ };
+
+ class fsdir_rule: public simple_rule
+ {
+ public:
+ virtual bool
+ match (action, target&) const override;
+
+ virtual recipe
+ apply (action, target&) const override;
+
+ fsdir_rule () {}
+ static const fsdir_rule instance;
};
}
}