From 1bb564a690e2661094e9071d4003638390a5a6fe Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Feb 2018 12:02:32 +0200 Subject: Fix test and install rules to handle see-through groups correctly --- build2/install/init.cxx | 20 +++++++++++----- build2/install/rule.cxx | 61 +++++++++++++++++++++++++++++++++++++------------ build2/install/rule.hxx | 39 +++++++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 24 deletions(-) (limited to 'build2/install') diff --git a/build2/install/init.cxx b/build2/install/init.cxx index a11f3e5..259fb07 100644 --- a/build2/install/init.cxx +++ b/build2/install/init.cxx @@ -165,6 +165,8 @@ namespace build2 static const dir_path dir_man (dir_path (dir_data) /= "man"); static const dir_path dir_man1 (dir_path ("man") /= "man1"); + static const group_rule group_rule_ (true /* see_through_only */); + bool init (scope& rs, scope& bs, @@ -207,18 +209,24 @@ namespace build2 vp.insert ("install.subdirs", variable_visibility::project); } - // Register our alias and file rules. + // Register our rules. // { + auto& r (bs.rules); + const auto& ar (alias_rule::instance); const auto& fr (file_rule::instance); + const auto& gr (group_rule_); - bs.rules.insert (perform_install_id, "install.alias", ar); - bs.rules.insert (perform_uninstall_id, "uninstall.alias", ar); + r.insert (perform_install_id, "install.alias", ar); + r.insert (perform_uninstall_id, "uninstall.alias", ar); - bs.rules.insert (perform_install_id, "install.file", fr); - bs.rules.insert (perform_uninstall_id, "uninstall.file", fr); - } + r.insert (perform_install_id, "install.file", fr); + r.insert (perform_uninstall_id, "uninstall.file", fr); + + r.insert (perform_install_id, "install.file", gr); + r.insert (perform_uninstall_id, "uninstall.file", gr); + } // Configuration. // diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index 4d4cb51..2b5d048 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -53,9 +53,16 @@ namespace build2 } const target* alias_rule:: - filter (action, const target& t, prerequisite_member p) const + filter (action a, const target& t, prerequisite_iterator& i) const { - return &p.search (t); + assert (i->target == nullptr); + return filter (a, t, i->prerequisite); + } + + const target* alias_rule:: + filter (action, const target& t, const prerequisite& p) const + { + return &search (t, p); } recipe alias_rule:: @@ -68,17 +75,24 @@ namespace build2 // @@ Shouldn't we do match in parallel (here and below)? // auto& pts (t.prerequisite_targets[a]); - for (prerequisite_member p: group_prerequisite_members (a, t)) + + auto pms (group_prerequisite_members (a, t, members_mode::never)); + for (auto i (pms.begin ()), e (pms.end ()); i != e; ++i) { + const prerequisite& p (i->prerequisite); + // Ignore unresolved targets that are imported from other projects. // We are definitely not installing those. // - if (p.proj ()) + if (p.proj) continue; // Let a customized rule have its say. // - const target* pt (filter (a, t, p)); + // Note: we assume that if the filter enters the group, then it + // iterates over all its members. + // + const target* pt (filter (a, t, i)); if (pt == nullptr) { l5 ([&]{trace << "ignoring " << p << " (filtered out)";}); @@ -112,7 +126,14 @@ namespace build2 // group_rule // - const group_rule group_rule::instance; + const group_rule group_rule::instance (false /* see_through_only */); + + bool group_rule:: + match (action a, target& t, const string& h) const + { + return (!see_through || t.type ().see_through) && + alias_rule::match (a, t, h); + } const target* group_rule:: filter (action, const target&, const target& m) const @@ -142,6 +163,7 @@ namespace build2 if (gv.members != nullptr) { auto& pts (t.prerequisite_targets[a]); + for (size_t i (0); i != gv.count; ++i) { const target* m (gv.members[i]); @@ -194,9 +216,16 @@ namespace build2 } const target* file_rule:: - filter (action, const target& t, prerequisite_member p) const + filter (action a, const target& t, prerequisite_iterator& i) const + { + assert (i->target == nullptr); + return filter (a, t, i->prerequisite); + } + + const target* file_rule:: + filter (action, const target& t, const prerequisite& p) const { - const target& pt (p.search (t)); + const target& pt (search (t, p)); return pt.in (t.root_scope ()) ? &pt : nullptr; } @@ -220,21 +249,25 @@ namespace build2 // In both cases, the next step is to search, match, and collect all the // installable prerequisites. // - // @@ Unconditional group? How does it work for cli? Change to maybe - // same like test? If so, also in alias_rule. - // auto& pts (t.prerequisite_targets[a]); - for (prerequisite_member p: group_prerequisite_members (a, t)) + + auto pms (group_prerequisite_members (a, t, members_mode::never)); + for (auto i (pms.begin ()), e (pms.end ()); i != e; ++i) { + const prerequisite& p (i->prerequisite); + // Ignore unresolved targets that are imported from other projects. // We are definitely not installing those. // - if (p.proj ()) + if (p.proj) continue; // Let a customized rule have its say. // - const target* pt (filter (a, t, p)); + // Note: we assume that if the filter enters the group, then it + // iterates over all its members. + // + const target* pt (filter (a, t, i)); if (pt == nullptr) { l5 ([&]{trace << "ignoring " << p << " (filtered out)";}); diff --git a/build2/install/rule.hxx b/build2/install/rule.hxx index b9699e3..2ad3d4b 100644 --- a/build2/install/rule.hxx +++ b/build2/install/rule.hxx @@ -25,8 +25,17 @@ namespace build2 // Return NULL if this prerequisite should be ignored and pointer to its // target otherwise. The default implementation accepts all prerequsites. // + // The prerequisite it passed as an iterator allowing the filter to + // "see" inside groups. + // + using prerequisite_iterator = + prerequisite_members_range::iterator; + + virtual const target* + filter (action, const target&, prerequisite_iterator&) const; + virtual const target* - filter (action, const target&, prerequisite_member) const; + filter (action, const target&, const prerequisite&) const; virtual recipe apply (action, target&) const override; @@ -38,10 +47,19 @@ namespace build2 // In addition to the alias rule's semantics, this rule sees through to // the group's members. // + // The default group_rule::instance matches any target for which it was + // registered. It is to be used for non-see-through groups that should + // exhibit the see-through behavior for install (see lib{} in the bin + // module for an example). + // + // We also register (for all targets) another instance of this rule that + // only matches see-through groups. + // class group_rule: public alias_rule { public: - using alias_rule::filter; // "Unhide" to make Clang happy. + virtual bool + match (action, target&, const string&) const override; // Return NULL if this group member should be ignored and pointer to its // target otherwise. The default implementation accepts all members. @@ -49,11 +67,15 @@ namespace build2 virtual const target* filter (action, const target&, const target& group_member) const; + using alias_rule::filter; // "Unhide" to make Clang happy. + virtual recipe apply (action, target&) const override; - group_rule () {} + group_rule (bool see_through_only): see_through (see_through_only) {} static const group_rule instance; + + bool see_through; }; struct install_dir; @@ -68,8 +90,17 @@ namespace build2 // target otherwise. The default implementation ignores prerequsites // that are outside of this target's project. // + // The prerequisite it passed as an iterator allowing the filter to + // "see" inside groups. + // + using prerequisite_iterator = + prerequisite_members_range::iterator; + + virtual const target* + filter (action, const target&, prerequisite_iterator&) const; + virtual const target* - filter (action, const target&, prerequisite_member) const; + filter (action, const target&, const prerequisite&) const; virtual recipe apply (action, target&) const override; -- cgit v1.1