aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-09-24 10:48:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-09-24 10:59:45 +0200
commita414fa7b0ff469013598ca9ef2999ca6293ee7c1 (patch)
treed0b5b74d026f16a6eec64c4a84f82bb76162f48c
parent9eb84a8134c532029b9f74ced48696994d9c7fc5 (diff)
Add post-boot module function
-rw-r--r--libbuild2/file.cxx11
-rw-r--r--libbuild2/module.cxx27
-rw-r--r--libbuild2/module.hxx73
3 files changed, 84 insertions, 27 deletions
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx
index 67aeb77..14b16a7 100644
--- a/libbuild2/file.cxx
+++ b/libbuild2/file.cxx
@@ -925,7 +925,6 @@ namespace build2
rs.root_extra->project = nullptr;
rs.root_extra->amalgamation = nullptr;
rs.root_extra->subprojects = nullptr;
-
}
// We assume that bootstrap out cannot load this file explicitly. It
// feels wrong to allow this since that makes the whole bootstrap
@@ -1248,6 +1247,16 @@ namespace build2
parser p (root.ctx, load_stage::boot);
source_hooks (p, root, d, false /* pre */);
}
+
+ // Call module's post-boot functions.
+ //
+ for (size_t i (0); i != root.root_extra->modules.size (); ++i)
+ {
+ module_state& s (root.root_extra->modules[i]);
+
+ if (s.boot_post != nullptr)
+ boot_post_module (root, s);
+ }
}
bool
diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx
index 14cf183..b2b4036 100644
--- a/libbuild2/module.cxx
+++ b/libbuild2/module.cxx
@@ -652,10 +652,11 @@ namespace build2
fail (loc) << "build system module " << mod << " should not be loaded "
<< "during bootstrap";
- lm.push_back (module_state {loc, mod, mf->init, nullptr, nullopt});
+ lm.push_back (
+ module_state {loc, mod, nullptr, mf->init, nullptr, nullopt});
i = lm.end () - 1;
- module_boot_extra e {nullptr, module_boot_init::before};
+ module_boot_extra e {nullptr, nullptr, module_boot_init::before};
// Note: boot() can load additional modules invalidating the iterator.
//
@@ -666,12 +667,31 @@ namespace build2
if (e.module != nullptr)
i->module = move (e.module);
+ i->boot_post = e.post;
i->boot_init = e.init;
}
rs.assign (rs.var_pool ().insert (mod + ".booted")) = (mf != nullptr);
}
+ void
+ boot_post_module (scope& rs, module_state& s)
+ {
+ module_boot_post_extra e {s.module, *s.boot_init};
+
+ // Note: boot_post() should be loading any additional modules.
+ //
+ s.boot_post (rs, s.loc, e);
+
+ if (e.module != s.module)
+ {
+ assert (s.module == nullptr);
+ s.module = move (e.module);
+ }
+
+ s.boot_init = e.init;
+ }
+
module_state*
init_module (scope& rs,
scope& bs,
@@ -697,7 +717,8 @@ namespace build2
fail (loc) << "build system module " << mod << " should be loaded "
<< "during bootstrap";
- lm.push_back (module_state {loc, mod, mf->init, nullptr, nullopt});
+ lm.push_back (
+ module_state {loc, mod, nullptr, mf->init, nullptr, nullopt});
i = lm.end () - 1;
}
}
diff --git a/libbuild2/module.hxx b/libbuild2/module.hxx
index 4f69914..770e694 100644
--- a/libbuild2/module.hxx
+++ b/libbuild2/module.hxx
@@ -33,12 +33,27 @@ namespace build2
~module () = default;
};
+ // The module_*_extra arguments in boot and init are used to pass additional
+ // information that is only used by some modules. It is also a way for us to
+ // later pass more information without breaking source compatibility.
+ //
+ struct module_common_extra
+ {
+ shared_ptr<build2::module> module; // Module instance (in/out).
+
+ // Convenience functions.
+ //
+ template <typename T>
+ T& set_module (T* p) {assert (!module); module.reset (p); return *p;}
+
+ template <typename T>
+ T& module_as () {assert (module); return static_cast<T&> (*module);}
+ };
+
// Module boot function signature.
//
- // The module_*_extra arguments (here and in init below) are used to pass
- // additional information that is only used by some modules. It is also a
- // way for us to later pass more information without breaking source
- // compatibility.
+ // A booted module may set the post function which will be called after
+ // booting all the modules in bootstrap.build.
//
// By default a booted module is initialized before loading root.build.
//
@@ -60,18 +75,29 @@ namespace build2
after
};
- struct module_boot_extra
+ struct module_boot_post_extra: module_common_extra
{
- shared_ptr<build2::module> module; // Module instance (out).
- module_boot_init init; // Init mode (out).
+ module_boot_init init; // Init mode (in/out).
- // Convenience functions.
- //
- template <typename T>
- T& set_module (T* p) {assert (!module); module.reset (p); return *p;}
+ module_boot_post_extra (const shared_ptr<build2::module>& m,
+ module_boot_init i)
+ : module_common_extra {m}, init (i) {} // VC14
+ };
- template <typename T>
- T& module_as () {assert (module); return static_cast<T&> (*module);}
+ using module_boot_post_function =
+ void (scope& root,
+ const location&,
+ module_boot_post_extra&);
+
+ struct module_boot_extra: module_common_extra
+ {
+ module_boot_post_function* post; // Post-boot function (out).
+ module_boot_init init; // Init mode (out).
+
+ module_boot_extra (const shared_ptr<build2::module>& m,
+ module_boot_post_function* p,
+ module_boot_init i)
+ : module_common_extra {m}, post (p), init (i) {} // VC14
};
using module_boot_function =
@@ -81,18 +107,13 @@ namespace build2
// Module init function signature.
//
- struct module_init_extra
+ struct module_init_extra: module_common_extra
{
- shared_ptr<build2::module> module; // Module instance (in/out).
- const variable_map& hints; // Configuration hints (see below).
-
- // Convenience functions.
- //
- template <typename T>
- T& set_module (T* p) {assert (!module); module.reset (p); return *p;}
+ const variable_map& hints; // Configuration hints (see below).
- template <typename T>
- T& module_as () {assert (module); return static_cast<T&> (*module);}
+ module_init_extra (const shared_ptr<build2::module>& m,
+ const variable_map& h)
+ : module_common_extra {m}, hints (h) {} // VC14
};
// Return false if the module configuration (normally based on the default
@@ -142,6 +163,7 @@ namespace build2
{
location_value loc; // Load location.
const string name;
+ module_boot_post_function* boot_post;
module_init_function* init;
shared_ptr<build2::module> module;
optional<module_boot_init> boot_init;
@@ -181,6 +203,11 @@ namespace build2
LIBBUILD2_SYMEXPORT void
boot_module (scope& root, const string& name, const location&);
+ // Post-boot the specified (as state) module.
+ //
+ LIBBUILD2_SYMEXPORT void
+ boot_post_module (scope& root, module_state&);
+
// Init the specified module loading its library if necessary. Used by the
// parser but also by some modules to init prerequisite modules. Return a
// pointer to the corresponding module state if the module was both