diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2020-05-15 06:50:05 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-05-27 08:35:29 +0200 |
commit | cf1670f9a6541e42f22d58e2de5940e64cb6637e (patch) | |
tree | efb80b4b34d447b2f36658c7f1a6a70d47547f5b /libbuild2/parser.cxx | |
parent | 3861606766939fffd3bf110420e377bf194e02b7 (diff) |
Implement ad hoc recipe sharing and locking
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r-- | libbuild2/parser.cxx | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 8d6beea..588968e 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -722,8 +722,12 @@ namespace build2 // that token part of the replay (we cannot peek past the replay // sequence). // - auto parse = [this, &st] (token& t, type& tt, - const target_type* type, string pat) + auto parse = [ + this, + &st, + recipes = small_vector<shared_ptr<adhoc_rule>, 1> ()] + (token& t, type& tt, + const target_type* type, string pat) mutable { token rt; // Recipe start token. @@ -752,7 +756,7 @@ namespace build2 if (type != nullptr) fail (rt) << "recipe in target type/pattern"; - parse_recipe (t, tt, rt); + parse_recipe (t, tt, rt, recipes); }; for_each (parse); @@ -1012,7 +1016,9 @@ namespace build2 } void parser:: - parse_recipe (token& t, type& tt, const token& start) + parse_recipe (token& t, type& tt, + const token& start, + small_vector<shared_ptr<adhoc_rule>, 1>& recipes) { // Parse a recipe chain. // @@ -1038,11 +1044,11 @@ namespace build2 default_target_ = target_; } - // True if seen a recipe that requires cleanup. - // - bool clean (false); + bool first (recipes.empty ()); // First target. + bool clean (false); // Seen a recipe that requires cleanup. - for (token st (start);; st = t) + token st (start); + for (size_t i (0);; st = t, ++i) { optional<string> diag; @@ -1111,31 +1117,37 @@ namespace build2 // me now. // shared_ptr<adhoc_rule> ar; + if (first) + { + // Note that this is always the location of the opening multi-curly- + // brace, whether we have the header or not. This is relied upon by + // the rule implementations (e.g., to calculate the first line of the + // recipe code). + // + location loc (get_location (st)); - // Note that this is always the location of the opening multi-curly- - // brace, whether we have the header or not. This is relied upon by the - // rule implementations (e.g., to calculate the first line of the recipe - // code). - // - location loc (get_location (st)); + if (!lang) + { + ar.reset (new adhoc_script_rule (move (t.value), + move (diag), + loc, + st.value.size ())); + } + else if (*lang == "c++") + { + ar.reset (new adhoc_cxx_rule (move (t.value), loc, st.value.size ())); + clean = true; + } + else + fail (lloc) << "unknown recipe language '" << *lang << "'"; - if (!lang) - { - ar.reset (new adhoc_script_rule (move (t.value), - move (diag), - loc, - st.value.size ())); - } - else if (*lang == "c++") - { - ar.reset (new adhoc_cxx_rule (move (t.value), loc, st.value.size ())); - clean = true; + recipes.push_back (ar); } else - fail (lloc) << "unknown recipe language '" << *lang << "'"; + ar = recipes[i]; - action a (perform_id, update_id); - target_->adhoc_recipes.push_back (adhoc_recipe {a, move (ar)}); + target_->adhoc_recipes.push_back ( + adhoc_recipe {perform_update_id, move (ar)}); next (t, tt); assert (tt == type::multi_rcbrace); @@ -1152,7 +1164,7 @@ namespace build2 // if (clean) { - action a (perform_id, clean_id); + action a (perform_clean_id); auto f (&adhoc_rule::clean_recipes_build); // First check if we have already done this. |