aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-11-12 14:51:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-11-12 14:51:02 +0200
commit8ac1daf33da807635eddd881f2b178af8e22863a (patch)
tree3a3e91538f4665b0d721bc91d935eb01a5a3b61d
parent8725010c51811c7ff91013e2caca3c45ea96b371 (diff)
Infra work for customizable config var persistence (config.config.persist)
-rw-r--r--libbuild2/bin/init.cxx2
-rw-r--r--libbuild2/config/init.cxx35
-rw-r--r--libbuild2/config/module.hxx4
-rw-r--r--libbuild2/config/operation.cxx74
-rw-r--r--libbuild2/config/utility.hxx1
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<bool> ("bin.whole", false, vis_tgt);
+ vp.insert<bool> ("bin.whole", vis_tgt);
vp.insert<string> ("bin.exe.prefix");
vp.insert<string> ("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<path> ("config.config.save", true /* ovr */);
+ vp.insert<path> ("config.config.save", true /* ovr */);
+
+ // @@ TODO
+ //
+ // Use the NULL value to clear.
+ //
+ auto& c_p (vp.insert<vector<pair<string, string>>> (
+ "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<module> 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<module_base>&,
+ unique_ptr<module_base>& 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<module&> (*mod).persist =
+ cast_null<vector<pair<string, string>>> (
+ 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<pair<string, string>>* 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<const scope*>; // 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<lookup, size_t> org {l, 1 /* depth */};
+ pair<lookup, size_t> 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> (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<string, string>> {
+ pair<string, string> {"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);