aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc')
-rw-r--r--libbuild2/cc/common.cxx2
-rw-r--r--libbuild2/cc/link-rule.cxx104
-rw-r--r--libbuild2/cc/windows-rpath.cxx4
3 files changed, 97 insertions, 13 deletions
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<string> (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;