2
0
mirror of https://gitlab.com/ita1024/waf.git synced 2024-11-26 03:39:53 +01:00

Split fast_partial data storage from the main pickle file

This commit is contained in:
Thomas Nagy 2017-08-06 11:48:25 +02:00
parent ee3f706bb7
commit 6ed9a9231f
No known key found for this signature in database
GPG Key ID: 49B4C67C05277AAA

View File

@ -30,12 +30,36 @@ NEEDED = 2
SKIPPABLE = ['cshlib', 'cxxshlib', 'cstlib', 'cxxstlib', 'cprogram', 'cxxprogram']
TSTAMP_DB = '.wafpickle_tstamp_db_file'
class bld(Build.BuildContext):
def store(self):
def is_dirty(self):
return True
def store_tstamps(self):
# For each task generator, record all files involved in task objects
# optimization: done only if there was something built
do_store = False
try:
f_deps = self.f_deps
except AttributeError:
f_deps = self.f_deps = {}
for g in self.groups:
for tg in g:
try:
staleness = tg.staleness
except AttributeError:
staleness = DIRTY
if staleness != DIRTY:
# DONE case: there was nothing built
# NEEDED case: the tg was brought in because of 'use' propagation
# but nothing really changed for them, there may be incomplete
# tasks (object files) and in this case it is best to let the next build
# figure out if an input/output file changed
continue
do_cache = False
for tsk in tg.tasks:
if tsk.hasrun == Task.SUCCESS:
@ -44,21 +68,31 @@ class bld(Build.BuildContext):
elif tsk.hasrun == Task.SKIPPED:
pass
else:
# dependencies are incomplete, clear the cache
# one failed task, clear the cache for this tg
try:
del self.raw_deps[(tg.path.abspath(), tg.idx)]
del f_deps[(tg.path.abspath(), tg.idx)]
except KeyError:
pass
else:
# just store the new state because there is a change
do_store = True
# skip the rest because there is no valid cache possible
break
else:
if not do_cache:
# all skipped, but is there anything in cache?
try:
self.raw_deps[(tg.path.abspath(), tg.idx)]
f_deps[(tg.path.abspath(), tg.idx)]
except KeyError:
# probably cleared because a wscript file changed
# store it
do_cache = True
if do_cache:
# all tasks skipped but no cache
# or a successful task build
do_store = True
st = set()
for tsk in tg.tasks:
st.update(tsk.inputs)
@ -67,13 +101,41 @@ class bld(Build.BuildContext):
lst = [x.abspath() for x in tg.path.ant_glob('wscript*')]
lst.extend(sorted(x.abspath() for x in st))
tss = [os.stat(x).st_mtime for x in lst]
self.raw_deps[(tg.path.abspath(), tg.idx)] = (lst, tss)
f_deps[(tg.path.abspath(), tg.idx)] = (lst, tss)
return Build.BuildContext.store(self)
if do_store:
dbfn = os.path.join(self.variant_dir, TSTAMP_DB)
Logs.debug('rev_use: storing %s', dbfn)
dbfn_tmp = dbfn + '.tmp'
x = Build.cPickle.dumps(f_deps)
Utils.writef(dbfn_tmp, x, m='wb')
os.rename(dbfn_tmp, dbfn)
def store(self):
self.store_tstamps()
if self.producer.dirty:
Build.BuildContext.store(self)
def compute_needed_tgs(self):
# assume the 'use' keys are not modified during the build phase
dbfn = os.path.join(self.variant_dir, TSTAMP_DB)
Logs.debug('rev_use: Loading %s', dbfn)
try:
data = Utils.readf(dbfn, 'rb')
except (EnvironmentError, EOFError):
Logs.debug('rev_use: Could not load the build cache %s (missing)', dbfn)
self.f_deps = {}
else:
try:
self.f_deps = Build.cPickle.loads(data)
except Exception as e:
Logs.debug('rev_use: Could not pickle the build cache %s: %r', dbfn, e)
self.f_deps = {}
else:
Logs.debug('rev_use: Loaded %s', dbfn)
# 1. obtain task generators that contain rebuilds
# 2. obtain the 'use' graph and its dual
stales = set()
@ -179,9 +241,16 @@ def is_stale(self):
Logs.debug('rev_use: must post %r because the configuration has changed', self.name)
return True
# 3.a any tstamp data?
try:
f_deps = self.bld.f_deps
except AttributeError:
Logs.debug('rev_use: must post %r because there is no f_deps', self.name)
return True
# 4. check if this is the first build (no cache)
try:
lst, tss = self.bld.raw_deps[(self.path.abspath(), self.idx)]
lst, tss = f_deps[(self.path.abspath(), self.idx)]
except KeyError:
Logs.debug('rev_use: must post %r because there it has no cached data', self.name)
return True
@ -205,7 +274,7 @@ def is_stale(self):
try:
ts = tstamp(x)
except OSError:
del self.bld.raw_deps[(self.path.abspath(), self.idx)]
del f_deps[(self.path.abspath(), self.idx)]
Logs.debug('rev_use: must post %r because %r does not exist anymore', self.name, x)
return True
else:
@ -219,6 +288,7 @@ def is_stale(self):
@taskgen_method
def create_compiled_task(self, name, node):
# the purpose is to skip the creation of object files
# assumption: object-only targets are not skippable
if self.staleness == NEEDED:
# only libraries/programs can skip object files
for x in SKIPPABLE:
@ -236,7 +306,6 @@ def create_compiled_task(self, name, node):
@feature(*SKIPPABLE)
@after_method('apply_link')
def apply_link_after(self):
# assumption: object-only targets are not skippable
# cprogram/cxxprogram might be unnecessary
if self.staleness != NEEDED:
return