Don't wipe the timestamp when a target fails to redo.

It's really a separate condition.  And since we're not removing the target
*file* in case of error - we update it atomically, and keeping it is better
than losing it - there's no reason to wipe the timestamp in that case
either.

However, we do need to know that the build failed, so that anybody else
(especially in a parallel build) who looks at that target knows that it
died.  So add a separate flag just for that.
This commit is contained in:
Avery Pennarun 2010-12-10 20:53:31 -08:00
commit 0126f6be1e
4 changed files with 39 additions and 17 deletions

View file

@ -42,6 +42,12 @@ def _try_stat(filename):
raise
class ImmediateReturn(Exception):
def __init__(self, rv):
Exception.__init__(self, "immediate return with exit code %d" % rv)
self.rv = rv
class BuildJob:
def __init__(self, t, sf, lock, shouldbuildfunc, donefunc):
self.t = t # original target name, not relative to vars.BASE
@ -57,9 +63,12 @@ class BuildJob:
t = self.t
sf = self.sf
tmpname = self.tmpname
if not self.shouldbuildfunc(t):
# target doesn't need to be built; skip the whole task
return self._after2(0)
try:
if not self.shouldbuildfunc(t):
# target doesn't need to be built; skip the whole task
return self._after2(0)
except ImmediateReturn, e:
return self._after2(e.rv)
if (os.path.exists(t) and not os.path.exists(t + '/.')
and not sf.is_generated):
# an existing source file that was not generated by us.
@ -174,8 +183,7 @@ class BuildJob:
else:
unlink(tmpname)
sf = self.sf
sf.stamp = None
sf.set_changed()
sf.set_failed()
sf.save()
f.close()
if rv != 0:
@ -259,7 +267,7 @@ def main(targets, shouldbuildfunc):
assert(lock.owned)
if vars.DEBUG_LOCKS:
log('%s (...unlocked!)\n' % _nice(t))
if state.File(name=t).stamp == None:
if state.File(name=t).is_failed():
err('%s: failed in another thread\n' % _nice(t))
retcode[0] = 2
lock.unlock()