aboutsummaryrefslogtreecommitdiff
path: root/build2/algorithm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build2/algorithm.cxx')
-rw-r--r--build2/algorithm.cxx89
1 files changed, 55 insertions, 34 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index a22837f..17768e3 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -478,60 +478,81 @@ namespace build2
}
target_state
- perform_clean (action a, target& t)
+ clean_extra (action a, file& ft, initializer_list<const char*> es)
{
- // The reverse order of update: first remove the file, then clean
- // prerequisites.
+ // Clean the extras first and don't print the commands at verbosity level
+ // below 3.
//
- file& ft (dynamic_cast<file&> (t));
+ target_state er (target_state::unchanged);
+ path ef; // First extra file that actually got removed (see below).
- target_state r (rmfile (ft.path (), ft)
- ? target_state::changed
- : target_state::unchanged);
+ for (const char* e: es)
+ {
+ if (e == nullptr)
+ continue;
- // Update timestamp in case there are operations after us that
- // could use the information.
- //
- ft.mtime (timestamp_nonexistent);
+ path f;
+ if (*e == '+')
+ f = ft.path () + ++e;
+ else
+ f = ft.path ().base () + e;
- // Clean prerequisites.
- //
- r |= reverse_execute_prerequisites (a, t);
+ target_state r (rmfile (f, false)
+ ? target_state::changed
+ : target_state::unchanged);
- return r;
- }
+ if (r == target_state::changed && ef.empty ())
+ {
+ ef = move (f);
+ }
- target_state
- perform_clean_depdb (action a, target& t)
- {
- // Normally the .d file is created/updated before the target so remove it
- // first. Also, don't print the command at verbosity level below 3.
- //
- file& ft (dynamic_cast<file&> (t));
+ er |= r;
+ }
- path df (ft.path () + ".d");
- target_state dr (rmfile (df, false)
+ // Now clean the primary target and its prerequisited in the reverse order
+ // of update: first remove the file, then clean the prerequisites.
+ //
+ target_state tr (rmfile (ft.path (), ft)
? target_state::changed
: target_state::unchanged);
- // Factor the result of removing the .d file into the target state. While
- // strictly speaking removing it doesn't change the target state, if we
- // don't do this, then we may end up removing the file but still saying
- // that everything is clean (e.g., if someone removes the target file but
- // leaves .d laying around). That would be confusing.
+ // Update timestamp in case there are operations after us that could use
+ // the information.
+ //
+ ft.mtime (timestamp_nonexistent);
+
+ // Clean prerequisites.
//
- target_state tr (perform_clean (a, t));
+ tr |= reverse_execute_prerequisites (a, ft);
+ // Factor the result of removing the extra files into the target state.
+ // While strictly speaking removing them doesn't change the target state,
+ // if we don't do this, then we may end up removing the file but still
+ // saying that everything is clean (e.g., if someone removes the target
+ // file but leaves the extra laying around). That would be confusing.
+ //
// What would also be confusing is if we didn't print any commands in
// this case.
//
- if (tr == target_state::unchanged && dr == target_state::changed)
+ if (tr != target_state::changed && er == target_state::changed)
{
if (verb > 0 && verb < 3)
- text << "rm " << df;
+ text << "rm " << ef;
}
- tr |= dr;
+ tr |= er;
return tr;
}
+
+ target_state
+ perform_clean (action a, target& t)
+ {
+ return clean_extra (a, dynamic_cast<file&> (t), {});
+ }
+
+ target_state
+ perform_clean_depdb (action a, target& t)
+ {
+ return clean_extra (a, dynamic_cast<file&> (t), {"+.d"});
+ }
}