diff options
Diffstat (limited to 'libbuild2/install')
-rw-r--r-- | libbuild2/install/rule.cxx | 164 | ||||
-rw-r--r-- | libbuild2/install/rule.hxx | 96 |
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; }; } } |