aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-26 13:10:37 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:40:59 +0200
commit57e2aaa28e19da1cd4e51982f46ef2630739ff8a (patch)
tree138a169b29aad630150906ffb4a8f30a5f9bdf5a /libbuild2/build
parent29c59165396eb842d92367fca74c4e459ea25900 (diff)
Wrap up $<, $> variables and related ($target.path(), hashing, cleanup)
Diffstat (limited to 'libbuild2/build')
-rw-r--r--libbuild2/build/script/lexer.cxx9
-rw-r--r--libbuild2/build/script/parser+variable.test.testscript2
-rw-r--r--libbuild2/build/script/parser.cxx9
-rw-r--r--libbuild2/build/script/parser.hxx3
-rw-r--r--libbuild2/build/script/parser.test.cxx4
-rw-r--r--libbuild2/build/script/runner.cxx19
-rw-r--r--libbuild2/build/script/script.cxx42
-rw-r--r--libbuild2/build/script/script.hxx19
8 files changed, 79 insertions, 28 deletions
diff --git a/libbuild2/build/script/lexer.cxx b/libbuild2/build/script/lexer.cxx
index 716d898..f5a7333 100644
--- a/libbuild2/build/script/lexer.cxx
+++ b/libbuild2/build/script/lexer.cxx
@@ -242,14 +242,19 @@ namespace build2
{
lexer_mode m (st.mode);
- // Customized implementation that handles special variable names ($>).
+ // Customized implementation that handles special variable names ($>,
+ // $<).
+ //
+ // @@ TODO: $(<), $(>): feels like this will have to somehow be
+ // handled at the top-level lexer level. Maybe provide a
+ // string of one-char special variable names as state::data?
//
if (m != lexer_mode::variable)
return base_lexer::word (st, sep);
xchar c (peek ());
- if (c != '>')
+ if (c != '>' && c != '<')
return base_lexer::word (st, sep);
get ();
diff --git a/libbuild2/build/script/parser+variable.test.testscript b/libbuild2/build/script/parser+variable.test.testscript
index 2d9bb1e..5040e66 100644
--- a/libbuild2/build/script/parser+variable.test.testscript
+++ b/libbuild2/build/script/parser+variable.test.testscript
@@ -13,7 +13,7 @@ EOO
: primary-target
:
$* <<EOI >>EOO
-echo $>
+echo $name($>)
EOI
echo driver
EOO
diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx
index 60000c2..b170088 100644
--- a/libbuild2/build/script/parser.cxx
+++ b/libbuild2/build/script/parser.cxx
@@ -248,7 +248,8 @@ namespace build2
//
void parser::
- execute (const script& s, environment& e, runner& r)
+ execute (const scope& rs, const scope& bs,
+ environment& e, const script& s, runner& r)
{
path_ = nullptr; // Set by replays.
@@ -256,6 +257,12 @@ namespace build2
set_lexer (nullptr);
+ // The script shouldn't be able to modify the scopes.
+ //
+ root_ = const_cast<scope*> (&rs);
+ scope_ = const_cast<scope*> (&bs);
+ pbase_ = scope_->src_path_;
+
script_ = const_cast<script*> (&s);
runner_ = &r;
environment_ = &e;
diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx
index 7183509..4c16087 100644
--- a/libbuild2/build/script/parser.hxx
+++ b/libbuild2/build/script/parser.hxx
@@ -68,7 +68,8 @@ namespace build2
//
public:
void
- execute (const script&, environment&, runner&);
+ execute (const scope& root, const scope& base,
+ environment&, const script&, runner&);
protected:
void
diff --git a/libbuild2/build/script/parser.test.cxx b/libbuild2/build/script/parser.test.cxx
index b179884..42681e3 100644
--- a/libbuild2/build/script/parser.test.cxx
+++ b/libbuild2/build/script/parser.test.cxx
@@ -166,9 +166,9 @@ namespace build2
{
case mode::run:
{
- environment e (tt);
+ environment e (perform_update_id, tt);
print_runner r (print_line);
- p.execute (s, e, r);
+ p.execute (ctx.global_scope, ctx.global_scope, e, s, r);
break;
}
case mode::dump:
diff --git a/libbuild2/build/script/runner.cxx b/libbuild2/build/script/runner.cxx
index c4a93fd..559a6cd 100644
--- a/libbuild2/build/script/runner.cxx
+++ b/libbuild2/build/script/runner.cxx
@@ -5,6 +5,7 @@
#include <libbutl/filesystem.mxx>
+#include <libbuild2/target.hxx>
#include <libbuild2/script/run.hxx>
using namespace butl;
@@ -75,6 +76,24 @@ namespace build2
void default_runner::
leave (environment& env, const location& ll)
{
+ // Drop cleanups of target paths.
+ //
+ for (auto i (env.cleanups.begin ()); i != env.cleanups.end (); )
+ {
+ const target* m (&env.target);
+ for (; m != nullptr; m = m->adhoc_member)
+ {
+ if (const path_target* pm = m->is_a<path_target> ())
+ if (i->path == pm->path ())
+ break;
+ }
+
+ if (m != nullptr)
+ i = env.cleanups.erase (i);
+ else
+ ++i;
+ }
+
clean (env, ll);
// Note that since the temporary directory may only contain special
diff --git a/libbuild2/build/script/script.cxx b/libbuild2/build/script/script.cxx
index b43203c..c258c4c 100644
--- a/libbuild2/build/script/script.cxx
+++ b/libbuild2/build/script/script.cxx
@@ -20,30 +20,46 @@ namespace build2
static const string wd_name ("current directory");
environment::
- environment (const target& pt)
+ environment (action a, const target_type& t)
: build2::script::environment (
- pt.ctx,
- cast<target_triplet> (pt.ctx.global_scope["build.host"]),
+ t.ctx,
+ cast<target_triplet> (t.ctx.global_scope["build.host"]),
work, wd_name,
temp_dir.path, false /* temp_dir_keep */,
redirect (redirect_type::none),
redirect (redirect_type::merge, 2),
redirect (redirect_type::pass)),
- primary_target (pt),
+ target (t),
vars (context, false /* global */)
{
- // Set the $> variable.
+ // Set special variables.
//
{
- //@@ TODO
+ // $>
//
- value& v (assign (var_pool.insert<string> (">")));
+ names ns;
+ for (const target_type* m (&t); m != nullptr; m = m->adhoc_member)
+ m->as_name (ns);
- if (auto* t = pt.is_a<path_target> ())
- v = t->path ().string ();
- else
- //fail << "target " << pt << " is not path-based";
- v = pt.name; //@@ TMP
+ assign (var_pool.insert (">")) = move (ns);
+ }
+
+ {
+ // $<
+ //
+ // Note that at this stage (after execute_prerequisites()) ad hoc
+ // prerequisites are no longer in prerequisite_targets which means
+ // they won't end up in $< either. While at first thought ad hoc
+ // prerequisites in ad hoc recipes don't seem to make much sense,
+ // they could be handy to exclude certain preresquisites from $<
+ // while still treating them as such.
+ //
+ names ns;
+ for (const target_type* pt: t.prerequisite_targets[a])
+ if (pt != nullptr)
+ pt->as_name (ns);
+
+ assign (var_pool.insert ("<")) = move (ns);
}
}
@@ -109,7 +125,7 @@ namespace build2
if (pvar == nullptr)
return lookup_type ();
- return primary_target[*pvar];
+ return target[*pvar];
}
value& environment::
diff --git a/libbuild2/build/script/script.hxx b/libbuild2/build/script/script.hxx
index ec603a7..2139f28 100644
--- a/libbuild2/build/script/script.hxx
+++ b/libbuild2/build/script/script.hxx
@@ -62,7 +62,9 @@ namespace build2
class environment: public build2::script::environment
{
public:
- environment (const target& primary_target);
+ using target_type = build2::target;
+
+ environment (action, const target_type&);
environment (environment&&) = delete;
environment (const environment&) = delete;
@@ -70,7 +72,7 @@ namespace build2
environment& operator= (const environment&) = delete;
public:
- const target& primary_target;
+ const target_type& target;
// Script-local variable pool.
//
@@ -121,17 +123,18 @@ namespace build2
lookup_in_buildfile (const string&) const;
// Return a value suitable for assignment. If the variable does not
- // exist in this environment's map, then a new one with the NULL value
- // is added and returned. Otherwise the existing value is returned.
+ // exist in this environment's variable map, then a new one with the
+ // NULL value is added and returned. Otherwise the existing value is
+ // returned.
//
value&
assign (const variable& var) {return vars.assign (var);}
// Return a value suitable for append/prepend. If the variable does
- // not exist in this environment's map, then outer scopes are searched
- // for the same variable. If found then a new variable with the found
- // value is added to the environment and returned. Otherwise this
- // function proceeds as assign() above.
+ // not exist in this environment's variable map, then outer scopes are
+ // searched for the same variable. If found then a new variable with
+ // the found value is added to the environment and returned. Otherwise
+ // this function proceeds as assign() above.
//
value&
append (const variable&);