aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/module.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/module.hxx')
-rw-r--r--libbuild2/module.hxx120
1 files changed, 120 insertions, 0 deletions
diff --git a/libbuild2/module.hxx b/libbuild2/module.hxx
new file mode 100644
index 0000000..5fbed9c
--- /dev/null
+++ b/libbuild2/module.hxx
@@ -0,0 +1,120 @@
+// file : libbuild2/module.hxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef LIBBUILD2_MODULE_HXX
+#define LIBBUILD2_MODULE_HXX
+
+#include <map>
+
+#include <libbuild2/types.hxx>
+#include <libbuild2/utility.hxx>
+
+#include <libbuild2/variable.hxx>
+#include <libbuild2/diagnostics.hxx>
+
+#include <libbuild2/export.hxx>
+
+namespace build2
+{
+ class scope;
+ class location;
+
+ class module_base
+ {
+ public:
+ virtual
+ ~module_base () = default;
+ };
+
+ // Return true if the module should be initialized first (the order of
+ // initialization within each group is unspecified).
+ //
+ using module_boot_function =
+ bool (scope& root,
+ const location&,
+ unique_ptr<module_base>&);
+
+ // Return false if the module configuration (normally based on the default
+ // values) was unsuccessful but this is not (yet) an error. One example
+ // would be the optional use of a module. Or a module might remain
+ // unconfigured for as long as it is actually not used (e.g., install,
+ // dist). The return value is used to set the <module>.configured variable.
+ //
+ using module_init_function =
+ bool (scope& root,
+ scope& base,
+ const location&,
+ unique_ptr<module_base>&,
+ bool first, // First time for this project.
+ bool optional, // Loaded with using? (optional module).
+ const variable_map& hints); // Configuration hints (see below).
+
+ struct module_functions
+ {
+ module_boot_function* boot;
+ module_init_function* init;
+ };
+
+ // The register() function will be written in C++ and will be called from
+ // C++ but we need to suppress name mangling to be able to use dlsym() and
+ // equivalent.
+ //
+ extern "C"
+ using module_register_function = module_functions ();
+
+ // Loaded modules state.
+ //
+ struct module_state
+ {
+ bool boot; // True if the module boot'ed but not yet init'ed.
+ bool first; // True if the boot'ed module must be init'ed first.
+ module_init_function* init;
+ unique_ptr<module_base> module;
+ const location loc; // Boot location.
+ };
+
+ struct loaded_module_map: std::map<string, module_state>
+ {
+ template <typename T>
+ T*
+ lookup (const string& name) const
+ {
+ auto i (find (name));
+ return i != end ()
+ ? static_cast<T*> (i->second.module.get ())
+ : nullptr;
+ }
+ };
+
+ // Load and boot the specified module.
+ //
+ LIBBUILD2_SYMEXPORT void
+ boot_module (scope& root, const string& name, const location&);
+
+ // Load (if not already loaded) and initialize the specified module. Used
+ // by the parser but also by some modules to load prerequisite modules.
+ // Return true if the module was both successfully loaded and configured
+ // (false can only be returned if optional).
+ //
+ // The config_hints variable map can be used to pass configuration hints
+ // from one module to another. For example, the cxx modude may pass the
+ // target platform (which was extracted from the C++ compiler) to the bin
+ // module (which may not always be able to extract the same information from
+ // its tools).
+ //
+ LIBBUILD2_SYMEXPORT bool
+ load_module (scope& root,
+ scope& base,
+ const string& name,
+ const location&,
+ bool optional = false,
+ const variable_map& config_hints = variable_map ());
+
+ // Builtin modules.
+ //
+ using available_module_map = std::map<string, module_functions>;
+ LIBBUILD2_SYMEXPORT extern available_module_map builtin_modules;
+}
+
+#endif // LIBBUILD2_MODULE_HXX