summaryrefslogtreecommitdiffstats
path: root/src/build.cc
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2017-05-19 00:34:51 (GMT)
committerColin Cross <ccross@android.com>2017-05-22 18:29:06 (GMT)
commit04d886b11041bb59d01df794cce7a1e8cad2250d (patch)
treee56630542064e75e205e85bd97dfd4f6fc693bcd /src/build.cc
parenta127dda3ee92916ef459b3da7aa9f2920ff1a5ab (diff)
downloadNinja-04d886b11041bb59d01df794cce7a1e8cad2250d.zip
Ninja-04d886b11041bb59d01df794cce7a1e8cad2250d.tar.gz
Ninja-04d886b11041bb59d01df794cce7a1e8cad2250d.tar.bz2
Always rebuild on errors
https://groups.google.com/forum/#!msg/ninja-build/YQuGNrECI-4/ti-lAs9SPv8J discusses a case where an rule updates its output file and then fails. The next run of ninja considers the ouptut file clean and doesn't rebuild it. Always stat output files after they are built, and write the mtime into .ninja_log. Consider output files dirty if the recorded mtime is older than the most recent input file.
Diffstat (limited to 'src/build.cc')
-rw-r--r--src/build.cc16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/build.cc b/src/build.cc
index 44d0663..1cce981 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -800,9 +800,10 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
return true;
}
- // Restat the edge outputs, if necessary.
- TimeStamp restat_mtime = 0;
- if (edge->GetBindingBool("restat") && !config_.dry_run) {
+ // Restat the edge outputs
+ TimeStamp output_mtime = 0;
+ bool restat = edge->GetBindingBool("restat");
+ if (!config_.dry_run) {
bool node_cleaned = false;
for (vector<Node*>::iterator o = edge->outputs_.begin();
@@ -810,7 +811,9 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
TimeStamp new_mtime = disk_interface_->Stat((*o)->path(), err);
if (new_mtime == -1)
return false;
- if ((*o)->mtime() == new_mtime) {
+ if (new_mtime > output_mtime)
+ output_mtime = new_mtime;
+ if ((*o)->mtime() == new_mtime && restat) {
// The rule command did not change the output. Propagate the clean
// state through the build graph.
// Note that this also applies to nonexistent outputs (mtime == 0).
@@ -821,6 +824,7 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
}
if (node_cleaned) {
+ TimeStamp restat_mtime = 0;
// If any output was cleaned, find the most recent mtime of any
// (existing) non-order-only input or the depfile.
for (vector<Node*>::iterator i = edge->inputs_.begin();
@@ -844,6 +848,8 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
// The total number of edges in the plan may have changed as a result
// of a restat.
status_->PlanHasTotalEdges(plan_.command_edge_count());
+
+ output_mtime = restat_mtime;
}
}
@@ -856,7 +862,7 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
if (scan_.build_log()) {
if (!scan_.build_log()->RecordCommand(edge, start_time, end_time,
- restat_mtime)) {
+ output_mtime)) {
*err = string("Error writing to build log: ") + strerror(errno);
return false;
}