aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility.txx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/utility.txx')
-rw-r--r--bpkg/utility.txx98
1 files changed, 98 insertions, 0 deletions
diff --git a/bpkg/utility.txx b/bpkg/utility.txx
new file mode 100644
index 0000000..f830478
--- /dev/null
+++ b/bpkg/utility.txx
@@ -0,0 +1,98 @@
+// file : bpkg/utility.txx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <libbutl/small-vector.mxx>
+
+#include <bpkg/diagnostics.hxx>
+
+namespace bpkg
+{
+ // *_b()
+ //
+ template <typename O, typename E, typename... A>
+ process
+ start_b (const common_options& co,
+ O&& out,
+ E&& err,
+ verb_b v,
+ A&&... args)
+ {
+ const char* b (name_b (co));
+
+ try
+ {
+ // Use our executable directory as a fallback search since normally the
+ // entire toolchain is installed into one directory. This way, for
+ // example, if we installed into /opt/build2 and run bpkg with absolute
+ // path (and without PATH), then bpkg will be able to find "its" b.
+ //
+ process_path pp (process::path_search (b, exec_dir));
+
+ butl::small_vector<const char*, 1> ops;
+
+ // Map verbosity level. If we are running quiet or at level 1,
+ // then run build2 quiet. Otherwise, run it at the same level
+ // as us.
+ //
+ string vl;
+
+ if (verb == 0)
+ ops.push_back ("-q");
+ else if (verb == 1)
+ {
+ if (v != verb_b::normal)
+ {
+ ops.push_back ("-q");
+
+ if (v == verb_b::progress && stderr_term)
+ ops.push_back ("--progress");
+ }
+ }
+ else if (verb == 2)
+ ops.push_back ("-v");
+ else
+ {
+ vl = to_string (verb);
+ ops.push_back ("--verbose");
+ ops.push_back (vl.c_str ());
+ }
+
+ return process_start_callback (
+ [] (const char* const args[], size_t n)
+ {
+ if (verb >= 2)
+ print_process (args, n);
+ },
+ 0 /* stdin */,
+ forward<O> (out),
+ forward<E> (err),
+ pp,
+ ops,
+ co.build_option (),
+ forward<A> (args)...);
+ }
+ catch (const process_error& e)
+ {
+ fail << "unable to execute " << b << ": " << e << endf;
+ }
+ }
+
+ template <typename... A>
+ void
+ run_b (const common_options& co, verb_b v, A&&... args)
+ {
+ process pr (
+ start_b (co, 1 /* stdout */, 2 /* stderr */, v, forward<A> (args)...));
+
+ if (!pr.wait ())
+ {
+ const process_exit& e (*pr.exit);
+
+ if (e.normal ())
+ throw failed (); // Assume the child issued diagnostics.
+
+ fail << "process " << name_b (co) << " " << e;
+ }
+ }
+}