From 8ac1daf33da807635eddd881f2b178af8e22863a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 12 Nov 2019 14:51:02 +0200 Subject: Infra work for customizable config var persistence (config.config.persist) --- libbuild2/bin/init.cxx | 2 +- libbuild2/config/init.cxx | 35 ++++++++++++++++---- libbuild2/config/module.hxx | 4 +++ libbuild2/config/operation.cxx | 74 +++++++++++++++++++++++------------------- libbuild2/config/utility.hxx | 1 + 5 files changed, 75 insertions(+), 41 deletions(-) diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx index 68b5fb4..1e5ccc5 100644 --- a/libbuild2/bin/init.cxx +++ b/libbuild2/bin/init.cxx @@ -120,7 +120,7 @@ namespace build2 // // If unspecified, defaults to false for liba{} and to true for libu*{}. // - vp.insert ("bin.whole", false, vis_tgt); + vp.insert ("bin.whole", vis_tgt); vp.insert ("bin.exe.prefix"); vp.insert ("bin.exe.suffix"); diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 9fc914c..1f053e9 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -47,14 +47,23 @@ namespace build2 // auto& vp (rs.ctx.var_pool.rw (rs)); - // While config.config.load could theoretically be specified in a - // buildfile, config.config.save is expected to always be specified as a - // command line override. + // While config.config.load (see below) could theoretically be specified + // in a buildfile, config.config.save is expected to always be specified + // as a command line override. // // Note: must be entered during bootstrap since we need it in // configure_execute(). // - vp.insert ("config.config.save", true /* ovr */); + vp.insert ("config.config.save", true /* ovr */); + + // @@ TODO + // + // Use the NULL value to clear. + // + auto& c_p (vp.insert>> ( + "config.config.persist", + true /* ovr */, + variable_visibility::project)); // Only create the module if we are configuring or creating or if it was // requested with config.config.module (useful if we need to call @@ -78,11 +87,14 @@ namespace build2 unique_ptr m (new module); - // Adjust priority for the import pseudo-module so that - // config.import.* values come first in config.build. + // Adjust priority for the config module and import pseudo-module so + // that their variables come first in config.build. // + m->save_module ("config", INT32_MIN); m->save_module ("import", INT32_MIN); + m->save_variable (c_p, omit_null); + mod = move (m); } @@ -109,7 +121,7 @@ namespace build2 init (scope& rs, scope&, const location& l, - unique_ptr&, + unique_ptr& mod, bool first, bool, const variable_map& config_hints) @@ -224,6 +236,15 @@ namespace build2 } } + // Cache the config.config.persist value, if any. + // + if (mod != nullptr) + { + static_cast (*mod).persist = + cast_null>> ( + rs["config.config.persist"]); + } + // Register alias and fallback rule for the configure meta-operation. // // We need this rule for out-of-any-project dependencies (e.g., diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx index 296dec5..eccd61b 100644 --- a/libbuild2/config/module.hxx +++ b/libbuild2/config/module.hxx @@ -86,6 +86,10 @@ namespace build2 bool save_module (const char* name, int prio = 0); + // Cached (during init) config.config.persist value, if defined. + // + const vector>* persist = nullptr; + static const string name; static const uint64_t version; }; diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index 21bf8c1..5f1c8cd 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -85,20 +85,18 @@ namespace build2 using project_set = set; // Use pointers to get comparison. - // Mark all the config.import.* variables defined in this variable map as - // saved optionally issuing a warning if the variable would otherwise be - // unsaved. + // Mark all the config.import.* variables defined on this scope as saved + // optionally warning if the variable would otherwise be dropped. // static void - save_config_import (context& ctx, - module& m, - const variable_map& vars, - bool warning = false, - const location& loc = location ()) + save_config_import (module& m, + const scope& rs, + const location& loc, + bool warning) { - auto& vp (ctx.var_pool); + auto& vp (rs.ctx.var_pool); - for (auto p (vars.find_namespace (*vp.find ("config.import"))); + for (auto p (rs.vars.find_namespace (*vp.find ("config.import"))); p.first != p.second; ++p.first) { @@ -111,7 +109,22 @@ namespace build2 var = vp.find (string (var->name, 0, n)); if (m.save_variable (*var) && warning) + { + // Consistently with save_config() below we don't warn about an + // overriden variable. + // + if (var->overrides != nullptr) + { + lookup l {p.first->second, *var, rs.vars}; + pair org {l, 1 /* depth */}; + pair ovr (rs.find_override (*var, org)); + + if (org.first != ovr.first) + continue; + } + warn (loc) << "keeping potentially no longer used variable " << *var; + } } } @@ -155,8 +168,8 @@ namespace build2 } } - // Mark all the config.import.* variables defined on our root scope as - // saved. + // Pre-mark all the config.import.* variables defined on our root + // scope as saved. // // This is in contrast to module-specific config variables (and later // probably to project-specific) where by default we drop no longer @@ -168,7 +181,8 @@ namespace build2 // // Note that in the future we may make these defaults configurable. // - save_config_import (ctx, *mod, rs.vars, true /* warn */, location (on)); + if (mod->persist) //@@ TMP + save_config_import (*mod, rs, location (on), false /* warn */); // Save config variables. // @@ -195,7 +209,7 @@ namespace build2 // inherited. We might also not have any value at all (see // unconfigured()). // - if (!l.defined ()) + if (!l.defined () || (l->null && sv.flags & omit_null)) continue; // Handle inherited from outer scope values. @@ -256,7 +270,7 @@ namespace build2 // outer project is reconfigured). Feels like this will // be quite obscure and error-prone. // - if (!found) + if (!found && m->persist) //@@ TMP found = var.name.compare (0, 14, "config.import.") == 0; // Handle that other case: if this is an override but @@ -504,8 +518,8 @@ namespace build2 dir_path out_nroot (out_root / pd); const scope& nrs (ctx.scopes.find (out_nroot)); - // @@ Strictly speaking we need to check whether the config - // module was loaded for this subproject. + // @@ Strictly speaking we need to check whether the config module + // was loaded for this subproject. // if (nrs.out_path () != out_nroot) // This subproject not loaded. continue; @@ -1002,29 +1016,23 @@ namespace build2 { // Since there aren't any sub-projects yet, any config.import.* values // that the user may want to specify won't be saved in config.build. So - // let's go ahead and mark them all to be saved. To do this, however, we - // need the config module (which is where this information is stored). - // And the module is created by init() during bootstrap. So what we are - // going to do is bootstrap the newly created project, similar to the - // way main() does it. + // we go ahead and add them to config.config.persist (unless overriden). + // To do this, however, we need the project's root scope (which is where + // this information is stored). So what we are going to do is bootstrap + // the newly created project, similar to the way main() does it. // scope& gs (ctx.global_scope.rw ()); scope& rs (load_project (gs, d, d, false /* fwd */, false /* load */)); - module& m (*rs.lookup_module (module::name)); - // Save all the global config.import.* variables. + // Add the default config.config.persist value unless there is a custom + // one (specified as a command line override). // - save_config_import (ctx, m, gs.vars); + const variable& var (*ctx.var_pool.find ("config.config.persist")); - // Now project-specific. For now we just save all of them and let - // save_config() above weed out the ones that do not apply. - // - for (const variable_override& vo: ctx.var_overrides) + if (!rs[var].defined ()) { - const variable& var (vo.var); - - if (var.name.compare (0, 14, "config.import.") == 0) - m.save_variable (var); + rs.assign (var) = vector> { + pair {"config.import.*", "unused=keep"}}; } } diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx index 2a0909f..7774b68 100644 --- a/libbuild2/config/utility.hxx +++ b/libbuild2/config/utility.hxx @@ -143,6 +143,7 @@ namespace build2 // config::module for details. // const uint64_t save_commented = 0x01; // Save default value as commented. + const uint64_t omit_null = 0x02; // Treat NULL as undefined. LIBBUILD2_SYMEXPORT void save_variable (scope& root, const variable&, uint64_t flags = 0); -- cgit v1.1