aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-05-31 12:37:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-06-08 15:43:08 +0200
commitc5feaaf745421f2ecda672585c462cf4c807d25d (patch)
treeda5b002dbd03fd624462cacfebb469df63708e63
parent274d65d2a76ed48cb618e25e0916e20ba3d5c87b (diff)
Only pass target to recipe_text() if recipe is not shared
-rw-r--r--libbuild2/adhoc-rule-buildscript.cxx10
-rw-r--r--libbuild2/adhoc-rule-buildscript.hxx2
-rw-r--r--libbuild2/adhoc-rule-cxx.cxx2
-rw-r--r--libbuild2/adhoc-rule-cxx.hxx2
-rw-r--r--libbuild2/build/script/parser.cxx24
-rw-r--r--libbuild2/build/script/parser.hxx5
-rw-r--r--libbuild2/build/script/parser.test.cxx2
-rw-r--r--libbuild2/parser.cxx12
-rw-r--r--libbuild2/rule.hxx6
-rw-r--r--tests/dependency/recipe/testscript65
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 ("<ad hoc buildscript recipe>", 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<string> 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<string> 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<target*> (&tg);
+ target_ = const_cast<target*> (tg);
actions_ = &as;
- scope_ = const_cast<scope*> (&tg.base_scope ());
+ scope_ = const_cast<scope*> (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<string> 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<shared_ptr<adhoc_rule>, 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
$* <<EOI 2>>/~%EOE%
alias{x y}: alias{z}
{{
+ diag echo
echo
}}
dump alias{y}
EOI
-<stdin>:5:1: dump:
+<stdin>:6:1: dump:
% .+/alias\{y\}: .+/:alias\{z\}%
- % [diag=echo] perform(update)
+ % perform(update)
{{
+ diag echo
echo
}}
EOE
@@ -64,14 +66,16 @@ $* <<EOI 2>>/~%EOE%
alias{x y}:
% perform(update clean)
{{
+ diag echo
echo
}}
dump alias{y}
EOI
-<stdin>:6:1: dump:
+<stdin>: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
-<stdin>:8:1: dump:
+<stdin>:9:1: dump:
% .+/alias\{y\}: .+/:alias\{z\}%
{
var = x
}
- % [diag=echo] perform(update)
+ % perform(update)
{{
+ diag echo
echo
}}
EOE
@@ -170,17 +176,19 @@ $* <<EOI 2>>/~%EOE%
var = x
}
{{
+ diag echo
echo
}}
dump alias{y}
EOI
-<stdin>:8:1: dump:
+<stdin>: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
-<stdin>:9:1: dump:
+<stdin>:10:1: dump:
% .+/alias\{y\}:%
{
var = x
}
- % [diag=echo] perform(update)
+ % perform(update)
{{
+ diag echo
echo
}}
EOE
@@ -263,22 +273,26 @@ EOE
$* <<EOI 2>>/~%EOE%
alias{x y}: alias{z}
{{
+ diag echo
echo
}}
% clean
{{{
+ diag cat
cat
}}}
dump alias{y}
EOI
-<stdin>:9:1: dump:
+<stdin>: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
-<stdin>:12:1: dump:
+<stdin>: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
-<stdin>:12:1: dump:
+<stdin>: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
-<stdin>:19:1: dump:
+<stdin>:22:1: dump:
% .+/alias\{y\}: .+/:alias\{z\}%
- % [diag=echo] perform(update)
+ % perform(update)
{{
+ diag echo
echo
}}
EOE