aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-20 15:00:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:38:57 +0200
commite222cbabb84b5a6357242e47196f7e0eeb69a44f (patch)
treed1f11ce1c17055b3c66a2b0df3f8070c5845e253 /libbuild2/build
parent82ee575b32bc57598cec5eaaa3a170ac36de9af0 (diff)
Implement build script variable hashing
Diffstat (limited to 'libbuild2/build')
-rw-r--r--libbuild2/build/script/parser.cxx40
-rw-r--r--libbuild2/build/script/script.hxx14
2 files changed, 50 insertions, 4 deletions
diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx
index 6649777..86019ba 100644
--- a/libbuild2/build/script/parser.cxx
+++ b/libbuild2/build/script/parser.cxx
@@ -16,6 +16,12 @@ namespace build2
{
using type = token_type;
+ static inline bool
+ special_variable (const string& name)
+ {
+ return name == ">" || name == "<";
+ }
+
//
// Pre-parse.
//
@@ -96,9 +102,9 @@ namespace build2
case line_type::var:
{
// Check if we are trying to modify any of the special variables
- // ($>).
+ // ($>, $<).
//
- if (t.value == ">")
+ if (special_variable (t.value))
fail (t) << "attempt to set '" << t.value << "' variable";
// We don't pre-enter variables.
@@ -327,13 +333,41 @@ namespace build2
lookup parser::
lookup_variable (name&& qual, string&& name, const location& loc)
{
+ // In the pre-parse mode collect the referenced variable names for the
+ // script semantics change tracking.
+ //
if (pre_parse_)
+ {
+ // Add the variable name skipping special variables and suppressing
+ // duplicates.
+ //
+ if (!name.empty () && !special_variable (name))
+ {
+ auto& vars (script_->vars);
+
+ if (find (vars.begin (), vars.end (), name) == vars.end ())
+ vars.push_back (move (name));
+ }
+
return lookup ();
+ }
if (!qual.empty ())
fail (loc) << "qualified variable name";
- return environment_->lookup (name);
+ lookup r (environment_->lookup (name));
+
+ // Fail if non-script-local variable with an untracked name.
+ //
+ if (r.defined () && !r.belongs (*environment_))
+ {
+ const auto& vars (script_->vars);
+
+ if (find (vars.begin (), vars.end (), name) == vars.end ())
+ fail (loc) << "use of untracked variable '" << name << "'";
+ }
+
+ return r;
}
}
}
diff --git a/libbuild2/build/script/script.hxx b/libbuild2/build/script/script.hxx
index 1540ed8..29d62aa 100644
--- a/libbuild2/build/script/script.hxx
+++ b/libbuild2/build/script/script.hxx
@@ -40,7 +40,19 @@ namespace build2
// Note that the variables are not pre-entered into a pool during the
// parsing phase, so the line variable pointers are NULL.
//
- build2::script::lines lines;
+ build2::script::lines lines;
+
+ // Referenced ordinary (non-special) variables.
+ //
+ // Used for the script semantics change tracking. The variable list is
+ // filled during the pre-parsing phase and is checked against during
+ // the execution phase. If during execution some non-script-local
+ // variable is not found in the list (may happen for a computed name),
+ // then the execution fails since the script semantics may not be
+ // properly tracked (the variable value change will not trigger the
+ // target rebuild).
+ //
+ small_vector<string, 1> vars;
location start_loc;
location end_loc;