From a414fa7b0ff469013598ca9ef2999ca6293ee7c1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 24 Sep 2020 10:48:45 +0200 Subject: Add post-boot module function --- libbuild2/file.cxx | 11 +++++++- libbuild2/module.cxx | 27 ++++++++++++++++--- libbuild2/module.hxx | 73 +++++++++++++++++++++++++++++++++++----------------- 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 module; // Module instance (in/out). + + // Convenience functions. + // + template + T& set_module (T* p) {assert (!module); module.reset (p); return *p;} + + template + T& module_as () {assert (module); return static_cast (*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 module; // Module instance (out). - module_boot_init init; // Init mode (out). + module_boot_init init; // Init mode (in/out). - // Convenience functions. - // - template - T& set_module (T* p) {assert (!module); module.reset (p); return *p;} + module_boot_post_extra (const shared_ptr& m, + module_boot_init i) + : module_common_extra {m}, init (i) {} // VC14 + }; - template - T& module_as () {assert (module); return static_cast (*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& 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 module; // Module instance (in/out). - const variable_map& hints; // Configuration hints (see below). - - // Convenience functions. - // - template - T& set_module (T* p) {assert (!module); module.reset (p); return *p;} + const variable_map& hints; // Configuration hints (see below). - template - T& module_as () {assert (module); return static_cast (*module);} + module_init_extra (const shared_ptr& 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 module; optional 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 -- cgit v1.1