diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-11-09 11:45:02 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-11-09 11:45:02 +0200 |
commit | accbdae9b6e985d663d8af57375c7861ecd755a1 (patch) | |
tree | 6e6016a1a6ebdaccf2ef67b29c4236aa23914573 /build2/context.cxx | |
parent | 6158e136e105aae2f032a159ce807db68abee281 (diff) |
Add support for relative to base scope command line variable overrides
Currently, if we say:
$ b dir/ ./foo=bar
The scope the foo=bar is set on is relative to CWD, not dir/. While this
may seem wrong at first, this is the least surprising behavior when we
take into account that there can be multiple dir/'s.
Sometimes, however, we do want the override directory to be treated relative
to (every) target's base scope that we are building. To support this we are
extending the '.' and '..' special directory names (which are still resolved
relative to CWD) with '...', which means "relative to the base scope of every
target in the buildspec". For example:
$ b dir/ .../foo=bar
Is equivalent to:
$ b dir/ dir/foo=bar
And:
$ b liba/ libb/ .../tests/foo=bar
Is equivalent to:
$ b liba/ libb/ liba/tests/foo=bar libb/tests/foo=bar
Diffstat (limited to 'build2/context.cxx')
-rw-r--r-- | build2/context.cxx | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/build2/context.cxx b/build2/context.cxx index 5741489..10995e6 100644 --- a/build2/context.cxx +++ b/build2/context.cxx @@ -412,7 +412,7 @@ namespace build2 // auto make_global_scope = [] () -> scope& { - auto i (scope_map::instance.insert (dir_path (), false)); + auto i (scope_map::instance.insert (dir_path ())); scope& r (i->second); r.out_path_ = &i->first; global_scope = scope::global_ = &r; @@ -602,7 +602,7 @@ namespace build2 // token t (l.next ()); - dir_path dir; + optional<dir_path> dir; if (t.type == token_type::word) { string& v (t.value); @@ -638,10 +638,20 @@ namespace build2 t.value.erase (0, p + 1); // Erase the separator. } - if (dir.relative ()) - dir.complete (); + if (dir->relative ()) + { + // Handle the special relative to base scope case (.../). + // + auto i (dir->begin ()); + + if (*i == "...") + dir = dir_path (++i, dir->end ()); // Note: can become empty. + else + dir->complete (); // Relative to CWD. + } - dir.normalize (); + if (dir->absolute ()) + dir->normalize (); } } @@ -668,7 +678,7 @@ namespace build2 string n (t.value, c == '!' || c == '%' || c == '/' ? 1 : 0); - if (c == '!' && !dir.empty ()) + if (c == '!' && dir) fail << "scope-qualified global override of variable " << n; variable_visibility v (c == '/' ? variable_visibility::scope : @@ -713,12 +723,13 @@ namespace build2 if (r.first.type != nullptr) fail << "typed override of variable " << n; - // Global and scope overrides we can enter directly. Project ones will - // be entered by the caller for each amalgamation/project. + // Global and absolute scope overrides we can enter directly. Project + // and relative scope ones will be entered by the caller for each + // amalgamation/project. // - if (c == '!' || !dir.empty ()) + if (c == '!' || (dir && dir->absolute ())) { - scope& s (c == '!' ? gs : sm.insert (dir, false)->second); + scope& s (c == '!' ? gs : sm.insert (*dir)->second); auto p (s.vars.insert (*o)); if (!p.second) @@ -727,14 +738,15 @@ namespace build2 fail << "multiple global overrides of variable " << n; else fail << "multiple overrides of variable " << n - << " in scope " << dir; + << " in scope " << *dir; } value& v (p.first); v = move (r.first); } else - vos.emplace_back (variable_override {var, *o, move (r.first)}); + vos.push_back ( + variable_override {var, *o, move (dir), move (r.first)}); } // Enter builtin variables and patterns. |