From 977d07a3ae47ef204665d1eda2d642e5064724f3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 24 Jun 2019 12:01:19 +0200 Subject: Split build system into library and driver --- libbuild2/module.cxx | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 libbuild2/module.cxx (limited to 'libbuild2/module.cxx') diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx new file mode 100644 index 0000000..50530f2 --- /dev/null +++ b/libbuild2/module.cxx @@ -0,0 +1,147 @@ +// file : libbuild2/module.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include + +using namespace std; + +namespace build2 +{ + available_module_map builtin_modules; + + void + boot_module (scope& rs, const string& name, const location& loc) + { + // First see if this modules has already been loaded for this project. + // + loaded_module_map& lm (rs.root_extra->modules); + auto i (lm.find (name)); + + if (i != lm.end ()) + { + module_state& s (i->second); + + // The only valid situation here is if the module has already been + // bootstrapped. + // + assert (s.boot); + return; + } + + // Otherwise search for this module. + // + auto j (builtin_modules.find (name)); + + if (j == builtin_modules.end ()) + fail (loc) << "unknown module " << name; + + const module_functions& mf (j->second); + + if (mf.boot == nullptr) + fail (loc) << "module " << name << " shouldn't be loaded in bootstrap"; + + i = lm.emplace (name, + module_state {true, false, mf.init, nullptr, loc}).first; + i->second.first = mf.boot (rs, loc, i->second.module); + + rs.assign (var_pool.rw (rs).insert (name + ".booted")) = true; + } + + bool + load_module (scope& rs, + scope& bs, + const string& name, + const location& loc, + bool opt, + const variable_map& hints) + { + // First see if this modules has already been loaded for this project. + // + loaded_module_map& lm (rs.root_extra->modules); + auto i (lm.find (name)); + bool f (i == lm.end ()); + + if (f) + { + // Otherwise search for this module. + // + auto j (builtin_modules.find (name)); + + if (j == builtin_modules.end ()) + { + if (!opt) + fail (loc) << "unknown module " << name; + } + else + { + const module_functions& mf (j->second); + + if (mf.boot != nullptr) + fail (loc) << "module " << name << " should be loaded in bootstrap"; + + i = lm.emplace ( + name, + module_state {false, false, mf.init, nullptr, loc}).first; + } + } + else + { + module_state& s (i->second); + + if (s.boot) + { + s.boot = false; + f = true; // This is a first call to init. + } + } + + // Note: pattern-typed in context.cxx:reset() as project-visibility + // variables of type bool. + // + auto& vp (var_pool.rw (rs)); + value& lv (bs.assign (vp.insert (name + ".loaded"))); + value& cv (bs.assign (vp.insert (name + ".configured"))); + + bool l; // Loaded. + bool c; // Configured. + + // Suppress duplicate init() calls for the same module in the same scope. + // + if (!lv.null) + { + assert (!cv.null); + + l = cast (lv); + c = cast (cv); + + if (!opt) + { + if (!l) + fail (loc) << "unknown module " << name; + + // We don't have original diagnostics. We could call init() again so + // that it can issue it. But that means optional modules must be + // prepared to be called again if configuring failed. Let's keep it + // simple for now. + // + if (!c) + fail (loc) << "module " << name << " failed to configure"; + } + } + else + { + l = i != lm.end (); + c = l && i->second.init (rs, bs, loc, i->second.module, f, opt, hints); + + lv = l; + cv = c; + } + + return l && c; + } +} -- cgit v1.1