diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-06-24 12:01:19 +0200 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2019-07-01 18:13:55 +0300 |
commit | 977d07a3ae47ef204665d1eda2d642e5064724f3 (patch) | |
tree | 525a3d6421f61ce789b690191d3c30fc09be3517 /libbuild2/module.cxx | |
parent | 7161b24963dd9da4d218f92c736b77c35c328a2d (diff) |
Split build system into library and driver
Diffstat (limited to 'libbuild2/module.cxx')
-rw-r--r-- | libbuild2/module.cxx | 147 |
1 files changed, 147 insertions, 0 deletions
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 <libbuild2/module.hxx> + +#include <libbuild2/scope.hxx> +#include <libbuild2/variable.hxx> +#include <libbuild2/diagnostics.hxx> + +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<bool> (lv); + c = cast<bool> (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; + } +} |