diff options
Diffstat (limited to 'libbuild2/build/script/script.cxx')
-rw-r--r-- | libbuild2/build/script/script.cxx | 122 |
1 files changed, 97 insertions, 25 deletions
diff --git a/libbuild2/build/script/script.cxx b/libbuild2/build/script/script.cxx index 3485f54..0d96cc3 100644 --- a/libbuild2/build/script/script.cxx +++ b/libbuild2/build/script/script.cxx @@ -3,10 +3,14 @@ #include <libbuild2/build/script/script.hxx> -#include <libbutl/filesystem.mxx> +#include <libbutl/filesystem.hxx> #include <libbuild2/target.hxx> +#include <libbuild2/adhoc-rule-buildscript.hxx> // include_unmatch* + +#include <libbuild2/script/timeout.hxx> + #include <libbuild2/build/script/parser.hxx> using namespace std; @@ -17,60 +21,113 @@ namespace build2 { namespace script { + using build2::script::to_deadline; + // environment // static const optional<string> wd_name ("current directory"); environment:: - environment (action a, const target_type& t, bool temp) + environment (action a, + const target_type& t, + const scope_type& s, + bool temp, + const optional<timestamp>& dl) : build2::script::environment ( t.ctx, - cast<target_triplet> (t.ctx.global_scope["build.host"]), + *t.ctx.build_host, dir_name_view (&work, &wd_name), temp_dir.path, false /* temp_dir_keep */, redirect (redirect_type::none), redirect (redirect_type::merge, 2), redirect (redirect_type::pass)), target (t), - vars (context, false /* global */) + scope (s), + vars (context, false /* shared */), // Note: managed. + var_ts (var_pool.insert (">")), + var_ps (var_pool.insert ("<")), + script_deadline (to_deadline (dl, false /* success */)) + { + set_special_variables (a); + + if (temp) + set_temp_dir_variable (); + } + + void environment:: + set_special_variables (action a) { - // Set special variables. - // { // $> // + // What should it contain for an explicit group? While it may seem + // that just the members should be enough (and analogous to the ad + // hoc case), this won't let us get the group name for diagnostics. + // So the group name followed by all the members seems like the + // logical choice. + // names ns; - for (const target_type* m (&t); m != nullptr; m = m->adhoc_member) - m->as_name (ns); - assign (var_pool.insert (">")) = move (ns); + if (const group* g = target.is_a<group> ()) + { + g->as_name (ns); + for (const target_type* m: g->members) + m->as_name (ns); + } + else + { + for (const target_type* m (&target); + m != nullptr; + m = m->adhoc_member) + m->as_name (ns); + } + + assign (var_ts) = 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. + // Note that ad hoc prerequisites don't end up in $<. 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 prerequisites + // from $< while still treating them as such, especially in rule. + // + // While initially we treated update=unmatch prerequisites as + // implicitly ad hoc, this turned out to be not quite correct, so + // now we add them unless they are explicitly marked ad hoc. // names ns; - for (const target_type* pt: t.prerequisite_targets[a]) - if (pt != nullptr) + for (const prerequisite_target& p: target.prerequisite_targets[a]) + { + // See adhoc_buildscript_rule::execute_update_prerequisites(). + // + if (const target_type* pt = + p.target != nullptr ? (p.adhoc () ? nullptr : p.target) : + (p.include & adhoc_buildscript_rule::include_unmatch) != 0 && + (p.include & prerequisite_target::include_adhoc) == 0 && + (p.include & adhoc_buildscript_rule::include_unmatch_adhoc) == 0 + ? reinterpret_cast<target_type*> (p.data) + : nullptr) + { pt->as_name (ns); + } + } - assign (var_pool.insert ("<")) = move (ns); + assign (var_ps) = move (ns); } + } - // Set the $~ special variable. + void environment:: + set_temp_dir_variable () + { + // Note that the temporary directory could have been created + // implicitly by the runner. // - if (temp) - { + if (temp_dir.path.empty ()) create_temp_dir (); - assign (var_pool.insert<dir_path> ("~")) = temp_dir.path; - } + + assign (var_pool.insert<dir_path> ("~")) = temp_dir.path; } void environment:: @@ -129,7 +186,7 @@ namespace build2 } void environment:: - set_variable (string&& nm, + set_variable (string nm, names&& val, const string& attrs, const location& ll) @@ -208,7 +265,7 @@ namespace build2 // in parallel). Plus, if there is no such variable, then we cannot // possibly find any value. // - const variable* pvar (context.var_pool.find (n)); + const variable* pvar (scope.var_pool ().find (n)); if (pvar == nullptr) return lookup_type (); @@ -231,6 +288,21 @@ namespace build2 return r; } + + void environment:: + set_timeout (const string& t, bool success, const location& l) + { + fragment_deadline = + to_deadline ( + parse_deadline (t, "buildscript timeout", "timeout: ", l), + success); + } + + optional<deadline> environment:: + effective_deadline () + { + return earlier (script_deadline, fragment_deadline); + } } } } |