From 634048a861658af2bc5c37507bf96116cf1968aa Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 24 Feb 2022 10:03:43 +0200 Subject: 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. --- libbuild2/cc/common.cxx | 2 +- libbuild2/cc/link-rule.cxx | 104 +++++++++++++++++++++++++++++++++++++---- libbuild2/cc/windows-rpath.cxx | 4 +- 3 files changed, 97 insertions(+), 13 deletions(-) (limited to 'libbuild2/cc') diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx index ccb678c..97ac6b8 100644 --- a/libbuild2/cc/common.cxx +++ b/libbuild2/cc/common.cxx @@ -317,7 +317,7 @@ namespace build2 // Note: adhoc prerequisites are not part of the library metadata // protocol (and we should check for adhoc first to avoid races). // - if (pt.adhoc || pt == nullptr) + if (pt == nullptr || pt.adhoc ()) continue; if (marked (pt)) diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index 28bd54f..c993df6 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -282,7 +282,11 @@ namespace build2 { // If excluded or ad hoc, then don't factor it into our tests. // - if (include (a, t, p) != include_type::normal) + // Note that here we don't validate the update operation override + // value (since we may not match). Instead we do this in apply(). + // + lookup l; + if (include (a, t, p, &l) != include_type::normal) continue; if (p.is_a (x_src) || @@ -914,26 +918,68 @@ namespace build2 return a.operation () == clean_id && !pt.dir.sub (rs.out_path ()); }; + bool update_match (false); // Have update during match. + auto& pts (t.prerequisite_targets[a]); size_t start (pts.size ()); for (prerequisite_member p: group_prerequisite_members (a, t)) { - include_type pi (include (a, t, p)); + // Note that we have to recognize update=match for *(update), not just + // perform(update). But only actually update for perform(update). + // + lookup l; // The `update` variable value, if any. + include_type pi ( + include (a, t, p, a.operation () == update_id ? &l : nullptr)); // We pre-allocate a NULL slot for each (potential; see clean) // prerequisite target. // pts.push_back (prerequisite_target (nullptr, pi)); - const target*& pt (pts.back ()); + auto& pto (pts.back ()); + + // Use bit 2 of prerequisite_target::include to signal update during + // match. + // + // Not that for now we only allow updating during match ad hoc and + // mark 3 (headers, etc; see below) prerequisites. + // + bool um (false); + + if (l) + { + const string& v (cast (l)); + + if (v == "match") + { + if (a == perform_update_id) + { + pto.include |= 2; + update_match = um = true; + } + } + else if (v != "false" && v != "true") + { + fail << "unrecognized update variable value '" << v + << "' specified for prerequisite " << p.prerequisite; + } + } - // Skip excluded and ad hoc on this pass. + // Skip excluded and ad hoc (unless updated during match) on this + // pass. // if (pi != include_type::normal) + { + if (pi == include_type::adhoc && um) + pto.target = &p.search (t); // mark 0 + continue; + } + + const target*& pt (pto); - // Mark: - // 0 - lib + // Mark (2 bits): + // 0 - lib or update during match // 1 - src // 2 - mod // 3 - obj/bmi and also lib not to be cleaned (and other stuff) @@ -1121,13 +1167,45 @@ namespace build2 if (user_binless && !binless) fail << t << " cannot be binless due to " << p << " prerequisite"; + // Upgrade update during match prerequisites to mark 0 (see above for + // details). + // + if (um) + { + if (m != 3) + fail << "unable to update during match prerequisite " << p << + info << "updating this type of prerequisites during match is " + << "not supported by this rule"; + + m = 0; + } + mark (pt, m); } - // Match lib{} (the only unmarked) in parallel and wait for completion. + // Match lib{} and update during match (the only unmarked) in parallel + // and wait for completion. // match_members (a, t, pts, start); + // If we have any update during match prerequisites, now is the time to + // update them. Note that we have to do it before any further matches + // since they may rely on these prerequisites already being updated (for + // example, object file matches may need the headers to be already + // updated). + // + // Note also that we ignore the result and whether it renders us out of + // date, leaving it to the common execute logic in perform_update(). + // + if (update_match) + { + for (prerequisite_target& pto: pts) + { + if ((pto.include & 2) != 0) + update_during_match (trace, a, *pto.target); + } + } + // Check if we have any binful utility libraries. // if (binless) @@ -1432,6 +1510,7 @@ namespace build2 continue; // New mark: + // 0 - already matched // 1 - completion // 2 - verification // @@ -1619,7 +1698,7 @@ namespace build2 m = 2; // Needs verification. } } - else // lib*{} + else // lib*{} or update during match { // If this is a static library, see if we need to link it whole. // Note that we have to do it after match since we rely on the @@ -1669,7 +1748,7 @@ namespace build2 i = start; for (prerequisite_member p: group_prerequisite_members (a, t)) { - bool adhoc (pts[i].adhoc); + bool adhoc (pts[i].adhoc ()); const target*& pt (pts[i++]); uint8_t m; @@ -1684,8 +1763,13 @@ namespace build2 pt = &p.search (t); m = 1; // Mark for completion. } - else if ((m = unmark (pt)) != 0) + else { + m = unmark (pt); + + if (m == 0) + continue; // Already matched. + // If this is a library not to be cleaned, we can finally blank it // out. // diff --git a/libbuild2/cc/windows-rpath.cxx b/libbuild2/cc/windows-rpath.cxx index 2d90ace..e205924 100644 --- a/libbuild2/cc/windows-rpath.cxx +++ b/libbuild2/cc/windows-rpath.cxx @@ -128,7 +128,7 @@ namespace build2 library_cache lib_cache; for (const prerequisite_target& pt: t.prerequisite_targets[a]) { - if (pt.adhoc || pt == nullptr) + if (pt == nullptr || pt.adhoc ()) continue; bool la; @@ -253,7 +253,7 @@ namespace build2 library_cache lib_cache; for (const prerequisite_target& pt: t.prerequisite_targets[a]) { - if (pt.adhoc || pt == nullptr) + if (pt == nullptr || pt.adhoc ()) continue; bool la; -- cgit v1.1