aboutsummaryrefslogtreecommitdiff
path: root/build/algorithm.ixx
diff options
context:
space:
mode:
Diffstat (limited to 'build/algorithm.ixx')
-rw-r--r--build/algorithm.ixx33
1 files changed, 28 insertions, 5 deletions
diff --git a/build/algorithm.ixx b/build/algorithm.ixx
index ddd63f6..d4d0ec8 100644
--- a/build/algorithm.ixx
+++ b/build/algorithm.ixx
@@ -95,16 +95,39 @@ namespace build
{
t.dependents--;
- switch (t.state)
+ switch (target_state ts = t.state ())
{
case target_state::unchanged:
- case target_state::changed: return t.state;
+ case target_state::changed: return ts;
default:
{
// Handle the "last" execution mode.
//
+ // This gets interesting when we consider interaction with
+ // groups. It seem to make sense to treat group members as
+ // dependents of the group, so, for example, if we try to
+ // clean the group via three of its members, only the last
+ // attempt will actually execute the clean. This means that
+ // when we match a group member, inside we should also match
+ // the group in order to increment the dependents count.
+ // Though this seems to be a natural requirement (if we
+ // are delegating to the group, we need to find a recipe
+ // for it, just like we would for a prerequisite).
+ //
+ // Note that below we are going to change the group state
+ // to postponed. This is not a mistake: until we execute
+ // the recipe, we want to keep returning postponed. And
+ // once the recipe is executed, it will reset the state
+ // to group (see group_action()). To put it another way,
+ // the execution of this member is postponed, not of the
+ // group.
+ //
+ // One important invariant to keep in mind: the return
+ // value from execute() should always be the same as what
+ // would get returned by a subsequent call to state().
+ //
if (current_mode == execution_mode::last && t.dependents != 0)
- return (t.state = target_state::postponed);
+ return (t.raw_state = target_state::postponed);
return execute_impl (a, t);
}
@@ -114,10 +137,10 @@ namespace build
inline target_state
execute_direct (action a, target& t)
{
- switch (t.state)
+ switch (target_state ts = t.state ())
{
case target_state::unchanged:
- case target_state::changed: return t.state;
+ case target_state::changed: return ts;
default: return execute_impl (a, t);
}
}