From 96908ec43ed27d9f34da27b6a94a6db357465056 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 14 May 2020 14:18:50 +0300 Subject: Add build script --- libbuild2/build/script/script.cxx | 156 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 libbuild2/build/script/script.cxx (limited to 'libbuild2/build/script/script.cxx') diff --git a/libbuild2/build/script/script.cxx b/libbuild2/build/script/script.cxx new file mode 100644 index 0000000..26fe006 --- /dev/null +++ b/libbuild2/build/script/script.cxx @@ -0,0 +1,156 @@ +// file : libbuild2/build/script/script.cxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#include + +#include + +#include + +using namespace std; + +namespace build2 +{ + namespace build + { + namespace script + { + // script + // + script:: + script () + : primary_target_var (var_pool.insert (">")) + { + } + + // environment + // + static const string wd_name ("current directory"); + + environment:: + environment (const build::script::script& s, const target& pt) + : build2::script::environment ( + pt.ctx, + cast (pt.ctx.global_scope["build.host"]), + work, + wd_name), + script (s), + vars (context, false /* global */), + primary_target (pt) + { + // Set the $> variable. + // + { + value& v (assign (s.primary_target_var)); + + if (auto* t = pt.is_a ()) + v = t->path (); + else + fail << "target " << pt << " is not path-based"; + } + } + + void environment:: + set_variable (string&& nm, names&& val, const string& attrs) + { + // Set the variable value and attributes. Note that we need to aquire + // unique lock before potentially changing the script's variable + // pool. The obtained variable reference can safelly be used with no + // locking as the variable pool is an associative container + // (underneath) and we are only adding new variables into it. + // + ulock ul (script.var_pool_mutex); + + const variable& var ( + const_cast (script).var_pool. + insert (move (nm))); + + ul.unlock (); + + value& lhs (assign (var)); + + // If there are no attributes specified then the variable assignment + // is straightforward. Otherwise we will use the build2 parser helper + // function. + // + if (attrs.empty ()) + lhs.assign (move (val), &var); + else + { + build2::script::parser p (context); + p.apply_value_attributes (&var, + lhs, + value (move (val)), + attrs, + token_type::assign, + path_name ("")); + } + } + + lookup environment:: + lookup (const variable& var) const + { + auto p (vars.lookup (var)); + if (p.first != nullptr) + return lookup_type (*p.first, p.second, vars); + + return lookup_in_buildfile (var.name); + } + + lookup environment:: + lookup (const string& name) const + { + // Every variable that is ever set in a script has been pre-entered + // during pre-parse or introduced with the set builtin during + // execution. Which means that if one is not found in the script pool + // then it can only possibly be set in the buildfile. + // + // Note that we need to acquire the variable pool lock. The pool can + // be changed from multiple threads by the set builtin. The obtained + // variable pointer can safelly be used with no locking as the + // variable pool is an associative container (underneath) and we are + // only adding new variables into it. + // + const variable* pvar (nullptr); + + slock sl (script.var_pool_mutex); + pvar = script.var_pool.find (name); + sl.unlock (); + + return pvar != nullptr ? lookup (*pvar) : lookup_in_buildfile (name); + } + + lookup environment:: + lookup_in_buildfile (const string& n) const + { + // Switch to the corresponding buildfile variable. Note that we don't + // want to insert a new variable into the pool (we might be running + // in parallel). Plus, if there is no such variable, then we cannot + // possibly find any value. + // + const variable* pvar (context.var_pool.find (n)); + + if (pvar == nullptr) + return lookup_type (); + + return primary_target[*pvar]; + } + + value& environment:: + append (const variable& var) + { + auto l (lookup (var)); + + if (l.defined () && l.belongs (*this)) // Existing var. + return vars.modify (l); + + value& r (assign (var)); // NULL. + + if (l.defined ()) + r = *l; // Copy value (and type) from the outer scope. + + return r; + } + } + } +} -- cgit v1.1