From ae5cab7489fe014dd3aa818cf2655d7a4714af83 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 16 Dec 2017 17:42:12 +0200 Subject: Improve process execution diagnostics by reusing run_*() API --- build2/bin/guess.cxx | 18 +++--- build2/bin/init.cxx | 3 +- build2/cc/compile.cxx | 14 ++--- build2/cc/gcc.cxx | 66 ++++++++------------ build2/cc/guess.cxx | 18 +++--- build2/cc/link.cxx | 25 ++------ build2/cc/module.cxx | 3 +- build2/cc/msvc.cxx | 5 +- build2/cli/init.cxx | 2 + build2/cli/rule.cxx | 20 +----- build2/context.cxx | 2 +- build2/dist/operation.cxx | 65 +++---------------- build2/install/rule.cxx | 131 +++++++++------------------------------ build2/utility.cxx | 49 +++++++++------ build2/utility.hxx | 134 +++++++++++++++++++++++++++++++++------- build2/utility.txx | 2 +- build2/version/snapshot-git.cxx | 8 ++- 17 files changed, 250 insertions(+), 315 deletions(-) diff --git a/build2/bin/guess.cxx b/build2/bin/guess.cxx index 780ccf8..795477e 100644 --- a/build2/bin/guess.cxx +++ b/build2/bin/guess.cxx @@ -78,7 +78,7 @@ namespace build2 // (yes, it goes to stdout) but that seems harmless. // sha256 cs; - arr = run (arp, "--version", f, false, false, &cs); + arr = run (3, arp, "--version", f, false, false, &cs); if (!arr.empty ()) arr.checksum = cs.string (); @@ -101,7 +101,7 @@ namespace build2 // Redirect STDERR to STDOUT and ignore exit status. // sha256 cs; - arr = run (arp, f, false, true, &cs); + arr = run (3, arp, f, false, true, &cs); if (!arr.empty ()) { @@ -142,7 +142,7 @@ namespace build2 }; sha256 cs; - rlr = run (rlp, "--version", f, false, false, &cs); + rlr = run (3, rlp, "--version", f, false, false, &cs); if (!rlr.empty ()) rlr.checksum = cs.string (); @@ -162,7 +162,7 @@ namespace build2 // Redirect STDERR to STDOUT and ignore exit status. // sha256 cs; - rlr = run (rlp, f, false, true, &cs); + rlr = run (3, rlp, f, false, true, &cs); if (!rlr.empty ()) { @@ -224,7 +224,7 @@ namespace build2 // but that seems harmless. // sha256 cs; - r = run (pp, "--version", f, false, true, &cs); + r = run (3, pp, "--version", f, false, true, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -255,7 +255,7 @@ namespace build2 }; sha256 cs; - r = run (pp, "-v", f, false, false, &cs); + r = run (3, pp, "-v", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -282,7 +282,7 @@ namespace build2 // option. // sha256 cs; - r = run (pp, "-version", f, false, false, &cs); + r = run (3, pp, "-version", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -322,7 +322,7 @@ namespace build2 // option. // sha256 cs; - r = run (pp, "--version", f, false, false, &cs); + r = run (3, pp, "--version", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); @@ -342,7 +342,7 @@ namespace build2 }; sha256 cs; - r = run (pp, "/?", f, false, false, &cs); + r = run (3, pp, "/?", f, false, false, &cs); if (!r.empty ()) r.checksum = cs.string (); diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx index ef4b3df..d9f3c0e 100644 --- a/build2/bin/init.cxx +++ b/build2/bin/init.cxx @@ -250,7 +250,8 @@ namespace build2 // if (!hint && ops.config_sub_specified ()) { - s = run (ops.config_sub (), + s = run (3, + ops.config_sub (), s.c_str (), [] (string& l) {return move (l);}); l5 ([&]{trace << "config.sub target: '" << s << "'";}); diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index d73e67c..3b60a5b 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -2723,7 +2723,7 @@ namespace build2 continue; } else - fail << args[0] << " terminated abnormally: " << e.description (); + run_finish (args, pr); // Throws. } catch (const process_error& e) { @@ -3012,7 +3012,7 @@ namespace build2 info << "then run failing command to display compiler diagnostics"; } else - fail << args[0] << " terminated abnormally: " << e.description (); + run_finish (args, pr); // Throws. } catch (const process_error& e) { @@ -4489,17 +4489,12 @@ namespace build2 catch (const io_error&) {} // Assume exits with error. } - if (!pr.wait ()) - throw failed (); + run_finish (args, pr); } catch (const process_error& e) { error << "unable to execute " << args[0] << ": " << e; - // In a multi-threaded program that fork()'ed but did not exec(), - // it is unwise to try to do any kind of cleanup (like unwinding - // the stack and running destructors). - // if (e.child) exit (1); @@ -4541,8 +4536,7 @@ namespace build2 nullptr, // CWD env.empty () ? nullptr : env.data ()); - if (!pr.wait ()) - throw failed (); + run_finish (args, pr); } catch (const process_error& e) { diff --git a/build2/cc/gcc.cxx b/build2/cc/gcc.cxx index ce1450e..0ce4c4f 100644 --- a/build2/cc/gcc.cxx +++ b/build2/cc/gcc.cxx @@ -180,57 +180,43 @@ namespace build2 if (verb >= 3) print_process (args); + process pr (run_start (xc, args.data (), -1)); // Open pipe to stdout. + string l; try { - process pr (xc, args.data (), 0, -1); // Open pipe to stdout. - - try + ifdstream is ( + move (pr.in_ofd), fdstream_mode::skip, ifdstream::badbit); + + // The output of -print-search-dirs are a bunch of lines that start + // with ": =" where name can be "install", "programs", or + // "libraries". If you have English locale, that is. If you set your + // LC_ALL="tr_TR", then it becomes "kurulum", "programlar", and + // "kitapl?klar". Also, Clang omits "install" while GCC and Intel icc + // print all three. The "libraries" seem to be alwasy last, however. + // + string s; + for (bool found (false); !found && getline (is, s); ) { - ifdstream is ( - move (pr.in_ofd), fdstream_mode::skip, ifdstream::badbit); - - // The output of -print-search-dirs are a bunch of lines that start - // with ": =" where name can be "install", "programs", or - // "libraries". If you have English locale, that is. If you set your - // LC_ALL="tr_TR", then it becomes "kurulum", "programlar", and - // "kitapl?klar". Also, Clang omits "install" while GCC and Intel - // icc print all three. The "libraries" seem to be alwasy last, - // however. - // - string s; - for (bool found (false); !found && getline (is, s); ) - { - found = (s.compare (0, 12, "libraries: =") == 0); - - size_t p (found ? 9 : s.find (": =")); - - if (p != string::npos) - l.assign (s, p + 3, string::npos); - } + found = (s.compare (0, 12, "libraries: =") == 0); - is.close (); // Don't block. + size_t p (found ? 9 : s.find (": =")); - if (!pr.wait ()) - throw failed (); // Assume issued diagnostics to stderr. - } - catch (const io_error&) - { - pr.wait (); - fail << "error reading " << x_lang << " compiler -print-search-dirs " - << "output"; + if (p != string::npos) + l.assign (s, p + 3, string::npos); } + + is.close (); // Don't block. } - catch (const process_error& e) + catch (const io_error&) { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); + pr.wait (); + fail << "error reading " << x_lang << " compiler -print-search-dirs " + << "output"; } + run_finish (args, pr); + if (l.empty ()) fail << "unable to extract " << x_lang << " compiler system library " << "search paths"; diff --git a/build2/cc/guess.cxx b/build2/cc/guess.cxx index 6dea97d..c39c02e 100644 --- a/build2/cc/guess.cxx +++ b/build2/cc/guess.cxx @@ -248,7 +248,7 @@ namespace build2 // Suppress all the compiler errors because we may be trying an // unsupported option. // - r = run (pp, "-v", f, false, false, &cs); + r = run (3, pp, "-v", f, false, false, &cs); if (!r.empty ()) { @@ -284,7 +284,7 @@ namespace build2 return guess_result (); }; - r = run (pp, "--version", f, false); + r = run (3, pp, "--version", f, false); } // Finally try to run it without any options to detect msvc. @@ -317,7 +317,7 @@ namespace build2 return guess_result (); }; - r = run (pp, f, false); + r = run (3, pp, f, false); } if (!r.empty ()) @@ -487,7 +487,7 @@ namespace build2 // auto f = [] (string& l) {return move (l);}; - string t (run (args.data (), f, false)); + string t (run (3, args.data (), f, false)); if (t.empty ()) { @@ -495,7 +495,7 @@ namespace build2 << "falling back to -dumpmachine";}); args[1] = "-dumpmachine"; - t = run (args.data (), f); + t = run (3, args.data (), f); } if (t.empty ()) @@ -609,7 +609,7 @@ namespace build2 // The output of -dumpmachine is a single line containing just the // target triplet. // - string t (run (args.data (), [] (string& l) {return move (l);})); + string t (run (3, args.data (), [](string& l) {return move (l);})); if (t.empty ()) fail << "unable to extract target architecture from " << xc @@ -682,7 +682,7 @@ namespace build2 // The -V output is sent to STDERR. // - s = run (xc, "-V", f, false); + s = run (3, xc, "-V", f, false); if (s.empty ()) fail << "unable to extract signature from " << xc << " -V output"; @@ -781,7 +781,7 @@ namespace build2 // The -V output is sent to STDERR. // - string t (run (args.data (), f, false)); + string t (run (3, args.data (), f, false)); if (t.empty ()) fail << "unable to extract target architecture from " << xc @@ -823,7 +823,7 @@ namespace build2 // on which we are running), who knows what will happen in the future. // So instead we are going to use -dumpmachine and substitute the CPU. // - t = run (xc, "-dumpmachine", [] (string& l) {return move (l);}); + t = run (3, xc, "-dumpmachine", [](string& l) {return move (l);}); if (t.empty ()) fail << "unable to extract target architecture from " << xc diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index c0ff10c..f69d549 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -1297,9 +1297,6 @@ namespace build2 os << "\"" << endl; os.close (); - - if (!pr.wait ()) - throw failed (); // Assume diagnostics issued. } catch (const io_error& e) { @@ -1307,6 +1304,8 @@ namespace build2 fail << "unable to pipe resource file to " << args[0] << ": " << e; } + + run_finish (args, pr); } catch (const process_error& e) { @@ -1963,8 +1962,7 @@ namespace build2 catch (const io_error&) {} // Assume exits with error. } - if (!pr.wait ()) - throw failed (); + run_finish (args, pr); } catch (const process_error& e) { @@ -1997,22 +1995,7 @@ namespace build2 if (verb >= 2) print_process (args); - try - { - process pr (rl, args); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); - } + run (rl, args); } if (tclass == "windows") diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 9fbae4b..d4962a4 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -119,7 +119,8 @@ namespace build2 if (ops.config_sub_specified ()) { - ct = run (ops.config_sub (), + ct = run (3, + ops.config_sub (), ci.target.c_str (), [] (string& l) {return move (l);}); l5 ([&]{trace << "config.sub target: '" << ct << "'";}); diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index a4c4317..59bb55c 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -151,10 +151,13 @@ namespace build2 l.string ().c_str (), nullptr}; + if (verb >= 3) + print_process (args); + // Link.exe seem to always dump everything to stdout but just in case // redirect stderr to stdout. // - process pr (run_start (ld, args, false)); + process pr (run_start (ld, args, -1 /* stdout */, false /* error */)); bool obj (false), dll (false); string s; diff --git a/build2/cli/init.cxx b/build2/cli/init.cxx index d257efa..c698fd2 100644 --- a/build2/cli/init.cxx +++ b/build2/cli/init.cxx @@ -107,6 +107,8 @@ namespace build2 { const char* args[] = {cli.string ().c_str (), "--version", nullptr}; + // @@ TODO: redo using run_start()/run_finish(). + try { pp = process::path_search (cli, true); // Can throw. diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index 83774a3..d05b190 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -283,25 +283,9 @@ namespace build2 else if (verb) text << "cli " << s; - try - { - process pr (cli, args.data ()); - - if (!pr.wait ()) - throw failed (); - - t.mtime (system_clock::now ()); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); - } + run (cli, args); + t.mtime (system_clock::now ()); return target_state::changed; } } diff --git a/build2/context.cxx b/build2/context.cxx index cfd925b..73717be 100644 --- a/build2/context.cxx +++ b/build2/context.cxx @@ -477,7 +477,7 @@ namespace build2 // string orig ( ops.config_guess_specified () - ? run (ops.config_guess (), [] (string& l) {return move (l);}) + ? run (3, ops.config_guess (), [](string& l) {return move (l);}) : BUILD2_HOST_TRIPLET); l5 ([&]{trace << "original host: '" << orig << "'";}); diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index 7539fc1..7644ba9 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -395,22 +395,7 @@ namespace build2 else if (verb) text << "dist -d " << d; - try - { - process pr (cmd, args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); - } + run (cmd, args); } // install @@ -449,22 +434,7 @@ namespace build2 else if (verb) text << "dist " << t; - try - { - process pr (cmd, args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); - } + run (cmd, args); return d / relf.leaf (); } @@ -494,31 +464,16 @@ namespace build2 args = {"tar", "-a", "-cf", ap.string ().c_str (), pkg.c_str (), nullptr}; - try - { - process_path pp (process::path_search (args[0])); - - if (verb >= 2) - print_process (args); - else if (verb) - text << args[0] << " " << ap; + process_path pp (run_search (args[0])); - // Change child's working directory to dist_root. - // - process pr (pp, args.data (), 0, 1, 2, root.string ().c_str ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); + if (verb >= 2) + print_process (args); + else if (verb) + text << args[0] << " " << ap; - throw failed (); - } + // Change child's working directory to dist_root. + // + run (pp, args, root); } const meta_operation_info mo_dist { diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index 75de96f..79287f8 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -553,29 +553,14 @@ namespace build2 args.push_back (reld.c_str ()); args.push_back (nullptr); - try - { - process_path pp (process::path_search (args[0])); - - if (verb >= 2) - print_process (args); - else if (verb && verbose) - text << "install " << chd; - - process pr (pp, args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; + process_path pp (run_search (args[0])); - if (e.child) - exit (1); + if (verb >= 2) + print_process (args); + else if (verb && verbose) + text << "install " << chd; - throw failed (); - } + run (pp, args); } // install / @@ -622,29 +607,14 @@ namespace build2 args.push_back (reld.c_str ()); args.push_back (nullptr); - try - { - process_path pp (process::path_search (args[0])); + process_path pp (run_search (args[0])); - if (verb >= 2) - print_process (args); - else if (verb && verbose) - text << "install " << t; + if (verb >= 2) + print_process (args); + else if (verb && verbose) + text << "install " << t; - process pr (pp, args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); - - throw failed (); - } + run (pp, args); } void file_rule:: @@ -672,29 +642,14 @@ namespace build2 const char** args (&args_a[base.sudo == nullptr ? 1 : 0]); - try - { - process_path pp (process::path_search (args[0])); - - if (verb >= 2) - print_process (args); - else if (verb && verbose) - text << "install " << rell << " -> " << target; - - process pr (pp, args); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; + process_path pp (run_search (args[0])); - if (e.child) - exit (1); + if (verb >= 2) + print_process (args); + else if (verb && verbose) + text << "install " << rell << " -> " << target; - throw failed (); - } + run (pp, args); } target_state file_rule:: @@ -839,29 +794,14 @@ namespace build2 const char** args (&args_a[base.sudo == nullptr ? 1 : 0]); - try - { - process_path pp (process::path_search (args[0])); - - if (verb >= 2) - print_process (args); - else if (verb && verbose) - text << "uninstall " << reld; - - process pr (pp, args); + process_path pp (run_search (args[0])); - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); + if (verb >= 2) + print_process (args); + else if (verb && verbose) + text << "uninstall " << reld; - throw failed (); - } + run (pp, args); } } @@ -942,27 +882,12 @@ namespace build2 const char** args (&args_a[base.sudo == nullptr ? 1 : 0]); - try - { - process_path pp (process::path_search (args[0])); - - if (verb >= 2) - print_process (args); - - process pr (pp, args); + process_path pp (run_search (args[0])); - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e; - - if (e.child) - exit (1); + if (verb >= 2) + print_process (args); - throw failed (); - } + run (pp, args); } return true; diff --git a/build2/utility.cxx b/build2/utility.cxx index df19b92..e8e5fe9 100644 --- a/build2/utility.cxx +++ b/build2/utility.cxx @@ -208,29 +208,32 @@ namespace build2 } process - run_start (const process_path& pp, const char* args[], bool err) + run_start (const process_path& pp, + const char* args[], + int out, + bool err, + const dir_path& cwd) + try { assert (args[0] == pp.recall_string ()); - - if (verb >= 3) - print_process (args); - - try - { - return process (pp, args, 0, -1, (err ? 2 : 1)); - } - catch (const process_error& e) + return process (pp, args, 0, out, (err ? 2 : 1), cwd.string ().c_str ()); + } + catch (const process_error& e) + { + if (e.child) { - if (e.child) - { - // Note: run_finish() expects this exact message. - // - cerr << "unable to execute " << args[0] << ": " << e << endl; - exit (1); - } - else - fail << "unable to execute " << args[0] << ": " << e << endf; + // Note: run_finish() expects this exact message. + // + cerr << "unable to execute " << args[0] << ": " << e << endl; + + // In a multi-threaded program that fork()'ed but did not exec(), it is + // unwise to try to do any kind of cleanup (like unwinding the stack and + // running destructors). + // + exit (1); } + else + fail << "unable to execute " << args[0] << ": " << e << endf; } bool @@ -240,6 +243,14 @@ namespace build2 if (pr.wait ()) return true; + const process_exit& e (*pr.exit); + + if (!e.normal ()) + fail << "process " << args[0] << " terminated abnormally: " + << e.description () << (e.core () ? " (core dumped)" : ""); + + // Normall but non-zero exit status. + // if (err) // Assuming diagnostics has already been issued (to STDERR). // diff --git a/build2/utility.hxx b/build2/utility.hxx index 77c46a8..db6460c 100644 --- a/build2/utility.hxx +++ b/build2/utility.hxx @@ -166,12 +166,16 @@ namespace build2 // Basic process utilities. // + // The run*() functions with process_path assume that you are printing + // the process command line yourself. - // Start a process with the specified arguments printing the command at - // verbosity level 3 and higher. Redirect STDOUT to a pipe. If error is - // false, then redirecting STDERR to STDOUT (this can be used to suppress - // diagnostics from the child process). Issue diagnostics and throw failed - // in case of an error. + extern uint16_t verb; // diagnostics.hxx + + void + print_process (const char* const*, size_t); // diagnostics.hxx + + // Search for a process executable. Issue diagnostics and throw failed in + // case of an error. // process_path run_search (const char*& args0); @@ -179,20 +183,88 @@ namespace build2 process_path run_search (const path&, bool init, const dir_path& fallback = dir_path ()); + // Wait for process termination. Issue diagnostics and throw failed in case + // of abnormal termination. If the process has terminated normally but with + // a non-zero exit status, then, if error is true, assume the diagnostics + // has already been issued and throw failed as well. Otherwise (error is + // false), return false. The last argument is used in cooperation with + // run_start() in case STDERR is redirected to STDOUT. + // + bool + run_finish (const char* args[], + process&, + bool error = true, + const string& = string ()); + + inline void + run_finish (cstrings& args, process& pr) + { + run_finish (args.data (), pr); + } + + // Start a process with the specified arguments. If out is -1, redirect + // STDOUT to a pipe. If error is false, then redirecting STDERR to STDOUT + // (this can be used to suppress diagnostics from the child process). Issue + // diagnostics and throw failed in case of an error. + // process - run_start (const process_path&, const char* args[], bool error = true); + run_start (const process_path&, + const char* args[], + int out, + bool error = true, + const dir_path& cwd = dir_path ()); + + inline void + run (const process_path& p, + const char* args[], + const dir_path& cwd = dir_path ()) + { + process pr (run_start (p, args, 1 /* stdout */, true, cwd)); + run_finish (args, pr); + } + inline void + run (const process_path& p, + cstrings& args, + const dir_path& cwd = dir_path ()) + { + run (p, args.data (), cwd); + } + + // As above, but search for the process (including updating args[0]) and + // print the process commands line at the specified verbosity level. + // inline process - run_start (const char* args[], bool error = true) + run_start (uint16_t verbosity, + const char* args[], + int out, + bool error = true, + const dir_path& cwd = dir_path ()) { - return run_start (run_search (args[0]), args, error); + process_path pp (run_search (args[0])); + + if (verb >= verbosity) + print_process (args, 0); + + return run_start (pp, args, out, error, cwd); } - bool - run_finish (const char* args[], - process&, - bool error = true, - const string& = string ()); + inline void + run (uint16_t verbosity, + const char* args[], + const dir_path& cwd = dir_path ()) + { + process pr (run_start (verbosity, args, 1 /* stdout */, true, cwd)); + run_finish (args, pr); + } + + inline void + run (uint16_t verbosity, + cstrings& args, + const dir_path& cwd = dir_path ()) + { + run (verbosity, args.data (), cwd); + } // Start the process as above and then call the specified function on each // trimmed line of the output until it returns a non-empty object T (tested @@ -220,40 +292,50 @@ namespace build2 template inline T - run (const char* args[], + run (uint16_t verbosity, + const char* args[], F&& f, bool error = true, bool ignore_exit = false, sha256* checksum = nullptr) { - return run ( - run_search ( - args[0]), args, forward (f), error, ignore_exit, checksum); + process_path pp (run_search (args[0])); + + if (verb >= verbosity) + print_process (args, 0); + + return run (pp, args, forward (f), error, ignore_exit, checksum); } // run // template inline T - run (const path& prog, + run (uint16_t verb, + const path& prog, F&& f, bool error = true, bool ignore_exit = false, sha256* checksum = nullptr) { const char* args[] = {prog.string ().c_str (), nullptr}; - return run (args, forward (f), error, ignore_exit, checksum); + return run (verb, args, forward (f), error, ignore_exit, checksum); } template inline T - run (const process_path& pp, + run (uint16_t verbosity, + const process_path& pp, F&& f, bool error = true, bool ignore_exit = false, sha256* checksum = nullptr) { const char* args[] = {pp.recall_string (), nullptr}; + + if (verb >= verbosity) + print_process (args, 0); + return run (pp, args, forward (f), error, ignore_exit, checksum); } @@ -261,7 +343,8 @@ namespace build2 // template inline T - run (const path& prog, + run (uint16_t verb, + const path& prog, const char* arg, F&& f, bool error = true, @@ -269,12 +352,13 @@ namespace build2 sha256* checksum = nullptr) { const char* args[] = {prog.string ().c_str (), arg, nullptr}; - return run (args, forward (f), error, ignore_exit, checksum); + return run (verb, args, forward (f), error, ignore_exit, checksum); } template inline T - run (const process_path& pp, + run (uint16_t verbosity, + const process_path& pp, const char* arg, F&& f, bool error = true, @@ -282,6 +366,10 @@ namespace build2 sha256* checksum = nullptr) { const char* args[] = {pp.recall_string (), arg, nullptr}; + + if (verb >= verbosity) + print_process (args, 0); + return run (pp, args, forward (f), error, ignore_exit, checksum); } diff --git a/build2/utility.txx b/build2/utility.txx index d195ea6..6ca245f 100644 --- a/build2/utility.txx +++ b/build2/utility.txx @@ -65,7 +65,7 @@ namespace build2 bool ignore_exit, sha256* checksum) { - process pr (run_start (pp, args, err)); + process pr (run_start (pp, args, -1 /* stdout */, err)); T r; string l; // Last line of output. diff --git a/build2/version/snapshot-git.cxx b/build2/version/snapshot-git.cxx index 9ff1cc9..bf863ce 100644 --- a/build2/version/snapshot-git.cxx +++ b/build2/version/snapshot-git.cxx @@ -30,7 +30,7 @@ namespace build2 { const char* args[] {"git", "-C", d, "status", "--porcelain", nullptr}; - if (!run (args, [] (string& s) {return move (s);}).empty ()) + if (!run (3, args, [](string& s) {return move (s);}).empty ()) return r; } @@ -49,7 +49,7 @@ namespace build2 const char* args[] { "git", "-C", d, "cat-file", "commit", "HEAD", nullptr}; - process pr (run_start (args)); + process pr (run_start (3 /* verbosity */, args, -1 /* stdout */)); try { @@ -116,7 +116,9 @@ namespace build2 // that. } - if (!run_finish (args, pr) || r.sn == 0) + run_finish (args, pr); + + if (r.sn == 0) fail << "unable to extract git commit id/date for " << src_root; sha1 cs; -- cgit v1.1