// file : build2/utility.txx -*- C++ -*- // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file namespace build2 { template void append_option_values (cstrings& args, const char* o, I b, I e, F&& get) { if (b != e) { args.reserve (args.size () + (e - b)); for (; b != e; ++b) { args.push_back (o); args.push_back (get (*b)); } } } template void hash_option_values (sha256& cs, const char* o, I b, I e, F&& get) { for (; b != e; ++b) { cs.append (o); cs.append (get (*b)); } } template basic_path relative (const basic_path& p) { typedef basic_path path; const dir_path& b (*relative_base); if (p.simple () || b.empty ()) return p; if (p.sub (b)) return p.leaf (b); if (p.root_directory () == b.root_directory ()) { path r (p.relative (b)); if (r.string ().size () < p.string ().size ()) return r; } return p; } template T run (uint16_t verbosity, const process_env& pe, const char* args[], F&& f, bool err, bool ignore_exit, sha256* checksum) { process pr (run_start (verbosity, pe, args, 0 /* stdin */, -1 /* stdout */, err)); T r; string l; // Last line of output. try { ifdstream is (move (pr.in_ofd), butl::fdstream_mode::skip); // Make sure we keep the last line. // for (bool last (is.peek () == ifdstream::traits_type::eof ()); !last && getline (is, l); ) { last = (is.peek () == ifdstream::traits_type::eof ()); trim (l); if (checksum != nullptr) checksum->append (l); if (r.empty ()) { r = f (l, last); if (!r.empty () && checksum == nullptr) break; } } is.close (); } catch (const io_error&) { // Presumably the child process failed. Let run_finish() deal with that. } if (!(run_finish (args, pr, err, l) || ignore_exit)) r = T (); return r; } }