From 152f83d22861129dba48404632b61b3f00f18715 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 27 Oct 2023 05:40:52 +0200 Subject: WIP: install: ad hoc members --- libbuild2/cc/install-rule.cxx | 83 ++++++++++++++++++++++++++----------------- libbuild2/cc/install-rule.hxx | 10 ++++-- libbuild2/install/rule.cxx | 43 +++++++++++++--------- libbuild2/install/rule.hxx | 15 ++++++-- 4 files changed, 96 insertions(+), 55 deletions(-) diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx index 4ed674a..fff3bdf 100644 --- a/libbuild2/cc/install-rule.cxx +++ b/libbuild2/cc/install-rule.cxx @@ -24,6 +24,41 @@ namespace build2 install_rule (data&& d, const link_rule& l) : common (move (d)), link_ (l) {} + // Wrap the file_rule's recipe into a data-carrying recipe. + // + struct install_match_data + { + build2::recipe recipe; + uint64_t options; // Match options. + link_rule::libs_paths libs_paths; + + target_state + operator() (action a, const target& t) + { + return recipe (a, t); + } + }; + + bool install_rule:: + filter (action a, const target& t, const target& m) const + { + if (!t.is_a ()) + { + // If runtime-only, filter out all known buildtime member types. + // + const auto& md (t.data (a)); + + if ((md.options & lib::option_install_buildtime) == 0) + { + if (m.is_a () || // pkg-config files. + m.is_a ()) // Import library. + return false; + } + } + + return true; + } + pair install_rule:: filter (const scope* is, action a, const target& t, prerequisite_iterator& i, @@ -205,21 +240,6 @@ namespace build2 file_rule::match (a, t); } - // Wrap the file_rule's recipe into a data-carrying recipe. - // - struct install_match_data - { - build2::recipe recipe; - uint64_t options; // Match options. - link_rule::libs_paths libs_paths; - - target_state - operator() (action a, const target& t) - { - return recipe (a, t); - } - }; - recipe install_rule:: apply (action a, target& t, match_extra& me) const { @@ -267,13 +287,15 @@ namespace build2 } else // install or uninstall { - // Derive shared library paths and cache them in the target's aux - // storage if we are un/installing (used in the *_extra() functions - // below). - // - if (file* f = t.is_a ()) + file* ls; + if ((ls = t.is_a ()) || t.is_a ()) { - if (!f->path ().empty ()) // Not binless. + // Derive shared library paths and cache them in the target's aux + // storage if we are un/installing (used in the *_extra() functions + // below). + // + link_rule::libs_paths lsp; + if (ls != nullptr && !ls->path ().empty ()) // Not binless. { // Note: we could omit deriving the paths if cur_options doesn't // have the buildtime option. But then we would have to duplicate @@ -283,13 +305,12 @@ namespace build2 const string* p (cast_null (t["bin.lib.prefix"])); const string* s (cast_null (t["bin.lib.suffix"])); - return install_match_data { - move (r), - me.cur_options, - link_.derive_libs_paths (*f, - p != nullptr ? p->c_str (): nullptr, - s != nullptr ? s->c_str (): nullptr)}; + lsp = link_.derive_libs_paths (*ls, + p != nullptr ? p->c_str (): nullptr, + s != nullptr ? s->c_str (): nullptr); } + + return install_match_data {move (r), me.cur_options, move (lsp)}; } } @@ -322,13 +343,9 @@ namespace build2 me.cur_options |= me.new_options; - // Update options in install_match_data. + // We also need to update options in install_match_data. // - if (file* f = t.is_a ()) - { - if (!f->path ().empty ()) // Not binless. - t.data (a).options = me.cur_options; - } + t.data (a).options = me.cur_options; } bool install_rule:: diff --git a/libbuild2/cc/install-rule.hxx b/libbuild2/cc/install-rule.hxx index 2427fda..9d9211b 100644 --- a/libbuild2/cc/install-rule.hxx +++ b/libbuild2/cc/install-rule.hxx @@ -36,6 +36,9 @@ namespace build2 public: install_rule (data&&, const link_rule&); + virtual bool + filter (action, const target&, const target&) const override; + virtual pair filter (const scope*, action, const target&, prerequisite_iterator&, @@ -70,13 +73,14 @@ namespace build2 // through them in case they depend on stuff that we need to install // (e.g., headers). Note that we use the alias_rule as a base. // - class LIBBUILD2_CC_SYMEXPORT libux_install_rule: - public install::alias_rule, - virtual common + class LIBBUILD2_CC_SYMEXPORT libux_install_rule: public install::alias_rule, + virtual common { public: libux_install_rule (data&&, const link_rule&); + // Note: utility libraries currently have no ad hoc members. + virtual pair filter (const scope*, action, const target&, prerequisite_iterator&, diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx index 7e086a8..788a13f 100644 --- a/libbuild2/install/rule.cxx +++ b/libbuild2/install/rule.cxx @@ -193,10 +193,10 @@ namespace build2 alias_rule::match (a, t); } - const target* group_rule:: - filter (action, const target&, const target& m) const + bool group_rule:: + filter (action, const target&, const target&) const { - return &m; + return true; } pair group_rule:: @@ -250,17 +250,16 @@ namespace build2 auto& pts (t.prerequisite_targets[a]); for (size_t i (0); i != gv.count; ++i) { - const target* m (gv.members[i]); + const target* mt (gv.members[i]); - if (m == nullptr) + if (mt == nullptr) continue; // Let a customized rule have its say. // - const target* mt (filter (a, t, *m)); - if (mt == nullptr) + if (!filter (a, t, *mt)) { - l5 ([&]{trace << "ignoring " << *m << " (filtered out)";}); + l5 ([&]{trace << "ignoring " << *mt << " (filtered out)";}); continue; } @@ -300,6 +299,12 @@ namespace build2 return true; } + bool file_rule:: + filter (action, const target&, const target&) const + { + return true; + } + pair file_rule:: filter (const scope* is, action a, const target& t, prerequisite_iterator& i, @@ -1177,10 +1182,13 @@ namespace build2 { if (!mf->path ().empty () && mf->mtime () != timestamp_nonexistent) { - if (const path* p = lookup_install (*mf, "install")) + if (filter (a, t, *mf)) { - install_target (*mf, *p, tp.empty () ? 1 : 2); - r |= target_state::changed; + if (const path* p = lookup_install (*mf, "install")) + { + install_target (*mf, *p, tp.empty () ? 1 : 2); + r |= target_state::changed; + } } } } @@ -1556,12 +1564,15 @@ namespace build2 { if (!mf->path ().empty () && mf->mtime () != timestamp_nonexistent) { - if (const path* p = lookup_install (*m, "install")) + if (filter (a, t, *mf)) { - r |= uninstall_target ( - *mf, - *p, - tp.empty () || r != target_state::changed ? 1 : 2); + if (const path* p = lookup_install (*m, "install")) + { + r |= uninstall_target ( + *mf, + *p, + tp.empty () || r != target_state::changed ? 1 : 2); + } } } } diff --git a/libbuild2/install/rule.hxx b/libbuild2/install/rule.hxx index 3f30757..2ddacc6 100644 --- a/libbuild2/install/rule.hxx +++ b/libbuild2/install/rule.hxx @@ -81,12 +81,12 @@ namespace build2 virtual bool match (action, target&) const override; - // Return NULL if this group member should be ignored and pointer to its - // target otherwise. + // Return false if this group member should be ignored and true + // otherwise. Note that this filter is called during apply(). // // The default implementation accepts all members. // - virtual const target* + virtual bool filter (action, const target&, const target& group_member) const; // Return NULL if this prerequisite should be ignored and pointer to its @@ -116,6 +116,15 @@ namespace build2 virtual bool match (action, target&) const override; + // Return false if this ad hoc group member should be ignored and true + // otherwise. Note that this filter is called during execute and only + // for install/uninstall (and not update). + // + // The default implementation accepts all members. + // + virtual bool + filter (action, const target&, const target& adhoc_group_member) const; + // Return NULL if this prerequisite should be ignored and pointer to its // target otherwise. In the latter case, return the match options that // should be used for this prerequisite (use match_extra::all_options -- cgit v1.1