aboutsummaryrefslogtreecommitdiff
path: root/build2/algorithm.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-01-18 13:50:58 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-01-18 13:50:58 +0200
commitd402bc96297c6ed3dd6ee883dcff8cc39bd01030 (patch)
tree634d397f48022935926e26123c13ab8adad6796e /build2/algorithm.cxx
parent34be21a72a396240642acf3050eead875d3ed4b4 (diff)
Ignore prerequisite mtimes that are not linker inputs
This makes sure, for example, that we don't unnecessarily re-link an executable when its testscript prerequisite is changes.
Diffstat (limited to 'build2/algorithm.cxx')
-rw-r--r--build2/algorithm.cxx71
1 files changed, 16 insertions, 55 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 638afd0..8874e96 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -413,54 +413,15 @@ namespace build2
return r;
}
- bool
- execute_prerequisites (action a, target& t, const timestamp& mt)
+ pair<target*, target_state>
+ execute_prerequisites (const target_type* tt,
+ action a, target& t,
+ const timestamp& mt, const prerequisite_filter& pf)
{
bool e (mt == timestamp_nonexistent);
- for (target* pt: t.prerequisite_targets)
- {
- if (pt == nullptr) // Skipped.
- continue;
-
- target_state ts (execute (a, *pt));
-
- if (!e)
- {
- // If this is an mtime-based target, then compare timestamps.
- //
- if (auto mpt = dynamic_cast<const mtime_target*> (pt))
- {
- timestamp mp (mpt->mtime ());
-
- // What do we do if timestamps are equal? This can happen, for
- // example, on filesystems that don't have subsecond resolution.
- // There is not much we can do here except detect the case where
- // the prerequisite was changed in this run which means the
- // action must be executed on the target as well.
- //
- if (mt < mp || (mt == mp && ts == target_state::changed))
- e = true;
- }
- else
- {
- // Otherwise we assume the prerequisite is newer if it was changed.
- //
- if (ts == target_state::changed)
- e = true;
- }
- }
- }
-
- return e;
- }
-
- target*
- execute_prerequisites (const target_type& tt,
- action a, target& t, const timestamp& mt)
- {
- bool e (mt == timestamp_nonexistent);
- target* r (nullptr);
+ target* rt (tt != nullptr ? nullptr : &t);
+ target_state rs (target_state::unchanged);
for (target* pt: t.prerequisite_targets)
{
@@ -468,8 +429,11 @@ namespace build2
continue;
target_state ts (execute (a, *pt));
+ rs |= ts;
- if (!e)
+ // Should we compare the timestamp to this target's?
+ //
+ if (!e && (!pf || pf (*pt)))
{
// If this is an mtime-based target, then compare timestamps.
//
@@ -477,11 +441,8 @@ namespace build2
{
timestamp mp (mpt->mtime ());
- // What do we do if timestamps are equal? This can happen, for
- // example, on filesystems that don't have subsecond resolution.
- // There is not much we can do here except detect the case where
- // the prerequisite was changed in this run which means the
- // action must be executed on the target as well.
+ // The same logic as in mtime_target::newer() (but avoids a call to
+ // state()).
//
if (mt < mp || (mt == mp && ts == target_state::changed))
e = true;
@@ -495,12 +456,12 @@ namespace build2
}
}
- if (r == nullptr && pt->is_a (tt))
- r = pt;
+ if (rt == nullptr && pt->is_a (*tt))
+ rt = pt;
}
- assert (r != nullptr);
- return e ? r : nullptr;
+ assert (rt != nullptr);
+ return make_pair (e ? rt : nullptr, rs);
}
target_state