aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-12-16 17:42:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-12-16 17:42:12 +0200
commitae5cab7489fe014dd3aa818cf2655d7a4714af83 (patch)
treea80fdc22ce5909b98bd58292aaf8e2bc28e70492
parent530e8914ba00ce0e7ee89ba30d2b88f2c09f43c9 (diff)
Improve process execution diagnostics by reusing run_*() API
-rw-r--r--build2/bin/guess.cxx18
-rw-r--r--build2/bin/init.cxx3
-rw-r--r--build2/cc/compile.cxx14
-rw-r--r--build2/cc/gcc.cxx66
-rw-r--r--build2/cc/guess.cxx18
-rw-r--r--build2/cc/link.cxx25
-rw-r--r--build2/cc/module.cxx3
-rw-r--r--build2/cc/msvc.cxx5
-rw-r--r--build2/cli/init.cxx2
-rw-r--r--build2/cli/rule.cxx20
-rw-r--r--build2/context.cxx2
-rw-r--r--build2/dist/operation.cxx65
-rw-r--r--build2/install/rule.cxx131
-rw-r--r--build2/utility.cxx49
-rw-r--r--build2/utility.hxx134
-rw-r--r--build2/utility.txx2
-rw-r--r--build2/version/snapshot-git.cxx8
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<guess_result> (arp, "--version", f, false, false, &cs);
+ arr = run<guess_result> (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<guess_result> (arp, f, false, true, &cs);
+ arr = run<guess_result> (3, arp, f, false, true, &cs);
if (!arr.empty ())
{
@@ -142,7 +142,7 @@ namespace build2
};
sha256 cs;
- rlr = run<guess_result> (rlp, "--version", f, false, false, &cs);
+ rlr = run<guess_result> (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<guess_result> (rlp, f, false, true, &cs);
+ rlr = run<guess_result> (3, rlp, f, false, true, &cs);
if (!rlr.empty ())
{
@@ -224,7 +224,7 @@ namespace build2
// but that seems harmless.
//
sha256 cs;
- r = run<guess_result> (pp, "--version", f, false, true, &cs);
+ r = run<guess_result> (3, pp, "--version", f, false, true, &cs);
if (!r.empty ())
r.checksum = cs.string ();
@@ -255,7 +255,7 @@ namespace build2
};
sha256 cs;
- r = run<guess_result> (pp, "-v", f, false, false, &cs);
+ r = run<guess_result> (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<guess_result> (pp, "-version", f, false, false, &cs);
+ r = run<guess_result> (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<guess_result> (pp, "--version", f, false, false, &cs);
+ r = run<guess_result> (3, pp, "--version", f, false, false, &cs);
if (!r.empty ())
r.checksum = cs.string ();
@@ -342,7 +342,7 @@ namespace build2
};
sha256 cs;
- r = run<guess_result> (pp, "/?", f, false, false, &cs);
+ r = run<guess_result> (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<string> (ops.config_sub (),
+ s = run<string> (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 "<name>: =" 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 "<name>: =" 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<guess_result> (pp, "-v", f, false, false, &cs);
+ r = run<guess_result> (3, pp, "-v", f, false, false, &cs);
if (!r.empty ())
{
@@ -284,7 +284,7 @@ namespace build2
return guess_result ();
};
- r = run<guess_result> (pp, "--version", f, false);
+ r = run<guess_result> (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<guess_result> (pp, f, false);
+ r = run<guess_result> (3, pp, f, false);
}
if (!r.empty ())
@@ -487,7 +487,7 @@ namespace build2
//
auto f = [] (string& l) {return move (l);};
- string t (run<string> (args.data (), f, false));
+ string t (run<string> (3, args.data (), f, false));
if (t.empty ())
{
@@ -495,7 +495,7 @@ namespace build2
<< "falling back to -dumpmachine";});
args[1] = "-dumpmachine";
- t = run<string> (args.data (), f);
+ t = run<string> (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<string> (args.data (), [] (string& l) {return move (l);}));
+ string t (run<string> (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<string> (xc, "-V", f, false);
+ s = run<string> (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<string> (args.data (), f, false));
+ string t (run<string> (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<string> (xc, "-dumpmachine", [] (string& l) {return move (l);});
+ t = run<string> (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<string> (ops.config_sub (),
+ ct = run<string> (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<string> (ops.config_guess (), [] (string& l) {return move (l);})
+ ? run<string> (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 <file> <dir>
@@ -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 <file> <dir>/
@@ -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 <typename T, typename F>
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<T> (
- run_search (
- args[0]), args, forward<F> (f), error, ignore_exit, checksum);
+ process_path pp (run_search (args[0]));
+
+ if (verb >= verbosity)
+ print_process (args, 0);
+
+ return run<T> (pp, args, forward<F> (f), error, ignore_exit, checksum);
}
// run <prog>
//
template <typename T, typename F>
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<T> (args, forward<F> (f), error, ignore_exit, checksum);
+ return run<T> (verb, args, forward<F> (f), error, ignore_exit, checksum);
}
template <typename T, typename F>
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<T> (pp, args, forward<F> (f), error, ignore_exit, checksum);
}
@@ -261,7 +343,8 @@ namespace build2
//
template <typename T, typename F>
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<T> (args, forward<F> (f), error, ignore_exit, checksum);
+ return run<T> (verb, args, forward<F> (f), error, ignore_exit, checksum);
}
template <typename T, typename F>
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<T> (pp, args, forward<F> (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<string> (args, [] (string& s) {return move (s);}).empty ())
+ if (!run<string> (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;