aboutsummaryrefslogtreecommitdiff
path: root/build2/install
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-02-05 12:02:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-02-05 12:02:32 +0200
commit1bb564a690e2661094e9071d4003638390a5a6fe (patch)
tree48ed8eedb1f87fd05eb66547c12349bb3db92c2b /build2/install
parent7005f1f5b525705fa3fd458a840d027046a2085b (diff)
Fix test and install rules to handle see-through groups correctly
Diffstat (limited to 'build2/install')
-rw-r--r--build2/install/init.cxx20
-rw-r--r--build2/install/rule.cxx61
-rw-r--r--build2/install/rule.hxx39
3 files changed, 96 insertions, 24 deletions
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<bool> ("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<alias> (perform_install_id, "install.alias", ar);
- bs.rules.insert<alias> (perform_uninstall_id, "uninstall.alias", ar);
+ r.insert<alias> (perform_install_id, "install.alias", ar);
+ r.insert<alias> (perform_uninstall_id, "uninstall.alias", ar);
- bs.rules.insert<file> (perform_install_id, "install.file", fr);
- bs.rules.insert<file> (perform_uninstall_id, "uninstall.file", fr);
- }
+ r.insert<file> (perform_install_id, "install.file", fr);
+ r.insert<file> (perform_uninstall_id, "uninstall.file", fr);
+
+ r.insert<target> (perform_install_id, "install.file", gr);
+ r.insert<target> (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<group_prerequisites>::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<group_prerequisites>::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;