aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r--libbuild2/parser.cxx43
1 files changed, 42 insertions, 1 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index db95297..8d6beea 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -1021,9 +1021,12 @@ namespace build2
// ...
// }}
//
- // enter: percent or openining multi-curly-brace
+ // enter: start is percent or openining multi-curly-brace
// leave: token past newline after last closing multi-curly-brace
+ if (stage_ == stage::boot)
+ fail (t) << "ad hoc recipe specified during bootstrap";
+
// If we have a recipe, the target is not implied.
//
if (target_->implied)
@@ -1035,6 +1038,10 @@ namespace build2
default_target_ = target_;
}
+ // True if seen a recipe that requires cleanup.
+ //
+ bool clean (false);
+
for (token st (start);; st = t)
{
optional<string> diag;
@@ -1113,12 +1120,17 @@ namespace build2
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 << "'";
@@ -1134,6 +1146,35 @@ namespace build2
if (tt != type::percent && tt != type::multi_lcbrace)
break;
}
+
+ // If we have a recipe that needs cleanup, register an operation callback
+ // for this project unless it has already been done.
+ //
+ if (clean)
+ {
+ action a (perform_id, clean_id);
+ auto f (&adhoc_rule::clean_recipes_build);
+
+ // First check if we have already done this.
+ //
+ auto p (root_->operation_callbacks.equal_range (a));
+ for (; p.first != p.second; ++p.first)
+ {
+ auto t (
+ p.first->second.pre.target<scope::operation_callback::callback*> ());
+
+ if (t != nullptr && *t == f)
+ break;
+ }
+
+ // It feels natural to clean up recipe builds as a post operation but
+ // that prevents the (otherwise-empty) out root directory to be cleaned
+ // up (via the standard fsdir{} chain).
+ //
+ if (p.first == p.second)
+ root_->operation_callbacks.emplace (
+ a, scope::operation_callback {f, nullptr /*post*/});
+ }
}
void parser::