From ad7b8477f177355e50b411b7296ae2e392d7a4be Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 31 May 2021 12:37:59 +0200 Subject: Only pass target to recipe_text() if recipe is not shared --- libbuild2/adhoc-rule-buildscript.cxx | 10 ++++-- libbuild2/adhoc-rule-buildscript.hxx | 2 +- libbuild2/adhoc-rule-cxx.cxx | 2 +- libbuild2/adhoc-rule-cxx.hxx | 2 +- libbuild2/build/script/parser.cxx | 24 ++++++++----- libbuild2/build/script/parser.hxx | 5 +-- libbuild2/build/script/parser.test.cxx | 2 +- libbuild2/parser.cxx | 12 +++++-- libbuild2/rule.hxx | 6 +++- tests/dependency/recipe/testscript | 65 +++++++++++++++++++++++----------- 10 files changed, 88 insertions(+), 42 deletions(-) diff --git a/libbuild2/adhoc-rule-buildscript.cxx b/libbuild2/adhoc-rule-buildscript.cxx index 73219b6..fe74fc6 100644 --- a/libbuild2/adhoc-rule-buildscript.cxx +++ b/libbuild2/adhoc-rule-buildscript.cxx @@ -23,8 +23,12 @@ using namespace std; namespace build2 { bool adhoc_buildscript_rule:: - recipe_text (context& ctx, const target& tg, const adhoc_actions& acts, - string&& t, attributes& as) + recipe_text (context& ctx, + const scope& s, + const target* tg, + const adhoc_actions& acts, + string&& t, + attributes& as) { // Handle and erase recipe-specific attributes. // @@ -57,7 +61,7 @@ namespace build2 istringstream is (move (t)); build::script::parser p (ctx); - script = p.pre_parse (tg, acts, + script = p.pre_parse (s, tg, acts, is, loc.file, loc.line + 1, move (diag), as.loc); diff --git a/libbuild2/adhoc-rule-buildscript.hxx b/libbuild2/adhoc-rule-buildscript.hxx index d98ffcf..38cce1e 100644 --- a/libbuild2/adhoc-rule-buildscript.hxx +++ b/libbuild2/adhoc-rule-buildscript.hxx @@ -43,7 +43,7 @@ namespace build2 : adhoc_rule ("", l, b) {} virtual bool - recipe_text (context&, const target&, const adhoc_actions&, + recipe_text (context&, const scope&, const target*, const adhoc_actions&, string&&, attributes&) override; virtual void diff --git a/libbuild2/adhoc-rule-cxx.cxx b/libbuild2/adhoc-rule-cxx.cxx index ed87cbd..e061a06 100644 --- a/libbuild2/adhoc-rule-cxx.cxx +++ b/libbuild2/adhoc-rule-cxx.cxx @@ -38,7 +38,7 @@ namespace build2 } bool adhoc_cxx_rule:: - recipe_text (context&, const target&, const adhoc_actions&, + recipe_text (context&, const scope&, const target*, const adhoc_actions&, string&& t, attributes&) { code = move (t); diff --git a/libbuild2/adhoc-rule-cxx.hxx b/libbuild2/adhoc-rule-cxx.hxx index dfcdf3f..7b83607 100644 --- a/libbuild2/adhoc-rule-cxx.hxx +++ b/libbuild2/adhoc-rule-cxx.hxx @@ -61,7 +61,7 @@ namespace build2 optional sep); virtual bool - recipe_text (context&, const target&, const adhoc_actions&, + recipe_text (context&, const scope&, const target*, const adhoc_actions&, string&&, attributes&) override; virtual diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 372c622..063ec68 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -27,7 +27,7 @@ namespace build2 // script parser:: - pre_parse (const target& tg, const adhoc_actions& as, + pre_parse (const scope& bs, const target* tg, const adhoc_actions& as, istream& is, const path_name& pn, uint64_t line, optional diag, const location& diag_loc) { @@ -40,9 +40,9 @@ namespace build2 // The script shouldn't be able to modify the target/scopes. // - target_ = const_cast (&tg); + target_ = const_cast (tg); actions_ = &as; - scope_ = const_cast (&tg.base_scope ()); + scope_ = const_cast (tg != nullptr ? &tg->base_scope () : &bs); root_ = scope_->root_scope (); pbase_ = scope_->src_path_; @@ -583,10 +583,16 @@ namespace build2 parse_names_result pr; { - // During pre-parse, if the script name is not set manually, we - // suspend pre-parse, parse the command names for real and try to - // deduce the script name from the result. Otherwise, we continue to - // pre-parse and bail out after parsing the names. + // During pre-parse, if the script name is not set manually and we + // have the target, we suspend pre-parse, parse the command names + // for real and try to deduce the script name from the result. + // Otherwise, we continue to pre-parse and bail out after parsing + // the names. + // + // @@ TODO: maybe we could recognize literal names even if target + // is NULL (see the tests for some ugly recipes). But will need + // to be careful to still pick up ambiguity between literal and + // skipped due to target being NULL. // // Note that the later is not just an optimization since expansion // that wouldn't fail during execution may fail in this special @@ -607,7 +613,7 @@ namespace build2 // // This is also the reason why we add a diag frame. // - if (pre_parse_ && diag_weight_ != 4) + if (pre_parse_ && (diag_weight_ != 4 && target_ != nullptr)) { pre_parse_ = false; // Make parse_names() perform expansions. pre_parse_suspended_ = true; @@ -638,7 +644,7 @@ namespace build2 pre_parse_ = true; } - if (pre_parse_ && diag_weight_ == 4) + if (pre_parse_ && (diag_weight_ == 4 || target_ == nullptr)) return nullopt; } diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx index 15429e3..af43e35 100644 --- a/libbuild2/build/script/parser.hxx +++ b/libbuild2/build/script/parser.hxx @@ -32,10 +32,11 @@ namespace build2 parser (context& c): build2::script::parser (c) {} // Note that the returned script object references the passed path - // name. + // name. Target is NULL if this recipe is shared among multiple + // targets. // script - pre_parse (const target&, const adhoc_actions& acts, + pre_parse (const scope&, const target*, const adhoc_actions& acts, istream&, const path_name&, uint64_t line, optional diag_name, const location& diag_loc); diff --git a/libbuild2/build/script/parser.test.cxx b/libbuild2/build/script/parser.test.cxx index 29711ef..c1ba1d1 100644 --- a/libbuild2/build/script/parser.test.cxx +++ b/libbuild2/build/script/parser.test.cxx @@ -208,7 +208,7 @@ namespace build2 parser p (ctx); path_name nm ("buildfile"); - script s (p.pre_parse (tt, acts, + script s (p.pre_parse (tt.base_scope (), &tt, acts, cin, nm, 11 /* line */, (m != mode::diag diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 120d6ab..d1db568 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -1208,6 +1208,7 @@ namespace build2 default_target_ = target_; } + bool multi (replay_ != replay::stop); // Multiple targets. bool first (replay_ != replay::play); // First target. bool clean (false); // Seen recipe that requires cleanup. @@ -1223,13 +1224,14 @@ namespace build2 struct data { small_vector, 1>& recipes; + bool multi; bool first; bool& clean; size_t i; attributes& as; buildspec& bs; const location& bsloc; - } d {recipes, first, clean, i, as, bs, bsloc}; + } d {recipes, multi, first, clean, i, as, bs, bsloc}; // Note that this function must be called at most once per iteration. // @@ -1431,8 +1433,12 @@ namespace build2 { adhoc_recipe& ar (ars.back ()); - if (ar.rule->recipe_text ( - ctx, *target_, ar.actions, move (t.value), d.as)) + if (ar.rule->recipe_text (ctx, + *scope_, + d.multi ? nullptr : target_, + ar.actions, + move (t.value), + d.as)) d.clean = true; // Verify we have no unhandled attributes. diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index 217632f..4b05379 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -161,8 +161,12 @@ namespace build2 // true if the recipe builds anything in the build/recipes/ directory and // therefore requires cleanup. // + // Target is not NULL only if this recipe is for a single target. Scope is + // the scope of the recipe (not necessarily the same as the target's base + // scope). + // virtual bool - recipe_text (context&, const target&, const adhoc_actions&, + recipe_text (context&, const scope&, const target*, const adhoc_actions&, string&&, attributes&) = 0; public: diff --git a/tests/dependency/recipe/testscript b/tests/dependency/recipe/testscript index 09a38ad..4c4abe5 100644 --- a/tests/dependency/recipe/testscript +++ b/tests/dependency/recipe/testscript @@ -28,14 +28,16 @@ EOE $* <>/~%EOE% alias{x y}: alias{z} {{ + diag echo echo }} dump alias{y} EOI -:5:1: dump: +:6:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE @@ -64,14 +66,16 @@ $* <>/~%EOE% alias{x y}: % perform(update clean) {{ + diag echo echo }} dump alias{y} EOI -:6:1: dump: +:7:1: dump: % .+/alias\{y\}:% - % [diag=echo] perform(update) perform(clean) + % perform(update) perform(clean) {{ + diag echo echo }} EOE @@ -124,17 +128,19 @@ alias{x y}: alias{z} var = x } {{ + diag echo echo }} dump alias{y} EOI -:8:1: dump: +:9:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% { var = x } - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE @@ -170,17 +176,19 @@ $* <>/~%EOE% var = x } {{ + diag echo echo }} dump alias{y} EOI -:8:1: dump: +:9:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% { var = x } - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE @@ -218,17 +226,19 @@ alias{x y}: } % perform(update) {{ + diag echo echo }} dump alias{y} EOI -:9:1: dump: +:10:1: dump: % .+/alias\{y\}:% { var = x } - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE @@ -263,22 +273,26 @@ EOE $* <>/~%EOE% alias{x y}: alias{z} {{ + diag echo echo }} % clean {{{ + diag cat cat }}} dump alias{y} EOI -:9:1: dump: +:11:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} - % [diag=cat] perform(clean) + % perform(clean) {{{ + diag cat cat }}} EOE @@ -317,23 +331,27 @@ alias{x y}: % clean {{ + diag echo echo }} % update {{{ + diag cat cat }}} dump alias{y} EOI -:12:1: dump: +:14:1: dump: % .+/alias\{y\}:% - % [diag=echo] perform(clean) + % perform(clean) {{ + diag echo echo }} - % [diag=cat] perform(update) + % perform(update) {{{ + diag cat cat }}} EOE @@ -468,18 +486,21 @@ alias{x y}: alias{z} % if $f {{ + diag false false }} else {{ + diag echo echo }} dump alias{y} EOI -:12:1: dump: +:14:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE @@ -541,23 +562,27 @@ switch $f { case 1 {{ + diag false false }} case 2 {{ + diag echo echo }} default {{ + diag false false }} } dump alias{y} EOI -:19:1: dump: +:22:1: dump: % .+/alias\{y\}: .+/:alias\{z\}% - % [diag=echo] perform(update) + % perform(update) {{ + diag echo echo }} EOE -- cgit v1.1