diff options
Diffstat (limited to 'libbuild2/functions-process.cxx')
-rw-r--r-- | libbuild2/functions-process.cxx | 86 |
1 files changed, 63 insertions, 23 deletions
diff --git a/libbuild2/functions-process.cxx b/libbuild2/functions-process.cxx index c4e5c24..6faa798 100644 --- a/libbuild2/functions-process.cxx +++ b/libbuild2/functions-process.cxx @@ -4,6 +4,8 @@ #include <libbutl/regex.hxx> #include <libbutl/builtin.hxx> +#include <libbuild2/scope.hxx> +#include <libbuild2/context.hxx> #include <libbuild2/function.hxx> #include <libbuild2/variable.hxx> @@ -141,6 +143,9 @@ namespace build2 builtin_callbacks cb; fdpipe ofd (open_pipe ()); + if (verb >= 3) + print_process (process_args (bn, args)); + uint8_t rs; // Storage. butl::builtin b (bf (rs, args, @@ -172,7 +177,16 @@ namespace build2 // While assuming that the builtin has issued the diagnostics on failure // we still print the error message (see process_finish() for details). // - fail << bn << " builtin " << process_exit (rs) << endf; + diag_record dr; + dr << fail << "builtin " << bn << " " << process_exit (rs); + + if (verb >= 1 && verb <= 2) + { + dr << info << "command line: "; + print_process (dr, process_args (bn, args)); + } + + dr << endf; } catch (const system_error& e) { @@ -181,18 +195,32 @@ namespace build2 } static inline value - run_builtin (builtin_function* bf, const strings& args, const string& bn) + run_builtin (const scope* s, + builtin_function* bf, + const strings& args, + const string& bn) { + // See below. + // + if (s != nullptr && s->ctx.phase != run_phase::load) + fail << "process.run() called during " << s->ctx.phase << " phase"; + return run_builtin_impl (bf, args, bn, read); } static inline value - run_builtin_regex (builtin_function* bf, + run_builtin_regex (const scope* s, + builtin_function* bf, const strings& args, const string& bn, const string& pat, const optional<string>& fmt) { + // See below. + // + if (s != nullptr && s->ctx.phase != run_phase::load) + fail << "process.run_regex() called during " << s->ctx.phase << " phase"; + // Note that we rely on the "small function object" optimization here. // return run_builtin_impl (bf, args, bn, @@ -293,6 +321,9 @@ namespace build2 [] (const string& s) {return s.c_str ();}); cargs.push_back (nullptr); + // Note that for now these functions can only be called during the load + // phase (see below) and so no diagnostics buffering is needed. + // return run_start (3 /* verbosity */, pp, cargs, @@ -309,15 +340,7 @@ namespace build2 void process_finish (const scope*, const cstrings& args, process& pr) { - try - { - if (!pr.wait ()) - fail << "process " << args[0] << " " << *pr.exit; - } - catch (const process_error& e) - { - fail << "unable to execute " << args[0] << ": " << e; - } + run_finish (args, pr, 2 /* verbosity */); } // Run a process. @@ -352,6 +375,15 @@ namespace build2 static inline value run_process (const scope* s, const process_path& pp, const strings& args) { + // The only plausible place where these functions can be called outside + // the load phase are scripts and there it doesn't make much sense to use + // them (the same can be achieved with commands in a uniform manner). Note + // that if there is no scope, then this is most likely (certainly?) the + // load phase (for example, command line). + // + if (s != nullptr && s->ctx.phase != run_phase::load) + fail << "process.run() called during " << s->ctx.phase << " phase"; + return run_process_impl (s, pp, args, read); } @@ -362,6 +394,11 @@ namespace build2 const string& pat, const optional<string>& fmt) { + // See above. + // + if (s != nullptr && s->ctx.phase != run_phase::load) + fail << "process.run_regex() called during " << s->ctx.phase << " phase"; + // Note that we rely on the "small function object" optimization here. // return run_process_impl (s, pp, args, @@ -377,7 +414,7 @@ namespace build2 if (builtin_function* bf = builtin (args)) { pair<string, strings> ba (builtin_args (bf, move (args), "run")); - return run_builtin (bf, ba.second, ba.first); + return run_builtin (s, bf, ba.second, ba.first); } else { @@ -395,7 +432,7 @@ namespace build2 if (builtin_function* bf = builtin (args)) { pair<string, strings> ba (builtin_args (bf, move (args), "run_regex")); - return run_builtin_regex (bf, ba.second, ba.first, pat, fmt); + return run_builtin_regex (s, bf, ba.second, ba.first, pat, fmt); } else { @@ -413,14 +450,15 @@ namespace build2 // $process.run(<prog>[ <args>...]) // - // Run builtin or external program and return trimmed stdout. + // Run builtin or external program and return trimmed `stdout` output. // // Note that if the result of executing the program can be affected by // environment variables and this result can in turn affect the build // result, then such variables should be reported with the - // config.environment directive. + // `config.environment` directive. // - // Note that this function is not pure. + // Note that this function is not pure and can only be called during the + // load phase. // f.insert (".run", false) += [](const scope* s, names args) { @@ -432,21 +470,23 @@ namespace build2 return run_process (s, pp, strings ()); }; - // $process.run_regex(<prog>[ <args>...], <pat> [, <fmt>]) + // $process.run_regex(<prog>[ <args>...], <pat>[, <fmt>]) // - // Run builtin or external program and return stdout lines matched and - // optionally processed with regex. + // Run builtin or external program and return `stdout` output lines + // matched and optionally processed with a regular expression. // // Each line of stdout (including the customary trailing blank) is matched // (as a whole) against <pat> and, if successful, returned, optionally - // processed with <fmt>, as an element of a list. + // processed with <fmt>, as an element of a list. See the `$regex.*()` + // function family for details on regular expressions and format strings. // // Note that if the result of executing the program can be affected by // environment variables and this result can in turn affect the build // result, then such variables should be reported with the - // config.environment directive. + // `config.environment` directive. // - // Note that this function is not pure. + // Note that this function is not pure and can only be called during the + // load phase. // { auto e (f.insert (".run_regex", false)); |