diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-02-24 10:03:43 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-03-02 13:26:51 +0200 |
commit | 634048a861658af2bc5c37507bf96116cf1968aa (patch) | |
tree | d6122830ed2744d86e1ddb389f0e76131e54d6be /libbuild2/target.cxx | |
parent | be66fff5ff42eaab81d2a526d8b6296c28848775 (diff) |
Add update operation-specific variable with unmatch|match additional values
Note that the unmatch (match but do not update) and match (update during
match) values are only supported by certain rules (and potentially only for
certain prerequisite types).
Additionally:
- All operation-specific variables are now checked for false as an override
for the prerequisite-specific include value. In particular, this can now be
used to disable a prerequisite for update, for example:
./: exe{test}: update = false
- The cc::link_rule now supports the update=match value for headers and ad hoc
prerequisites. In particular, this can be used to make sure all the library
headers are updated before matching any of its (or dependent's) object
files.
Diffstat (limited to 'libbuild2/target.cxx')
-rw-r--r-- | libbuild2/target.cxx | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx index bc5dbba..f829cca 100644 --- a/libbuild2/target.cxx +++ b/libbuild2/target.cxx @@ -541,40 +541,87 @@ namespace build2 // include() // + // See var_include documentation for details on what's going on here. + // include_type include_impl (action a, const target& t, const prerequisite& p, - const target* m) + const target* m, + lookup* rl) { context& ctx (t.ctx); include_type r (include_type::normal); - // If var_clean is defined, then it takes precedence over include for - // the clean operation. - // - lookup l; - if (a.operation () == clean_id && (l = p.vars[ctx.var_clean])) - { - r = cast<bool> (l) ? include_type::normal : include_type::excluded; - } - else if (const string* v = cast_null<string> (p.vars[ctx.var_include])) + if (const string* v = cast_null<string> (p.vars[ctx.var_include])) { if (*v == "false") r = include_type::excluded; else if (*v == "adhoc") r = include_type::adhoc; else if (*v == "true") r = include_type::normal; else - fail << "invalid " << ctx.var_include->name << " variable value " + fail << "invalid " << *ctx.var_include << " variable value " << "'" << *v << "' specified for prerequisite " << p; } + // Handle operation-specific override. + // + lookup l; + optional<bool> r1; // Absent means something other than true|false. + + names storage; + names_view ns; + + if (r != include_type::excluded && ctx.current_ovar != nullptr) + { + if ((l = p.vars[*ctx.current_ovar])) + { + // Maybe we should optimize this for the common cases (bool, path, + // name)? But then again we don't expect many such overrides. Plus + // will complicate the diagnostics below. + // + ns = reverse (*l, storage); + + if (ns.size () == 1) + { + const name& n (ns[0]); + + if (n.simple ()) + { + const string& v (n.value); + + if (v == "false") + r1 = false; + else if (v == "true") + r1 = true; + } + } + + if (r1 && !*r1) + r = include_type::excluded; + } + } + // Call the meta-operation override, if any (currently used by dist). // - if (r != include_type::normal) + if (r != include_type::normal || l) { if (auto f = ctx.current_mif->include) - r = f (a, t, prerequisite_member {p, m}, r); + r = f (a, t, prerequisite_member {p, m}, r, l); + } + + if (l) + { + if (rl != nullptr) + *rl = l; + else if (!r1) + { + // Note: we have to delay this until the meta-operation callback above + // had a chance to override it. + // + fail << "unrecognized " << *ctx.current_ovar << " variable value " + << "'" << ns << "' specified for prerequisite " << p; + } } return r; |