From 57e2aaa28e19da1cd4e51982f46ef2630739ff8a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 26 May 2020 13:10:37 +0200 Subject: Wrap up $<, $> variables and related ($target.path(), hashing, cleanup) --- libbuild2/build/script/lexer.cxx | 9 +++-- .../build/script/parser+variable.test.testscript | 2 +- libbuild2/build/script/parser.cxx | 9 ++++- libbuild2/build/script/parser.hxx | 3 +- libbuild2/build/script/parser.test.cxx | 4 +-- libbuild2/build/script/runner.cxx | 19 ++++++++++ libbuild2/build/script/script.cxx | 42 +++++++++++++++------- libbuild2/build/script/script.hxx | 19 +++++----- 8 files changed, 79 insertions(+), 28 deletions(-) (limited to 'libbuild2/build') 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 : $* <>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 (&rs); + scope_ = const_cast (&bs); + pbase_ = scope_->src_path_; + script_ = const_cast (&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 +#include #include 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 ()) + 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 (pt.ctx.global_scope["build.host"]), + t.ctx, + cast (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 (">"))); + names ns; + for (const target_type* m (&t); m != nullptr; m = m->adhoc_member) + m->as_name (ns); - if (auto* t = pt.is_a ()) - 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&); -- cgit v1.1