From d06e8d1d3b0594c74fa444da76c3c7925ed58f70 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 22 Sep 2020 11:28:53 +0200 Subject: Add ability to skip external modules during bootstrap (--no-external-modules) --- libbuild2/context.cxx | 2 ++ libbuild2/context.hxx | 5 +++ libbuild2/file.cxx | 8 ++++- libbuild2/module.cxx | 94 +++++++++++++++++++++++++++++++++------------------ 4 files changed, 75 insertions(+), 34 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx index d62965c..b78cd27 100644 --- a/libbuild2/context.cxx +++ b/libbuild2/context.cxx @@ -59,6 +59,7 @@ namespace build2 context (scheduler& s, global_mutexes& ms, bool mo, + bool nem, bool dr, bool kg, const strings& cmd_vars, @@ -68,6 +69,7 @@ namespace build2 sched (s), mutexes (ms), match_only (mo), + no_external_modules (nem), dry_run_option (dr), keep_going (kg), phase_mutex (*this), diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx index c4e1259..0790355 100644 --- a/libbuild2/context.hxx +++ b/libbuild2/context.hxx @@ -146,6 +146,10 @@ namespace build2 // bool match_only; + // Skip booting external modules flag (see --no-external-modules). + // + bool no_external_modules; + // Dry run flag (see --dry-run|-n). // // This flag is set (based on dry_run_option) only for the final execute @@ -479,6 +483,7 @@ namespace build2 context (scheduler&, global_mutexes&, bool match_only = false, + bool no_external_modules = false, bool dry_run = false, bool keep_going = true, const strings& cmd_vars = {}, diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx index 2660b9e..67aeb77 100644 --- a/libbuild2/file.cxx +++ b/libbuild2/file.cxx @@ -1431,6 +1431,8 @@ namespace build2 { tracer trace ("load_root"); + context& ctx (root.ctx); + const dir_path& out_root (root.out_path ()); const dir_path& src_root (root.src_path ()); @@ -1442,6 +1444,10 @@ namespace build2 if (root.buildfiles.find (f) != root.buildfiles.end ()) return; + if (ctx.no_external_modules) + fail << "attempt to load project " << root << " after skipped loading " + << "external modules"; + // First load outer roots, if any. // if (scope* rs = root.parent_scope ()->root_scope ()) @@ -1483,7 +1489,7 @@ namespace build2 // Reuse the parser to accumulate the configuration variable information. // - parser p (root.ctx, load_stage::root); + parser p (ctx, load_stage::root); if (he) {source_hooks (p, root, hd, true /* pre */); p.reset ();} if (fe) {source_once (p, root, root, f, root);} diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx index 11b32cb..14cf183 100644 --- a/libbuild2/module.cxx +++ b/libbuild2/module.cxx @@ -81,6 +81,7 @@ namespace build2 new context (ctx.sched, ctx.mutexes, false, /* match_only */ + false, /* no_external_modules */ false, /* dry_run */ ctx.keep_going, ctx.global_var_overrides, /* cmd_vars */ @@ -238,7 +239,11 @@ namespace build2 #endif const string& mod, const location& loc, - bool /* boot */, +#if defined(BUILD2_BOOTSTRAP) || defined(LIBBUILD2_STATIC_BUILD) + bool, +#else + bool boot, +#endif bool opt) { tracer trace ("import_module"); @@ -251,6 +256,26 @@ namespace build2 else if (mod == "install") return &install::build2_install_load; else if (mod == "test") return &test::build2_test_load; + module_load_function* r (nullptr); + + // No dynamic loading of build system modules during bootstrap or if + // statically-linked.. + // +#if defined(BUILD2_BOOTSTRAP) || defined(LIBBUILD2_STATIC_BUILD) + if (!opt) + { + fail (loc) << "unknown build system module " << mod << +#ifdef BUILD2_BOOTSTRAP + info << "running bootstrap build system"; +#else + info << "running statically-linked build system"; +#endif + } +#else + context& ctx (bs.ctx); + + bool bundled (bundled_module (mod)); + // Note that importing external modules during bootstrap is problematic // since we haven't loaded config.build nor entered non-global variable // overrides. We used to just not support external modules that require @@ -287,28 +312,20 @@ namespace build2 // And another case is the bdep-sync hook which also doesn't have the // global overrides propagated to it. // - // It does feel right to propagate global overrides to all the nested - // build system invocations. Maybe we should set an environment variable? - - module_load_function* r (nullptr); - - // No dynamic loading of build system modules during bootstrap or if - // statically-linked.. - // -#if defined(BUILD2_BOOTSTRAP) || defined(LIBBUILD2_STATIC_BUILD) - if (!opt) - { - fail (loc) << "unknown build system module " << mod << -#ifdef BUILD2_BOOTSTRAP - info << "running bootstrap build system"; -#else - info << "running statically-linked build system"; -#endif - } -#else - context& ctx (bs.ctx); - - bool bundled (bundled_module (mod)); + // And it turns out the story does not end here: without an external + // module we cannot do info or dist. So to support this we now allow + // skipping of loading of external modules (for dist this is only part of + // the solution with the other part being the bootstrap mode). While no + // doubt a hack, it feels like this is the time to cut of this complexity + // escalation. Essentially, we are saying external module that require + // bootstrap must be prepared to be skipped if the project is only being + // bootstrapped. Note also that the fact that a module boot was skipped + // can be detected by checking the module's *.booted variable. In case of + // a skip it will be false, as opposed to true if the module was booted + // and undefined if the module was not mentioned. + // + if (boot && !bundled && ctx.no_external_modules) + return nullptr; // See if we can import a target for this module. // @@ -570,7 +587,14 @@ namespace build2 << mmod; } else + { + // Reduce skipped external module to optional. + // + if (boot) + opt = true; + i = loaded_modules.emplace (move (mmod), nullptr).first; + } } } @@ -616,23 +640,27 @@ namespace build2 // Otherwise search for this module. // - const module_functions& mf ( - *find_module (rs, mod, loc, true /* boot */, false /* optional */)); + // Note that find_module() may return NULL in case of a skipped external + // module. + // + const module_functions* mf ( + find_module (rs, mod, loc, true /* boot */, false /* optional */)); - if (mf.boot == nullptr) - fail (loc) << "build system module " << mod << " should not be loaded " - << "during bootstrap"; + if (mf != nullptr) + { + if (mf->boot == nullptr) + fail (loc) << "build system module " << mod << " should not be loaded " + << "during bootstrap"; - lm.push_back (module_state {loc, mod, mf.init, nullptr, nullopt}); - i = lm.end () - 1; + lm.push_back (module_state {loc, mod, mf->init, nullptr, nullopt}); + i = lm.end () - 1; - { module_boot_extra e {nullptr, module_boot_init::before}; // Note: boot() can load additional modules invalidating the iterator. // size_t j (i - lm.begin ()); - mf.boot (rs, loc, e); + mf->boot (rs, loc, e); i = lm.begin () + j; if (e.module != nullptr) @@ -641,7 +669,7 @@ namespace build2 i->boot_init = e.init; } - rs.assign (rs.var_pool ().insert (mod + ".booted")) = true; + rs.assign (rs.var_pool ().insert (mod + ".booted")) = (mf != nullptr); } module_state* -- cgit v1.1