diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-04-19 11:10:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-04-19 11:10:53 +0200 |
commit | 9034f7c51ef6437ce9d4547ba5bde217b4740fb2 (patch) | |
tree | bfaa297fda78b6cafe4487e2281420a4cf77c81a /libbuild2/cc | |
parent | 457f65414031f45174f3c35230a0c0e1de88b51a (diff) |
Use target recipe for auxiliary data storage during match-apply
In particular, we now have separate auxiliary data storage for inner
and outer operations.
Diffstat (limited to 'libbuild2/cc')
-rw-r--r-- | libbuild2/cc/compile-rule.cxx | 41 | ||||
-rw-r--r-- | libbuild2/cc/compile-rule.hxx | 5 | ||||
-rw-r--r-- | libbuild2/cc/install-rule.cxx | 26 | ||||
-rw-r--r-- | libbuild2/cc/link-rule.cxx | 29 | ||||
-rw-r--r-- | libbuild2/cc/link-rule.hxx | 26 |
5 files changed, 84 insertions, 43 deletions
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx index f680001..ada0cc6 100644 --- a/libbuild2/cc/compile-rule.cxx +++ b/libbuild2/cc/compile-rule.cxx @@ -229,10 +229,16 @@ namespace build2 return nullopt; } + // Note that we don't really need this for clean (where we only need + // unrefined unit type) so we could make this update-only. But let's keep + // it simple for now. + // struct compile_rule::match_data { - match_data (unit_type t, const prerequisite_member& s) - : type (t), src (s) {} + match_data (const compile_rule& r, + unit_type t, + const prerequisite_member& s) + : type (t), src (s), rule (r) {} unit_type type; preprocessed pp = preprocessed::none; @@ -245,6 +251,14 @@ namespace build2 path dd; // Dependency database path. size_t header_units = 0; // Number of imported header units. module_positions modules = {0, 0, 0}; // Positions of imported modules. + + const compile_rule& rule; + + target_state + operator() (action a, const target& t) + { + return rule.perform_update (a, t, *this); + } }; compile_rule:: @@ -464,7 +478,7 @@ namespace build2 { // Save in the target's auxiliary storage. // - t.data (match_data (ut, p)); + t.data (a, match_data (*this, ut, p)); return true; } } @@ -809,7 +823,7 @@ namespace build2 file& t (xt.as<file> ()); // Either obj*{} or bmi*{}. - match_data& md (t.data<match_data> ()); + match_data& md (t.data<match_data> (a)); context& ctx (t.ctx); @@ -1497,10 +1511,7 @@ namespace build2 switch (a) { - case perform_update_id: return [this] (action a, const target& t) - { - return perform_update (a, t); - }; + case perform_update_id: return move (md); case perform_clean_id: return [this] (action a, const target& t) { return perform_clean (a, t); @@ -5439,10 +5450,11 @@ namespace build2 // 1. There is no good place in prerequisite_targets to store the // exported flag (no, using the marking facility across match/execute // is a bad idea). So what we are going to do is put re-exported - // bmi{}s at the back and store (in the target's data pad) the start - // position. One bad aspect about this part is that we assume those - // bmi{}s have been matched by the same rule. But let's not kid - // ourselves, there will be no other rule that matches bmi{}s. + // bmi{}s at the back and store (in the target's auxiliary data + // storage) the start position. One bad aspect about this part is + // that we assume those bmi{}s have been matched by the same + // rule. But let's not kid ourselves, there will be no other rule + // that matches bmi{}s. // // @@ I think now we could use prerequisite_targets::data for this? // @@ -5833,7 +5845,7 @@ namespace build2 // Copy over bmi{}s from our prerequisites weeding out duplicates. // - if (size_t j = bt->data<match_data> ().modules.start) + if (size_t j = bt->data<match_data> (a).modules.start) { // Hard to say whether we should reserve or not. We will probably // get quite a bit of duplications. @@ -6578,12 +6590,11 @@ namespace build2 } target_state compile_rule:: - perform_update (action a, const target& xt) const + perform_update (action a, const target& xt, match_data& md) const { const file& t (xt.as<file> ()); const path& tp (t.path ()); - match_data md (move (t.data<match_data> ())); unit_type ut (md.type); context& ctx (t.ctx); diff --git a/libbuild2/cc/compile-rule.hxx b/libbuild2/cc/compile-rule.hxx index 16b33fa..49d33eb 100644 --- a/libbuild2/cc/compile-rule.hxx +++ b/libbuild2/cc/compile-rule.hxx @@ -44,6 +44,8 @@ namespace build2 dyndep_rule { public: + struct match_data; + compile_rule (data&&, const scope&); virtual bool @@ -53,7 +55,7 @@ namespace build2 apply (action, target&) const override; target_state - perform_update (action, const target&) const; + perform_update (action, const target&, match_data&) const; target_state perform_clean (action, const target&) const; @@ -74,7 +76,6 @@ namespace build2 functions (function_family&, const char*); // functions.cxx private: - struct match_data; using environment = small_vector<const char*, 2>; template <typename T> diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx index d83bf70..0b4d1e1 100644 --- a/libbuild2/cc/install-rule.cxx +++ b/libbuild2/cc/install-rule.cxx @@ -160,6 +160,20 @@ 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; + 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) const { @@ -173,7 +187,7 @@ namespace build2 // Signal to the link rule that this is update for install. And if the // update has already been executed, verify it was done for install. // - auto& md (t.data<link_rule::match_data> ()); + auto& md (t.data<link_rule::match_data> (a.inner_action ())); if (md.for_install) { @@ -198,10 +212,12 @@ namespace build2 { const string* p (cast_null<string> (t["bin.lib.prefix"])); const string* s (cast_null<string> (t["bin.lib.suffix"])); - t.data ( + + return install_match_data { + move (r), link_.derive_libs_paths (*f, p != nullptr ? p->c_str (): nullptr, - s != nullptr ? s->c_str (): nullptr)); + s != nullptr ? s->c_str (): nullptr)}; } } } @@ -219,7 +235,7 @@ namespace build2 // Here we may have a bunch of symlinks that we need to install. // const scope& rs (t.root_scope ()); - auto& lp (t.data<link_rule::libs_paths> ()); + auto& lp (t.data<install_match_data> (perform_install_id).libs_paths); auto ln = [&rs, &id] (const path& f, const path& l) { @@ -253,7 +269,7 @@ namespace build2 // Here we may have a bunch of symlinks that we need to uninstall. // const scope& rs (t.root_scope ()); - auto& lp (t.data<link_rule::libs_paths> ()); + auto& lp (t.data<install_match_data> (perform_uninstall_id).libs_paths); auto rm = [&rs, &id] (const path& l) { diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index f2e3775..de47822 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -875,8 +875,11 @@ namespace build2 // Note that for_install is signalled by install_rule and therefore // can only be relied upon during execute. // - t.data (match_data ()); - match_data& md (t.data<match_data> ()); + // Note that we don't really need to set it as target data: while there + // are calls to get it, they should only happen after the target has + // been matched. + // + match_data md (*this); const scope& bs (t.base_scope ()); const scope& rs (*bs.root_scope ()); @@ -2008,14 +2011,11 @@ namespace build2 switch (a) { - case perform_update_id: return [this] (action a, const target& t) - { - return perform_update (a, t); - }; - case perform_clean_id: return [this] (action a, const target& t) - { - return perform_clean (a, t); - }; + // Keep the recipe (which is match_data) after execution to allow the + // install rule to examine it. + // + case perform_update_id: t.keep_data (a); // Fall through. + case perform_clean_id: return move (md); default: return noop_recipe; // Configure update. } } @@ -2158,7 +2158,7 @@ namespace build2 *type != "cc" && type->compare (0, 3, "cc,") != 0) { - auto& md (l->data<link_rule::match_data> ()); + auto& md (l->data<link_rule::match_data> (d.a)); assert (md.for_install); // Must have been executed. // The user will get the target name from the context info. @@ -2556,7 +2556,7 @@ namespace build2 msvc_machine (const string& cpu); // msvc.cxx target_state link_rule:: - perform_update (action a, const target& xt) const + perform_update (action a, const target& xt, match_data& md) const { tracer trace (x, "link_rule::perform_update"); @@ -2568,8 +2568,6 @@ namespace build2 const scope& bs (t.base_scope ()); const scope& rs (*bs.root_scope ()); - match_data& md (t.data<match_data> ()); - // Unless the outer install rule signalled that this is update for // install, signal back that we've performed plain update. // @@ -4078,12 +4076,11 @@ namespace build2 } target_state link_rule:: - perform_clean (action a, const target& xt) const + perform_clean (action a, const target& xt, match_data& md) const { const file& t (xt.as<file> ()); ltype lt (link_type (t)); - const match_data& md (t.data<match_data> ()); clean_extras extras; clean_adhoc_extras adhoc_extras; diff --git a/libbuild2/cc/link-rule.hxx b/libbuild2/cc/link-rule.hxx index f0052e9..14a70d2 100644 --- a/libbuild2/cc/link-rule.hxx +++ b/libbuild2/cc/link-rule.hxx @@ -23,6 +23,8 @@ namespace build2 public: link_rule (data&&); + struct match_data; + struct match_result { bool seen_x = false; @@ -52,10 +54,10 @@ namespace build2 apply (action, target&, match_extra&) const override; target_state - perform_update (action, const target&) const; + perform_update (action, const target&, match_data&) const; target_state - perform_clean (action, const target&) const; + perform_clean (action, const target&, match_data&) const; public: // Library handling. @@ -226,9 +228,9 @@ namespace build2 static void functions (function_family&, const char*); // functions.cxx - private: - friend class install_rule; - friend class libux_install_rule; + // Implementation details. + // + public: // Shared library paths. // @@ -271,6 +273,9 @@ namespace build2 struct match_data { + explicit + match_data (const link_rule& r): rule (r) {} + // The "for install" condition is signalled to us by install_rule when // it is matched for the update operation. It also verifies that if we // have already been executed, then it was for install. @@ -305,10 +310,21 @@ namespace build2 size_t start; // Parallel prerequisites/prerequisite_targets start. link_rule::libs_paths libs_paths; + + const link_rule& rule; + + target_state + operator() (action a, const target& t) + { + return a == perform_update_id + ? rule.perform_update (a, t, *this) + : rule.perform_clean (a, t, *this); + } }; // Windows rpath emulation (windows-rpath.cxx). // + private: struct windows_dll { reference_wrapper<const string> dll; |