From e815af118562c68794efbd310c887acd8eae800c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 24 Jun 2015 13:53:28 +0200 Subject: First take on the cli module plus necessary infrastructure --- build/cli/module.cxx | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 build/cli/module.cxx (limited to 'build/cli/module.cxx') diff --git a/build/cli/module.cxx b/build/cli/module.cxx new file mode 100644 index 0000000..96da40d --- /dev/null +++ b/build/cli/module.cxx @@ -0,0 +1,147 @@ +// file : build/cli/module.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace butl; + +namespace build +{ + namespace cli + { + static compile compile_; + + void + init (scope& root, scope& base, const location& l) + { + //@@ TODO: avoid multiple inits (generally, for modules). + // + tracer trace ("cli::init"); + + //@@ Should it be this way? + // + if (&root != &base) + fail (l) << "cli module must be initialized in project root scope"; + + // Initialize the cxx module. We need its targets types (?xx{}). + // + cxx::init (root, base, l); + + const dir_path& out_root (root.path ()); + level4 ([&]{trace << "for " << out_root;}); + + // Register our target types. + // + target_types.insert (cli::static_type); + target_types.insert (cli_cxx::static_type); + + // Register our rules. + // + rules[default_id][typeid (cli_cxx)].emplace ("cli.compile", compile_); + rules[update_id][typeid (cli_cxx)].emplace ("cli.compile", compile_); + rules[clean_id][typeid (cli_cxx)].emplace ("cli.compile", compile_); + + rules[default_id][typeid (cxx::cxx)].emplace ("cli.compile", compile_); + rules[update_id][typeid (cxx::cxx)].emplace ("cli.compile", compile_); + rules[clean_id][typeid (cxx::cxx)].emplace ("cli.compile", compile_); + + rules[default_id][typeid (cxx::hxx)].emplace ("cli.compile", compile_); + rules[update_id][typeid (cxx::hxx)].emplace ("cli.compile", compile_); + rules[clean_id][typeid (cxx::hxx)].emplace ("cli.compile", compile_); + + rules[default_id][typeid (cxx::ixx)].emplace ("cli.compile", compile_); + rules[update_id][typeid (cxx::ixx)].emplace ("cli.compile", compile_); + rules[clean_id][typeid (cxx::ixx)].emplace ("cli.compile", compile_); + + // Configure. + // + + // config.cli + // + { + auto r (config::required (root, "config.cli", "cli")); + + // If we actually set a new value, test it by trying to execute. + // + if (r.second) + { + const string& cli (r.first); + const char* args[] = {cli.c_str (), "--version", nullptr}; + + if (verb) + print_process (args); + else + text << "test " << cli; + + string ver; + try + { + process pr (args, false, false, true); + ifdstream is (pr.in_ofd); + + for (bool first (true); !is.eof (); ) + { + string l; + getline (is, l); + + if (first) + { + // The version is the last word on the first line. + // + auto p (l.rfind (' ')); + if (p != string::npos) + ver = string (l, p + 1); + + first = false; + } + } + + if (!pr.wait ()) + throw failed (); + + if (ver.empty ()) + fail << "unexpected output from " << cli; + } + catch (const process_error& e) + { + error << "unable to execute " << cli << ": " << e.what (); + + if (e.child ()) + exit (1); + + throw failed (); + } + + if (verb) + text << cli << " " << ver; + } + } + + // config.cli.options + // + // This one is optional. We also merge it into the corresponding + // cli.* variables. + // + if (auto* v = config::optional (root, "config.cli.options")) + root.append ("cli.options") += *v; + } + } +} -- cgit v1.1