aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-03-30 15:30:08 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-03-31 07:32:46 +0200
commitdfb51bc816cde2cb345f8a0300205e6ac95a2065 (patch)
treead5996b87bb3829f7058aa990fab65940b575249 /libbuild2
parent65340a0a897c91b580db1de0bab026a0814c5d74 (diff)
Switch to project variable visibility by default
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/bin/init.cxx57
-rw-r--r--libbuild2/c/init.cxx24
-rw-r--r--libbuild2/cc/init.cxx24
-rw-r--r--libbuild2/cc/module.cxx9
-rw-r--r--libbuild2/config/init.cxx6
-rw-r--r--libbuild2/context.cxx180
-rw-r--r--libbuild2/cxx/init.cxx41
-rw-r--r--libbuild2/dist/init.cxx15
-rw-r--r--libbuild2/functions-builtin.cxx2
-rw-r--r--libbuild2/install/init.cxx18
-rw-r--r--libbuild2/module.cxx2
-rw-r--r--libbuild2/parser.cxx5
-rw-r--r--libbuild2/scope.cxx4
-rw-r--r--libbuild2/scope.hxx20
-rw-r--r--libbuild2/test/init.cxx24
-rw-r--r--libbuild2/test/script/parser.test.cxx3
-rw-r--r--libbuild2/variable.cxx43
-rw-r--r--libbuild2/variable.hxx48
-rw-r--r--libbuild2/version/init.cxx12
19 files changed, 289 insertions, 248 deletions
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index 25d5c39..c97cadf 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -50,45 +50,42 @@ namespace build2
assert (first);
- // Enter variables. Note: some overridable, some not.
+ // Enter variables.
//
// Target is a string and not target_triplet because it can be
// specified by the user.
//
auto& vp (rs.var_pool ());
- const auto vis_tgt (variable_visibility::target);
- const auto vis_prj (variable_visibility::project);
-
- vp.insert<string> ("config.bin.target", true);
- vp.insert<string> ("config.bin.pattern", true);
+ vp.insert<string> ("config.bin.target");
+ vp.insert<string> ("config.bin.pattern");
// Library types to build.
//
- vp.insert<string> ("config.bin.lib", true);
+ vp.insert<string> ("config.bin.lib");
// Library types to use (in priority order).
//
- vp.insert<strings> ("config.bin.exe.lib", true);
- vp.insert<strings> ("config.bin.liba.lib", true);
- vp.insert<strings> ("config.bin.libs.lib", true);
+ vp.insert<strings> ("config.bin.exe.lib");
+ vp.insert<strings> ("config.bin.liba.lib");
+ vp.insert<strings> ("config.bin.libs.lib");
// The rpath[_link].auto flag controls automatic rpath behavior, for
// example, addition of rpaths for prerequisite libraries (see the cc
// module for an example). Default is true.
//
- vp.insert<dir_paths> ("config.bin.rpath", true);
- vp.insert<bool> ("config.bin.rpath.auto", true);
+ vp.insert<dir_paths> ("config.bin.rpath");
+ vp.insert<bool> ("config.bin.rpath.auto");
- vp.insert<dir_paths> ("config.bin.rpath_link", true);
- vp.insert<bool> ("config.bin.rpath_link.auto", true);
+ vp.insert<dir_paths> ("config.bin.rpath_link");
+ vp.insert<bool> ("config.bin.rpath_link.auto");
- vp.insert<string> ("config.bin.prefix", true);
- vp.insert<string> ("config.bin.suffix", true);
- vp.insert<string> ("config.bin.lib.prefix", true);
- vp.insert<string> ("config.bin.lib.suffix", true);
- vp.insert<string> ("config.bin.exe.prefix", true);
- vp.insert<string> ("config.bin.exe.suffix", true);
+ vp.insert<string> ("config.bin.prefix");
+ vp.insert<string> ("config.bin.suffix");
+ vp.insert<string> ("config.bin.lib.prefix");
+ vp.insert<string> ("config.bin.lib.suffix");
+ vp.insert<string> ("config.bin.exe.prefix");
+ vp.insert<string> ("config.bin.exe.suffix");
vp.insert<string> ("bin.lib");
@@ -102,7 +99,7 @@ namespace build2
vp.insert<dir_paths> ("bin.rpath_link");
vp.insert<bool> ("bin.rpath_link.auto");
- // Link whole archive. Note: non-overridable with target visibility.
+ // Link whole archive. Note: with target visibility.
//
// The lookup semantics is as follows: we first look for a prerequisite-
// specific value, then for a target-specific value in the library being
@@ -118,7 +115,7 @@ namespace build2
//
// If unspecified, defaults to false for liba{} and to true for libu*{}.
//
- vp.insert<bool> ("bin.whole", vis_tgt);
+ vp.insert<bool> ("bin.whole", variable_visibility::target);
vp.insert<string> ("bin.exe.prefix");
vp.insert<string> ("bin.exe.suffix");
@@ -131,11 +128,11 @@ namespace build2
// only used for platform-independent versions (for platforms-specific
// versions we can always derive the pattern automatically).
//
- vp.insert<string> ("bin.lib.load_suffix", vis_prj);
- vp.insert<string> ("bin.lib.load_suffix_pattern", vis_prj);
+ vp.insert<string> ("bin.lib.load_suffix");
+ vp.insert<string> ("bin.lib.load_suffix_pattern");
- vp.insert<map<string, string>> ("bin.lib.version", vis_prj);
- vp.insert<string> ("bin.lib.version_pattern", vis_prj);
+ vp.insert<map<string, string>> ("bin.lib.version");
+ vp.insert<string> ("bin.lib.version_pattern");
return true;
}
@@ -580,8 +577,8 @@ namespace build2
vp.insert<process_path> ("bin.ar.path");
vp.insert<process_path> ("bin.ranlib.path");
- vp.insert<path> ("config.bin.ar", true);
- vp.insert<path> ("config.bin.ranlib", true);
+ vp.insert<path> ("config.bin.ar");
+ vp.insert<path> ("config.bin.ranlib");
}
// Configuration.
@@ -745,7 +742,7 @@ namespace build2
auto& vp (rs.var_pool ());
vp.insert<process_path> ("bin.ld.path");
- vp.insert<path> ("config.bin.ld", true);
+ vp.insert<path> ("config.bin.ld");
}
// Configuration.
@@ -881,7 +878,7 @@ namespace build2
auto& vp (rs.var_pool ());
vp.insert<process_path> ("bin.rc.path");
- vp.insert<path> ("config.bin.rc", true);
+ vp.insert<path> ("config.bin.rc");
}
// Configuration.
diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx
index ffea0ca..e6e28aa 100644
--- a/libbuild2/c/init.cxx
+++ b/libbuild2/c/init.cxx
@@ -163,20 +163,18 @@ namespace build2
hinters,
- // Note: some overridable, some not.
- //
// NOTE: remember to update documentation if changing anything here.
//
- vp.insert<strings> ("config.c", true),
- vp.insert<string> ("config.c.id", true),
- vp.insert<string> ("config.c.version", true),
- vp.insert<string> ("config.c.target", true),
- vp.insert<string> ("config.c.std", true),
- vp.insert<strings> ("config.c.poptions", true),
- vp.insert<strings> ("config.c.coptions", true),
- vp.insert<strings> ("config.c.loptions", true),
- vp.insert<strings> ("config.c.aoptions", true),
- vp.insert<strings> ("config.c.libs", true),
+ vp.insert<strings> ("config.c"),
+ vp.insert<string> ("config.c.id"),
+ vp.insert<string> ("config.c.version"),
+ vp.insert<string> ("config.c.target"),
+ vp.insert<string> ("config.c.std"),
+ vp.insert<strings> ("config.c.poptions"),
+ vp.insert<strings> ("config.c.coptions"),
+ vp.insert<strings> ("config.c.loptions"),
+ vp.insert<strings> ("config.c.aoptions"),
+ vp.insert<strings> ("config.c.libs"),
nullptr /* config.c.translatable_headers */,
vp.insert<process_path> ("c.path"),
@@ -184,7 +182,7 @@ namespace build2
vp.insert<dir_paths> ("c.sys_lib_dirs"),
vp.insert<dir_paths> ("c.sys_inc_dirs"),
- vp.insert<string> ("c.std", variable_visibility::project),
+ vp.insert<string> ("c.std"),
vp.insert<strings> ("c.poptions"),
vp.insert<strings> ("c.coptions"),
diff --git a/libbuild2/cc/init.cxx b/libbuild2/cc/init.cxx
index 723b678..8d66376 100644
--- a/libbuild2/cc/init.cxx
+++ b/libbuild2/cc/init.cxx
@@ -74,7 +74,7 @@ namespace build2
//
load_module (rs, rs, "bin.vars", loc);
- // Enter variables. Note: some overridable, some not.
+ // Enter variables.
//
auto& vp (rs.var_pool ());
@@ -82,11 +82,11 @@ namespace build2
// NOTE: remember to update documentation if changing anything here.
//
- vp.insert<strings> ("config.cc.poptions", true);
- vp.insert<strings> ("config.cc.coptions", true);
- vp.insert<strings> ("config.cc.loptions", true);
- vp.insert<strings> ("config.cc.aoptions", true);
- vp.insert<strings> ("config.cc.libs", true);
+ vp.insert<strings> ("config.cc.poptions");
+ vp.insert<strings> ("config.cc.coptions");
+ vp.insert<strings> ("config.cc.loptions");
+ vp.insert<strings> ("config.cc.aoptions");
+ vp.insert<strings> ("config.cc.libs");
vp.insert<strings> ("cc.poptions");
vp.insert<strings> ("cc.coptions");
@@ -101,11 +101,11 @@ namespace build2
// Hint variables (not overridable).
//
- vp.insert<string> ("config.cc.id");
- vp.insert<string> ("config.cc.hinter"); // Hinting module.
- vp.insert<string> ("config.cc.pattern");
- vp.insert<strings> ("config.cc.mode");
- vp.insert<target_triplet> ("config.cc.target");
+ vp.insert<string> ("config.cc.id", false);
+ vp.insert<string> ("config.cc.hinter", false); // Hinting module.
+ vp.insert<string> ("config.cc.pattern", false);
+ vp.insert<strings> ("config.cc.mode", false);
+ vp.insert<target_triplet> ("config.cc.target", false);
// Compiler runtime and C standard library.
//
@@ -137,7 +137,7 @@ namespace build2
// Ability to disable using preprocessed output for compilation.
//
- vp.insert<bool> ("config.cc.reprocess", true);
+ vp.insert<bool> ("config.cc.reprocess");
vp.insert<bool> ("cc.reprocess");
// Register scope operation callback.
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index d6c337d..2b2604b 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -78,7 +78,7 @@ namespace build2
// Must be the same as in module's init().
//
- const variable& v (vp.insert<strings> ("config." + m, true));
+ const variable& v (vp.insert<strings> ("config." + m));
if (rs[v].defined ())
{
@@ -358,8 +358,11 @@ namespace build2
// @@ There are actually two cases to this issue:
//
// 1. The module is loaded in the outer project (e.g., tests inside a
- // project). It feels like this should be handled with project-
- // specific variable visibility.
+ // project). It feels like this should be handled with project
+ // variable visibility. And now it is with the project being the
+ // default. Note that this is the reason we don't need any of this
+ // for the project configuration: there the config.* variables are
+ // always set on the project root.
//
// 2. The module is loaded in the outer scope within the same
// project. We are currently thinking whether we should even
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx
index f15bfc5..75193bb 100644
--- a/libbuild2/config/init.cxx
+++ b/libbuild2/config/init.cxx
@@ -44,12 +44,12 @@ namespace build2
// reserved to not be valid module names (`build`). We also currently
// treat `import` as special.
//
+ auto& vp (rs.var_pool ());
+
// NOTE: all config.** variables are by default made (via a pattern) to
// be overridable with global visibility. So we must override this if a
// different semantics is required.
//
- auto& vp (rs.var_pool ());
-
const auto v_p (variable_visibility::project);
// While config.config.load (see below) could theoretically be specified
@@ -166,6 +166,8 @@ namespace build2
auto& vp (rs.var_pool ());
+ // Note: config.* is pattern-typed to global visibility.
+ //
const auto v_p (variable_visibility::project);
auto& c_l (vp.insert<paths> ("config.config.load", true /* ovr */));
diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx
index 724a16e..3838451 100644
--- a/libbuild2/context.cxx
+++ b/libbuild2/context.cxx
@@ -124,45 +124,50 @@ namespace build2
// may reference these things.
//
scope& gs (global_scope.rw ());
+ {
+ const auto v_g (variable_visibility::global);
- gs.assign<dir_path> ("build.work") = work;
- gs.assign<dir_path> ("build.home") = home;
+ // Any variable assigned on the global scope should natually have the
+ // global visibility.
+ //
+ auto set = [&gs, &vp] (const char* var, auto val)
+ {
+ using T = decltype (val);
+ value& v (gs.assign (vp.insert<T> (var, variable_visibility::global)));
+ v = move (val);
+ };
- // Build system driver process path.
- //
- gs.assign<process_path> ("build.path") =
- process_path (nullptr, // Will be filled by value assignment.
- path (argv0.recall_string ()),
- path (argv0.effect));
+ set ("build.work", work);
+ set ("build.home", home);
- // Build system import path for modules. We only set it for the
- // development build.
- //
- var_import_build2 = &vp.insert<abs_dir_path> ("import.build2");
+ // Build system driver process path.
+ //
+ set ("build.path",
+ process_path (nullptr, // Will be filled by value assignment.
+ path (argv0.recall_string ()),
+ path (argv0.effect)));
- if (!build_installed)
- {
+ // Build system import path for modules. We only set it for the
+ // development build.
+ //
+ var_import_build2 = &vp.insert<abs_dir_path> ("import.build2", v_g);
+
+ if (!build_installed)
+ {
#ifdef BUILD2_IMPORT_PATH
- gs.assign (var_import_build2) = abs_dir_path (BUILD2_IMPORT_PATH);
+ gs.assign (var_import_build2) = abs_dir_path (BUILD2_IMPORT_PATH);
#endif
- }
+ }
- // Build system verbosity level.
- //
- gs.assign<uint64_t> ("build.verbosity") = verb;
+ // Build system verbosity level.
+ //
+ set ("build.verbosity", uint64_t (verb));
- // Build system version (similar to what we do in the version module
- // except here we don't include package epoch/revision).
- //
- {
+ // Build system version (similar to what we do in the version module
+ // except here we don't include package epoch/revision).
+ //
const standard_version& v (build_version);
- auto set = [&gs, &vp] (const char* var, auto val)
- {
- using T = decltype (val);
- gs.assign (vp.insert<T> (var)) = move (val);
- };
-
// Note: here we assume epoch will always be 1 and therefore omit the
// project_ prefix in a few places.
//
@@ -201,16 +206,15 @@ namespace build2
// not re-package things during the queued-to-public transition.
//
set ("build.version.stage", LIBBUILD2_STAGE);
- }
- // Enter the host information. Rather than jumping through hoops like
- // config.guess, for now we are just going to use the compiler target we
- // were built with. While it is not as precise (for example, a binary
- // built for i686 might be running on x86_64), it is good enough of an
- // approximation/fallback since most of the time we are interested in just
- // the target class (e.g., linux, windows, macos).
- //
- {
+ // Enter the host information. Rather than jumping through hoops like
+ // config.guess, for now we are just going to use the compiler target we
+ // were built with. While it is not as precise (for example, a binary
+ // built for i686 might be running on x86_64), it is good enough of an
+ // approximation/fallback since most of the time we are interested in
+ // just the target class (e.g., linux, windows, macos).
+ //
+
// Did the user ask us to use config.guess?
//
string orig (config_guess
@@ -231,19 +235,22 @@ namespace build2
// Also enter as build.host.{cpu,vendor,system,version,class} for
// convenience of access.
//
- gs.assign<string> ("build.host.cpu") = t.cpu;
- gs.assign<string> ("build.host.vendor") = t.vendor;
- gs.assign<string> ("build.host.system") = t.system;
- gs.assign<string> ("build.host.version") = t.version;
- gs.assign<string> ("build.host.class") = t.class_;
+ set ("build.host.cpu", t.cpu);
+ set ("build.host.vendor", t.vendor);
+ set ("build.host.system", t.system);
+ set ("build.host.version", t.version);
+ set ("build.host.class", t.class_);
- gs.assign<target_triplet> ("build.host") = move (t);
+ set ("build.host", move (t));
}
catch (const invalid_argument& e)
{
fail << "unable to parse build host '" << orig << "': " << e <<
info << "consider using the --config-guess option";
}
+
+ var_build_meta_operation =
+ &vp.insert<string> ("build.meta_operation", v_g);
}
// Register builtin target types.
@@ -271,6 +278,39 @@ namespace build2
}
}
+ // Enter builtin variable patterns.
+ //
+ // Note that we must do this prior to entering overrides below.
+ //
+ {
+ const auto v_g (variable_visibility::global);
+ const auto v_p (variable_visibility::project);
+
+ // All config.** variables are overridable with global visibility.
+ //
+ // For the config.**.configured semantics, see config::unconfigured().
+ //
+ // Note that some config.config.* variables have project visibility thus
+ // the match argument is false.
+ //
+ vp.insert_pattern ("config.**", nullopt, true, v_g, true, false);
+ vp.insert_pattern<bool> ("config.**.configured", false, v_p);
+
+ // file.cxx:import() (note: order is important; see insert_pattern()).
+ //
+ vp.insert_pattern<abs_dir_path> ("config.import.*", true, v_g, true);
+ vp.insert_pattern<path> ("config.import.**", true, v_g, true);
+
+ // module.cxx:boot/init_module().
+ //
+ // Note that we also have the config.<module>.configured variable (see
+ // above).
+ //
+ vp.insert_pattern<bool> ("**.booted", false /* overridable */, v_p);
+ vp.insert_pattern<bool> ("**.loaded", false, v_p);
+ vp.insert_pattern<bool> ("**.configured", false, v_p);
+ }
+
// Parse and enter the command line variables. We do it before entering
// any other variables so that all the variables that are overriden are
// marked as such first. Then, as we enter variables, we can verify that
@@ -400,14 +440,18 @@ namespace build2
if (c == '!' && dir)
fail << "scope-qualified global override of variable " << n;
- variable& var (const_cast<variable&> (
- vp.insert (n, true /* overridable */)));
+ // Pre-enter the main variable. Note that we rely on all the overridable
+ // variables with global visibility to be known (either entered or
+ // handled via a pettern) at this stage.
+ //
+ variable& var (
+ const_cast<variable&> (vp.insert (n, true /* overridable */)));
const variable* o;
{
variable_visibility v (c == '/' ? variable_visibility::scope :
c == '%' ? variable_visibility::project :
- variable_visibility::normal);
+ variable_visibility::global);
const char* k (tt == token_type::assign ? "__override" :
tt == token_type::append ? "__suffix" : "__prefix");
@@ -474,52 +518,28 @@ namespace build2
data_->global_var_overrides.push_back (s);
}
- // Enter builtin variables and patterns.
+ // Enter builtin variables.
//
- const auto v_g (variable_visibility::normal); // Global.
- const auto v_p (variable_visibility::project);
const auto v_t (variable_visibility::target);
const auto v_q (variable_visibility::prereq);
- // All config.** variables are by default overridable with global
- // visibility.
- //
- // For the config.**.configured semantics, see config::unconfigured().
- //
- vp.insert_pattern ("config.**", nullopt, true, v_g, true, false);
- vp.insert_pattern<bool> ("config.**.configured", false, v_p);
-
- // file.cxx:import() (note that order is important; see insert_pattern()).
- //
- vp.insert_pattern<abs_dir_path> ("config.import.*", true, v_g, true);
- vp.insert_pattern<path> ("config.import.**", true, v_g, true);
-
- // module.cxx:boot/init_module().
- //
- // Note that we also have the config.<module>.configured variable (see
- // above).
- //
- vp.insert_pattern<bool> ("**.booted", false /* overridable */, v_p);
- vp.insert_pattern<bool> ("**.loaded", false, v_p);
- vp.insert_pattern<bool> ("**.configured", false, v_p);
-
var_src_root = &vp.insert<dir_path> ("src_root");
var_out_root = &vp.insert<dir_path> ("out_root");
var_src_base = &vp.insert<dir_path> ("src_base");
var_out_base = &vp.insert<dir_path> ("out_base");
- var_forwarded = &vp.insert<bool> ("forwarded", v_p);
+ var_forwarded = &vp.insert<bool> ("forwarded");
// Note that subprojects is not typed since the value requires
// pre-processing (see file.cxx).
//
- var_project = &vp.insert<project_name> ("project", v_p);
- var_amalgamation = &vp.insert<dir_path> ("amalgamation", v_p);
- var_subprojects = &vp.insert ("subprojects", v_p);
- var_version = &vp.insert<string> ("version", v_p);
+ var_project = &vp.insert<project_name> ("project");
+ var_amalgamation = &vp.insert<dir_path> ("amalgamation");
+ var_subprojects = &vp.insert ("subprojects");
+ var_version = &vp.insert<string> ("version");
- var_project_url = &vp.insert<string> ("project.url", v_p);
- var_project_summary = &vp.insert<string> ("project.summary", v_p);
+ var_project_url = &vp.insert<string> ("project.url");
+ var_project_summary = &vp.insert<string> ("project.summary");
var_import_target = &vp.insert<name> ("import.target");
@@ -533,8 +553,6 @@ namespace build2
gs.target_vars[exe::static_type]["*"].assign (var_backlink) = "true";
gs.target_vars[doc::static_type]["*"].assign (var_backlink) = "true";
- var_build_meta_operation = &vp.insert<string> ("build.meta_operation");
-
// Register builtin rules.
//
{
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 4c4f6ad..1d8421c 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -91,13 +91,13 @@ namespace build2
// Feature flags.
//
- auto enter = [&rs] (const char* v) -> const variable&
- {
- return rs.var_pool ().insert<bool> (v, variable_visibility::project);
- };
+ auto& vp (rs.var_pool ());
- //bool concepts (false); auto& v_c (enter ("cxx.features.concepts"));
- bool modules (false); auto& v_m (enter ("cxx.features.modules"));
+ //bool concepts (false);
+ //auto& v_c (vp.insert<bool> ("cxx.features.concepts"));
+
+ bool modules (false);
+ auto& v_m (vp.insert<bool> ("cxx.features.modules"));
// NOTE: see also module sidebuild subproject if changing anything about
// modules here.
@@ -403,20 +403,18 @@ namespace build2
hinters,
- // Note: some overridable, some not.
- //
// NOTE: remember to update documentation if changing anything here.
//
- vp.insert<strings> ("config.cxx", true),
- vp.insert<string> ("config.cxx.id", true),
- vp.insert<string> ("config.cxx.version", true),
- vp.insert<string> ("config.cxx.target", true),
- vp.insert<string> ("config.cxx.std", true),
- vp.insert<strings> ("config.cxx.poptions", true),
- vp.insert<strings> ("config.cxx.coptions", true),
- vp.insert<strings> ("config.cxx.loptions", true),
- vp.insert<strings> ("config.cxx.aoptions", true),
- vp.insert<strings> ("config.cxx.libs", true),
+ vp.insert<strings> ("config.cxx"),
+ vp.insert<string> ("config.cxx.id"),
+ vp.insert<string> ("config.cxx.version"),
+ vp.insert<string> ("config.cxx.target"),
+ vp.insert<string> ("config.cxx.std"),
+ vp.insert<strings> ("config.cxx.poptions"),
+ vp.insert<strings> ("config.cxx.coptions"),
+ vp.insert<strings> ("config.cxx.loptions"),
+ vp.insert<strings> ("config.cxx.aoptions"),
+ vp.insert<strings> ("config.cxx.libs"),
// List of translatable headers. Inclusions of such headers are
// translated to the corresponding header unit imports.
@@ -427,14 +425,14 @@ namespace build2
// opposed to -I) header search paths. Note also that all entries must
// be specified before loading the cxx module.
//
- &vp.insert<strings> ("config.cxx.translatable_headers", true),
+ &vp.insert<strings> ("config.cxx.translatable_headers"),
vp.insert<process_path> ("cxx.path"),
vp.insert<strings> ("cxx.mode"),
vp.insert<dir_paths> ("cxx.sys_lib_dirs"),
vp.insert<dir_paths> ("cxx.sys_inc_dirs"),
- vp.insert<string> ("cxx.std", variable_visibility::project),
+ vp.insert<string> ("cxx.std"),
vp.insert<strings> ("cxx.poptions"),
vp.insert<strings> ("cxx.coptions"),
@@ -602,8 +600,7 @@ namespace build2
bool symexport (false);
if (modules)
{
- auto& var (vp.insert<bool> ("cxx.features.symexport",
- variable_visibility::project));
+ auto& var (vp.insert<bool> ("cxx.features.symexport"));
symexport = cast_false<bool> (rs[var]);
cm.x_symexport = &var;
}
diff --git a/libbuild2/dist/init.cxx b/libbuild2/dist/init.cxx
index 8eaafa2..a95f768 100644
--- a/libbuild2/dist/init.cxx
+++ b/libbuild2/dist/init.cxx
@@ -38,8 +38,6 @@ namespace build2
//
auto& vp (rs.var_pool ());
- // Note: some overridable, some not.
- //
// config.dist.archives is a list of archive extensions (e.g., zip,
// tar.gz) that can be optionally prefixed with a directory. If it is
// relative, then it is prefixed with config.dist.root. Otherwise, the
@@ -51,15 +49,15 @@ namespace build2
// absent, then the checksum file is written into the same directory as
// the corresponding archive.
//
- vp.insert<abs_dir_path> ("config.dist.root", true);
- vp.insert<paths> ("config.dist.archives", true);
- vp.insert<paths> ("config.dist.checksums", true);
- vp.insert<path> ("config.dist.cmd", true);
+ vp.insert<abs_dir_path> ("config.dist.root");
+ vp.insert<paths> ("config.dist.archives");
+ vp.insert<paths> ("config.dist.checksums");
+ vp.insert<path> ("config.dist.cmd");
// Allow distribution of uncommitted projects. This is enforced by the
// version module.
//
- vp.insert<bool> ("config.dist.uncommitted", true);
+ vp.insert<bool> ("config.dist.uncommitted");
vp.insert<dir_path> ("dist.root");
vp.insert<process_path> ("dist.cmd");
@@ -71,8 +69,7 @@ namespace build2
// Project's package name.
//
- auto& v_d_p (
- vp.insert<string> ("dist.package", variable_visibility::project));
+ auto& v_d_p (vp.insert<string> ("dist.package"));
// Create the module.
//
diff --git a/libbuild2/functions-builtin.cxx b/libbuild2/functions-builtin.cxx
index 4e28741..afafe66 100644
--- a/libbuild2/functions-builtin.cxx
+++ b/libbuild2/functions-builtin.cxx
@@ -27,7 +27,7 @@ namespace build2
return (*s)[convert<string> (move (name))].defined ();
};
- // Return variable visibility if it exists and NULL otherwise.
+ // Return variable visibility if it has been entered and NULL otherwise.
//
f["visibility"] = [](const scope* s, names name)
{
diff --git a/libbuild2/install/init.cxx b/libbuild2/install/init.cxx
index 06e5d3a..d0fb4bc 100644
--- a/libbuild2/install/init.cxx
+++ b/libbuild2/install/init.cxx
@@ -52,8 +52,6 @@ namespace build2
if (spec)
{
- // Note: overridable.
- //
vn = "config.install";
if (!global)
{
@@ -61,7 +59,7 @@ namespace build2
vn += name;
}
vn += var;
- const variable& vr (rs.var_pool ().insert<CT> (move (vn), true));
+ const variable& vr (rs.var_pool ().insert<CT> (move (vn)));
using config::lookup_config;
@@ -75,8 +73,6 @@ namespace build2
if (global)
return;
- // Note: not overridable.
- //
vn = "install.";
vn += name;
vn += var;
@@ -196,18 +192,16 @@ namespace build2
// Note that the set_dir() calls below enter some more.
//
{
- // Note: not overridable.
- //
// The install variable is a path, not dir_path, since it can be used
// to both specify the target directory (to install with the same file
// name) or target file (to install with a different name). And the
// way we distinguish between the two is via the presence/absence of
// the trailing directory separator.
//
- vp.insert<path> ("install", variable_visibility::target);
- vp.insert<bool> ("for_install", variable_visibility::prereq);
- vp.insert<string> ("install.mode", variable_visibility::project);
- vp.insert<bool> ("install.subdirs", variable_visibility::project);
+ vp.insert<path> ("install", variable_visibility::target);
+ vp.insert<bool> ("for_install", variable_visibility::prereq);
+ vp.insert<string> ("install.mode");
+ vp.insert<bool> ("install.subdirs");
}
// Register our rules.
@@ -278,7 +272,7 @@ namespace build2
//
{
auto& var (vp.insert<dir_path> ( "install.chroot"));
- auto& cvar (vp.insert<abs_dir_path> ("config.install.chroot", true));
+ auto& cvar (vp.insert<abs_dir_path> ("config.install.chroot"));
value& v (rs.assign (var));
diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx
index 777f177..28d2468 100644
--- a/libbuild2/module.cxx
+++ b/libbuild2/module.cxx
@@ -571,7 +571,7 @@ namespace build2
}
}
- // Note: pattern-typed in context ctor as project-visibility variables of
+ // Note: pattern-typed in context ctor as project visibility variables of
// type bool.
//
// We call the variable 'loaded' rather than 'inited' because it is
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index 68e7ed9..532b357 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -1823,7 +1823,7 @@ namespace build2
// Note that even though we are relying on the config.** variable
// pattern to set global visibility, let's make sure as a sanity check.
//
- if (var.visibility != variable_visibility::normal)
+ if (var.visibility != variable_visibility::global)
{
fail (t) << "configuration variable " << var << " has "
<< var.visibility << " visibility";
@@ -3224,7 +3224,8 @@ namespace build2
<< var.type->name << " to " << type->name;
}
- //@@ TODO: the same for vis and ovr.
+ //@@ TODO: the same checks for vis and ovr (when we have the corresponding
+ // attributes).
if (type || vis || ovr)
ctx.var_pool.update (const_cast<variable&> (var),
diff --git a/libbuild2/scope.cxx b/libbuild2/scope.cxx
index d18c4eb..842b839 100644
--- a/libbuild2/scope.cxx
+++ b/libbuild2/scope.cxx
@@ -164,7 +164,7 @@ namespace build2
case variable_visibility::project:
s = s->root () ? nullptr : s->parent_scope ();
break;
- case variable_visibility::normal:
+ case variable_visibility::global:
s = s->parent_scope ();
break;
case variable_visibility::prereq:
@@ -259,7 +259,7 @@ namespace build2
break;
}
- case variable_visibility::normal:
+ case variable_visibility::global:
break;
case variable_visibility::target:
case variable_visibility::prereq:
diff --git a/libbuild2/scope.hxx b/libbuild2/scope.hxx
index cb20f79..39be143 100644
--- a/libbuild2/scope.hxx
+++ b/libbuild2/scope.hxx
@@ -187,13 +187,15 @@ namespace build2
value&
assign (const variable* var) {return vars.assign (var);} // For cached.
+ // Assign an untyped non-overridable variable with project visibility.
+ //
value&
assign (string name)
{
return assign (var_pool ().insert (move (name)));
}
- // Assign a typed non-overridable variable with normal visibility.
+ // As above, but assign a typed variable.
//
template <typename T>
value&
@@ -210,6 +212,22 @@ namespace build2
return v.as<T> ();
}
+ template <typename T>
+ T&
+ assign (const variable& var, T&& val)
+ {
+ value& v (assign (var) = forward<T> (val));
+ return v.as<T> ();
+ }
+
+ template <typename T>
+ T&
+ assign (const variable* var, T&& val)
+ {
+ value& v (assign (var) = forward<T> (val));
+ return v.as<T> ();
+ }
+
// Return a value suitable for appending. If the variable does not
// exist in this scope's map, then outer scopes are searched for
// the same variable. If found then a new variable with the found
diff --git a/libbuild2/test/init.cxx b/libbuild2/test/init.cxx
index a21e8f2..16891c6 100644
--- a/libbuild2/test/init.cxx
+++ b/libbuild2/test/init.cxx
@@ -46,25 +46,23 @@ namespace build2
//
// Specified as <target>@<path-id> pairs with both sides being
// optional. The variable is untyped (we want a list of name-pairs),
- // overridable, and inheritable. The target is relative (in essence a
- // prerequisite) which is resolved from the (root) scope where the
- // config.test value is defined.
+ // overridable, and with global visibiility. The target is relative
+ // (in essence a prerequisite) which is resolved from the (root) scope
+ // where the config.test value is defined.
//
- vp.insert ("config.test", true),
+ vp.insert ("config.test"),
// Test working directory before/after cleanup (see Testscript spec
// for semantics).
//
- vp.insert<name_pair> ("config.test.output", true),
+ vp.insert<name_pair> ("config.test.output"),
// The test variable is a name which can be a path (with the
// true/false special values) or a target name.
//
- // Note: none are overridable.
- //
- vp.insert<name> ("test", variable_visibility::target),
- vp.insert<strings> ("test.options", variable_visibility::project),
- vp.insert<strings> ("test.arguments", variable_visibility::project),
+ vp.insert<name> ("test", variable_visibility::target),
+ vp.insert<strings> ("test.options"),
+ vp.insert<strings> ("test.arguments"),
// Prerequisite-specific.
//
@@ -93,7 +91,7 @@ namespace build2
// Test target platform.
//
- vp.insert<target_triplet> ("test.target", variable_visibility::project)
+ vp.insert<target_triplet> ("test.target")
};
// This one is used by other modules/rules.
@@ -102,8 +100,8 @@ namespace build2
// These are only used in testscript.
//
- vp.insert<strings> ("test.redirects", variable_visibility::project);
- vp.insert<strings> ("test.cleanups", variable_visibility::project);
+ vp.insert<strings> ("test.redirects");
+ vp.insert<strings> ("test.cleanups");
// Unless already set, default test.target to build.host. Note that it
// can still be overriden by the user, e.g., in root.build.
diff --git a/libbuild2/test/script/parser.test.cxx b/libbuild2/test/script/parser.test.cxx
index 44be998..a12fda4 100644
--- a/libbuild2/test/script/parser.test.cxx
+++ b/libbuild2/test/script/parser.test.cxx
@@ -206,8 +206,7 @@ namespace build2
value& v (
tt.assign (
- ctx.var_pool.rw ().insert<target_triplet> (
- "test.target", variable_visibility::project)));
+ ctx.var_pool.rw ().insert<target_triplet> ("test.target")));
v = cast<target_triplet> (ctx.global_scope["build.host"]);
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index 48fcf40..d16fcb4 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -22,7 +22,7 @@ namespace build2
switch (v)
{
- case variable_visibility::normal: r = "normal"; break;
+ case variable_visibility::global: r = "global"; break;
case variable_visibility::project: r = "project"; break;
case variable_visibility::scope: r = "scope"; break;
case variable_visibility::target: r = "target"; break;
@@ -1161,14 +1161,34 @@ namespace build2
var.type = t;
}
- // Change visibility? While this might at first seem like a bad idea,
- // it can happen that the variable lookup happens before any values
- // were set, in which case the variable will be entered with the
- // default visibility.
+ // Change visibility? While this might at first seem like a bad idea, it
+ // can happen that the variable lookup happens before any values were set
+ // in which case the variable will be entered with the default (project)
+ // visibility.
+ //
+ // For example, a buildfile, for some reason, could reference a target-
+ // specific variable (say, test) before loading a module (say, test) that
+ // sets this visibility. While strictly speaking we could have potentially
+ // already made a lookup using the wrong visibility, presumably this
+ // should be harmless.
+ //
+ // @@ But consider a situation where this test is set on scope prior to
+ // loading the module: now this value will effectively be unreachable
+ // without any diagnostics. So maybe we should try to clean this up.
+ // But we will need proper diagnostics instead of assert (which means
+ // we would probably need to track the location where the variable
+ // was first entered).
+ //
+ // Note also that this won't work well for global visibility since we only
+ // allow restrictions. The thinking is that global visibility is special
+ // and requiring special arrangements (like variable patterns, similar to
+ // how we've done it for config.*) is reasonable. In fact, it feels like
+ // only the build system core should be allowed to use global visibility
+ // (see the context ctor for details).
//
if (uv)
{
- assert (var.visibility == variable_visibility::normal); // Default.
+ assert (*v > var.visibility);
var.visibility = *v;
}
}
@@ -1219,7 +1239,14 @@ namespace build2
if (v == nullptr)
v = &*p.visibility;
else if (p.match)
- assert (*v == *p.visibility);
+ {
+ // Allow the pattern to restrict but not relax.
+ //
+ if (*p.visibility > *v)
+ v = &*p.visibility;
+ else
+ assert (*v == *p.visibility);
+ }
}
if (p.overridable)
@@ -1277,7 +1304,7 @@ namespace build2
nullptr,
pt,
nullptr,
- pv != nullptr ? *pv : variable_visibility::normal}));
+ pv != nullptr ? *pv : variable_visibility::project}));
variable& var (r.first->second);
diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx
index bf0aa00..0eaf170 100644
--- a/libbuild2/variable.hxx
+++ b/libbuild2/variable.hxx
@@ -98,10 +98,10 @@ namespace build2
//
enum class variable_visibility: uint8_t
{
- // Note that the search for target type/pattern-specific terminates at
- // the project boundary.
+ // Note that the search for target type/pattern-specific variables always
+ // terminates at the project boundary but includes the global scope.
//
- normal, // All outer scopes.
+ global, // All outer scopes.
project, // This project (no outer projects).
scope, // This scope (no outer scopes).
target, // Target and target type/pattern-specific.
@@ -192,8 +192,8 @@ namespace build2
// context ctor before any other variables. Project wide overrides are
// entered in main(). Overriding happens in scope::find_override().
//
- // NULL type and normal visibility are the defaults and can be overridden by
- // "tighter" values.
+ // Untyped (NULL type) and project visibility are the defaults but can be
+ // overridden by "tighter" values.
//
struct variable
{
@@ -1068,8 +1068,10 @@ namespace build2
// Find existing or insert new variable.
//
// Unless specified explicitly, the variable is untyped, non-overridable,
- // and with normal visibility but these may be overridden by a pattern.
- // Note also that a pattern may restrict (but not relax) overridability.
+ // and with project visibility but these may be overridden by a pattern.
+ //
+ // Note also that a pattern and later insertions may restrict (but not
+ // relax) visibility and overridability.
const variable&
insert (string name)
@@ -1077,18 +1079,12 @@ namespace build2
return insert (move (name), nullptr, nullptr, nullptr);
}
- // Insert or override (type/visibility). Note that by default the
- // variable is not overridable.
- //
const variable&
insert (string name, variable_visibility v)
{
return insert (move (name), nullptr, &v, nullptr);
}
- // Note that overridability can still be restricted (but not relaxed) by
- // another call to insert or via patterns (see below).
- //
const variable&
insert (string name, bool overridable)
{
@@ -1149,19 +1145,19 @@ namespace build2
LIBBUILD2_SYMEXPORT const variable&
insert_alias (const variable& var, string name);
- // Insert a variable pattern. Any variable that matches this pattern
- // will have the specified type, visibility, and overridability. If
- // match is true, then individual insertions of the matching variable
- // must match the specified type/visibility/overridability. Otherwise,
- // individual insertions can provide alternative values and the pattern
- // values are a fallback (if you specify false you better be very clear
- // about what you are trying to achieve).
- //
- // The pattern must be in the form [<prefix>.](*|**)[.<suffix>] where
- // '*' matches single component stems (i.e., 'foo' but not 'foo.bar')
- // and '**' matches single and multi-component stems. Note that only
- // multi-component variables are considered for pattern matching (so
- // just '*' won't match anything).
+ // Insert a variable pattern. Any variable that matches this pattern will
+ // have the specified type, visibility, and overridability. If match is
+ // true, then individual insertions of the matching variable must match
+ // the specified type/visibility/overridability. Otherwise, individual
+ // insertions can provide alternative values and the pattern values are a
+ // fallback (if you specify false you better be very clear about what you
+ // are trying to achieve).
+ //
+ // The pattern must be in the form [<prefix>.](*|**)[.<suffix>] where '*'
+ // matches single component stems (i.e., 'foo' but not 'foo.bar') and '**'
+ // matches single and multi-component stems. Note that only multi-
+ // component variables are considered for pattern matching (so just '*'
+ // won't match anything).
//
// The patterns are matched in the more-specific-first order where the
// pattern is considered more specific if it has a greater sum of its
diff --git a/libbuild2/version/init.cxx b/libbuild2/version/init.cxx
index 135f2db..d30dc24 100644
--- a/libbuild2/version/init.cxx
+++ b/libbuild2/version/init.cxx
@@ -226,17 +226,13 @@ namespace build2
// Note also that we have "gifted" the config.version variable name to
// the config module.
//
- auto& vp (rs.var_pool ());
-
- auto set = [&vp, &rs] (const char* var, auto val)
+ auto set = [&rs] (auto var, auto val)
{
- using T = decltype (val);
- auto& v (vp.insert<T> (var, variable_visibility::project));
- rs.assign (v) = move (val);
+ rs.assign (var, move (val));
};
- if (!sum.empty ()) rs.assign (ctx.var_project_summary) = move (sum);
- if (!url.empty ()) rs.assign (ctx.var_project_url) = move (url);
+ if (!sum.empty ()) set (ctx.var_project_summary, move (sum));
+ if (!url.empty ()) set (ctx.var_project_url, move (url));
set ("version", v.string ()); // Project version (var_version).