builder.py: now the only exported function is main().
We can also avoid forking altogether if should_build() returns false. This doesn't seem to result in any noticeable speedup, but it's cleaner at least.
This commit is contained in:
parent
547dbe550f
commit
3209316856
3 changed files with 36 additions and 27 deletions
45
builder.py
45
builder.py
|
|
@ -41,7 +41,7 @@ def _nice(t):
|
||||||
return os.path.normpath(os.path.join(vars.PWD, t))
|
return os.path.normpath(os.path.join(vars.PWD, t))
|
||||||
|
|
||||||
|
|
||||||
def build(t):
|
def _build(t):
|
||||||
if (os.path.exists(t) and not state.is_generated(t)
|
if (os.path.exists(t) and not state.is_generated(t)
|
||||||
and not os.path.exists('%s.do' % t)):
|
and not os.path.exists('%s.do' % t)):
|
||||||
# an existing source file that is not marked as a generated file.
|
# an existing source file that is not marked as a generated file.
|
||||||
|
|
@ -68,12 +68,9 @@ def build(t):
|
||||||
ext, # extension (if any), including leading dot
|
ext, # extension (if any), including leading dot
|
||||||
os.path.basename(tmpname) # randomized output file name
|
os.path.basename(tmpname) # randomized output file name
|
||||||
]
|
]
|
||||||
if vars.VERBOSE:
|
if vars.VERBOSE: argv[1] += 'v'
|
||||||
argv[1] += 'v'
|
if vars.XTRACE: argv[1] += 'x'
|
||||||
if vars.XTRACE:
|
if vars.VERBOSE or vars.XTRACE: log_('\n')
|
||||||
argv[1] += 'x'
|
|
||||||
if vars.VERBOSE or vars.XTRACE:
|
|
||||||
log_('\n')
|
|
||||||
log('%s\n' % _nice(t))
|
log('%s\n' % _nice(t))
|
||||||
rv = subprocess.call(argv, preexec_fn=lambda: _preexec(t),
|
rv = subprocess.call(argv, preexec_fn=lambda: _preexec(t),
|
||||||
stdout=f.fileno())
|
stdout=f.fileno())
|
||||||
|
|
@ -97,7 +94,28 @@ def build(t):
|
||||||
log('%s (done)\n\n' % _nice(t))
|
log('%s (done)\n\n' % _nice(t))
|
||||||
|
|
||||||
|
|
||||||
def main(targets, buildfunc):
|
class BuildJob:
|
||||||
|
def __init__(self, t, lock, shouldbuildfunc, donefunc):
|
||||||
|
self.t = t
|
||||||
|
self.lock = lock
|
||||||
|
self.shouldbuildfunc = shouldbuildfunc
|
||||||
|
self.donefunc = donefunc
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if not self.shouldbuildfunc(self.t):
|
||||||
|
# target doesn't need to be built; skip the whole task
|
||||||
|
self.done(self.t, 0)
|
||||||
|
return
|
||||||
|
jwack.start_job(self.t, self.lock, self.build, self.done)
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return _build(self.t)
|
||||||
|
|
||||||
|
def done(self, name, rv):
|
||||||
|
return self.donefunc(self.t, rv)
|
||||||
|
|
||||||
|
|
||||||
|
def main(targets, shouldbuildfunc):
|
||||||
retcode = [0] # a list so that it can be reassigned from done()
|
retcode = [0] # a list so that it can be reassigned from done()
|
||||||
if vars.SHUFFLE:
|
if vars.SHUFFLE:
|
||||||
random.shuffle(targets)
|
random.shuffle(targets)
|
||||||
|
|
@ -106,7 +124,6 @@ def main(targets, buildfunc):
|
||||||
|
|
||||||
def done(t, rv):
|
def done(t, rv):
|
||||||
if rv:
|
if rv:
|
||||||
#err('%s: exit code was %r\n' % (t, rv))
|
|
||||||
retcode[0] = 1
|
retcode[0] = 1
|
||||||
|
|
||||||
for i in range(len(targets)):
|
for i in range(len(targets)):
|
||||||
|
|
@ -128,8 +145,8 @@ def main(targets, buildfunc):
|
||||||
log('%s (locked...)\n' % _nice(t))
|
log('%s (locked...)\n' % _nice(t))
|
||||||
locked.append(t)
|
locked.append(t)
|
||||||
else:
|
else:
|
||||||
jwack.start_job(t, lock,
|
j = BuildJob(t, lock, shouldbuildfunc, done)
|
||||||
lambda: buildfunc(t), lambda t,rv: done(t,rv))
|
j.start()
|
||||||
|
|
||||||
# Now we've built all the "easy" ones. Go back and just wait on the
|
# Now we've built all the "easy" ones. Go back and just wait on the
|
||||||
# remaining ones one by one. This is technically non-optimal; we could
|
# remaining ones one by one. This is technically non-optimal; we could
|
||||||
|
|
@ -137,6 +154,8 @@ def main(targets, buildfunc):
|
||||||
# be rare enough that it doesn't matter, and the logic is easier this way.
|
# be rare enough that it doesn't matter, and the logic is easier this way.
|
||||||
while locked or jwack.running():
|
while locked or jwack.running():
|
||||||
jwack.wait_all()
|
jwack.wait_all()
|
||||||
|
# at this point, we don't have any children holding any tokens, so
|
||||||
|
# it's okay to block below.
|
||||||
if retcode[0] and not vars.KEEP_GOING:
|
if retcode[0] and not vars.KEEP_GOING:
|
||||||
break
|
break
|
||||||
if locked:
|
if locked:
|
||||||
|
|
@ -151,6 +170,6 @@ def main(targets, buildfunc):
|
||||||
retcode[0] = 2
|
retcode[0] = 2
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
else:
|
else:
|
||||||
jwack.start_job(t, lock,
|
j = BuildJob(t, lock, shouldbuildfunc, done)
|
||||||
lambda: buildfunc(t), lambda t,rv: done(t,rv))
|
j.start()
|
||||||
return retcode[0]
|
return retcode[0]
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,6 @@ def should_build(t):
|
||||||
return not state.isbuilt(t) and dirty_deps(t, depth = '')
|
return not state.isbuilt(t) and dirty_deps(t, depth = '')
|
||||||
|
|
||||||
|
|
||||||
def maybe_build(t):
|
|
||||||
if should_build(t):
|
|
||||||
return builder.build(t)
|
|
||||||
|
|
||||||
|
|
||||||
if not vars.TARGET:
|
if not vars.TARGET:
|
||||||
err('redo-ifchange: error: must be run from inside a .do\n')
|
err('redo-ifchange: error: must be run from inside a .do\n')
|
||||||
sys.exit(100)
|
sys.exit(100)
|
||||||
|
|
@ -57,13 +52,10 @@ if not vars.TARGET:
|
||||||
rv = 202
|
rv = 202
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
want_build = []
|
targets = sys.argv[1:]
|
||||||
for t in sys.argv[1:]:
|
for t in targets:
|
||||||
state.add_dep(vars.TARGET, 'm', t)
|
state.add_dep(vars.TARGET, 'm', t)
|
||||||
if should_build(t):
|
rv = builder.main(targets, should_build)
|
||||||
want_build.append(t)
|
|
||||||
|
|
||||||
rv = builder.main(want_build, maybe_build)
|
|
||||||
finally:
|
finally:
|
||||||
jwack.force_return_tokens()
|
jwack.force_return_tokens()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
||||||
4
redo.py
4
redo.py
|
|
@ -67,11 +67,9 @@ try:
|
||||||
err('invalid --jobs value: %r\n' % opt.jobs)
|
err('invalid --jobs value: %r\n' % opt.jobs)
|
||||||
jwack.setup(j)
|
jwack.setup(j)
|
||||||
try:
|
try:
|
||||||
retcode = builder.main(targets, builder.build)
|
retcode = builder.main(targets, lambda t: True)
|
||||||
finally:
|
finally:
|
||||||
jwack.force_return_tokens()
|
jwack.force_return_tokens()
|
||||||
#if retcode:
|
|
||||||
# err('exiting: %d\n' % retcode)
|
|
||||||
sys.exit(retcode)
|
sys.exit(retcode)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit(200)
|
sys.exit(200)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue