diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-01 11:08:13 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-01 11:08:13 +0200 |
commit | 0dee00f28e623830e816c4002c8004c86055df85 (patch) | |
tree | 14c2a2abe241df53821bc585b7adeaff16c768cd /build/cxx/module.cxx | |
parent | 276a0796a97b0a312c0071bba0bf924b5f5c6eee (diff) |
Implement initial C++ configuration support
Diffstat (limited to 'build/cxx/module.cxx')
-rw-r--r-- | build/cxx/module.cxx | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx new file mode 100644 index 0000000..eb7ca40 --- /dev/null +++ b/build/cxx/module.cxx @@ -0,0 +1,134 @@ +// file : build/cxx/module.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include <build/cxx/module> + +#include <istream> +#include <ext/stdio_filebuf.h> + +#include <build/path> +#include <build/scope> +#include <build/process> +#include <build/diagnostics> + +using namespace std; + +namespace build +{ + namespace cxx + { + void + init (scope& root, scope& base, const location& l) + { + //@@ TODO: avoid multiple inits (generally, for modules). + // + + tracer trace ("cxx::init"); + + //@@ Should it be this way? + // + if (&root != &base) + fail (l) << "cxx module must be initialized in project root scope"; + + //@@ TODO: need to register target types, rules here instead of main(). + + const path& out_root (root.path ()); + level4 ([&]{trace << "for " << out_root << '/';}); + + // Configure. + // + + // config.cxx + // + for (bool f (true); f; f = false) + { + auto val (root["config.cxx"]); + + string v; + + if (val) + { + if (&val.scope () != global_scope) + break; // A value from config.build. + + v = val.as<const string&> (); + } + else + v = "g++"; // Default. + + // Test it by trying to execute. + // + const char* args[] = {v.c_str (), "-dumpversion", nullptr}; + + if (verb >= 1) + print_process (args); + else + text << "test " << v; + + string ver; + try + { + process pr (args, false, false, true); + + __gnu_cxx::stdio_filebuf<char> fb (pr.in_ofd, ios_base::in); + istream is (&fb); + + bool r (getline (is, ver)); + + if (!pr.wait ()) + throw failed (); + + if (!r) + fail << "unexpected output from " << v; + } + catch (const process_error& e) + { + error << "unable to execute " << v << ": " << e.what (); + + if (e.child ()) + exit (1); + + throw failed (); + } + + text << "toolchain version " << ver; + + // Set on the project root. + // + root.variables["config.cxx"] = move (v); + } + + // config.cxx.{p,c,l}options + // config.cxx.libs + // + // These are optional so all we need to do is "import" them + // into the root scope if they were specified on the command + // line. + // + if (auto val = root["config.cxx.poptions"]) + { + if (&val.scope () == global_scope) + root.variables["config.cxx.poptions"] = val; + } + + if (auto val = root["config.cxx.coptions"]) + { + if (&val.scope () == global_scope) + root.variables["config.cxx.coptions"] = val; + } + + if (auto val = root["config.cxx.loptions"]) + { + if (&val.scope () == global_scope) + root.variables["config.cxx.loptions"] = val; + } + + if (auto val = root["config.cxx.libs"]) + { + if (&val.scope () == global_scope) + root.variables["config.cxx.libs"] = val; + } + } + } +} |