build/siggen: Add support for stamp 'clean' masks
PATCH 1/1 build/siggen: Add support for stamp 'clean' masks
Currently when we execute a task, we don't remove other potentially stale stamps. This can mean if you switch between two different versions of a recipe without a clean, the build can get very confused.
This patch adds in functionality to allow a wildcard expression of stamp files to be removed when creating a new stamp file. This patch adds in the core of the code to enable this but it also requires metadata support to enable it.
When writing this improvement I went through several different options but this was the only way I could find to allow things like noexec tasks to function correctly (where stamps need to be created without the data store).
[YOCTO #2961]
Signed-off-by Richard Purdie <[email protected]>
---
bitbake/lib/bb/build.py +29 -0
@@ -470,11 +470,40 @@ def stamp_internal(taskname, d, file_name): return stamp +def stamp_cleanmask_internal(taskname, d, file_name): + """ + Internal stamp helper function to generate stamp cleaning mask + Returns the stamp path+filename + + In the bitbake core, d can be a CacheData and file_name will be set. + When called in task context, d will be a data store, file_name will not be set + """ + taskflagname = taskname + if taskname.endswith("_setscene") and taskname != "do_setscene": + taskflagname = taskname.replace("_setscene", "") + + if file_name: + stamp = d.stamp_base_clean[file_name].get(taskflagname) or d.stampclean[file_name] + extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or "" + else: + stamp = d.getVarFlag(taskflagname, 'stamp-base-clean', True) or d.getVar('STAMPCLEAN', True) + file_name = d.getVar('BB_FILENAME', True) + extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or "" + + if not stamp: + return + + return bb.parse.siggen.stampcleanmask(stamp, file_name, taskname, extrainfo) + def make_stamp(task, d, file_name = None): """ Creates/updates a stamp for a given task (d can be a data dict or dataCache) """ + cleanmask = stamp_cleanmask_internal(task, d, file_name) + if cleanmask: + bb.utils.remove(cleanmask) + stamp = stamp_internal(task, d, file_name) # Remove the file and recreate to force timestamp # change on broken NFS filesystems
bitbake/lib/bb/cache.py +7 -1
@@ -43,7 +43,7 @@ except ImportError: logger.info("Importing cPickle failed. " "Falling back to a very slow implementation.") -__cache_version__ = "144" +__cache_version__ = "145" def getCacheFile(path, filename, data_hash): return os.path.join(path, filename + "." + data_hash)
@@ -130,7 +130,9 @@ class CoreRecipeInfo(RecipeInfoCommon): self.broken = self.getvar('BROKEN', metadata) self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata) self.stamp = self.getvar('STAMP', metadata) + self.stampclean = self.getvar('STAMPCLEAN', metadata) self.stamp_base = self.flaglist('stamp-base', self.tasks, metadata) + self.stamp_base_clean = self.flaglist('stamp-base-clean', self.tasks, metadata) self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata) self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True) self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
@@ -157,7 +159,9 @@ class CoreRecipeInfo(RecipeInfoCommon): cachedata.pkg_dp = {} cachedata.stamp = {} + cachedata.stampclean = {} cachedata.stamp_base = {} + cachedata.stamp_base_clean = {} cachedata.stamp_extrainfo = {} cachedata.file_checksums = {} cachedata.fn_provides = {}
@@ -189,7 +193,9 @@ class CoreRecipeInfo(RecipeInfoCommon): cachedata.pkg_pepvpr[fn] = (self.pe, self.pv, self.pr) cachedata.pkg_dp[fn] = self.defaultpref cachedata.stamp[fn] = self.stamp + cachedata.stampclean[fn] = self.stampclean cachedata.stamp_base[fn] = self.stamp_base + cachedata.stamp_base_clean[fn] = self.stamp_base_clean cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo cachedata.file_checksums[fn] = self.file_checksums
bitbake/lib/bb/siggen.py +11 -2
@@ -48,6 +48,9 @@ class SignatureGenerator(object): def stampfile(self, stampbase, file_name, taskname, extrainfo): return ("%s.%s.%s" % (stampbase, taskname, extrainfo)).rstrip('.') + def stampcleanmask(self, stampbase, file_name, taskname, extrainfo): + return ("%s.%s*.%s" % (stampbase, taskname, extrainfo)).rstrip('.') + def dump_sigtask(self, fn, task, stampbase, runtime): return
@@ -266,18 +269,24 @@ class SignatureGeneratorBasic(SignatureGenerator): class SignatureGeneratorBasicHash(SignatureGeneratorBasic): name = "basichash" - def stampfile(self, stampbase, fn, taskname, extrainfo): + def stampfile(self, stampbase, fn, taskname, extrainfo, clean=False): if taskname != "do_setscene" and taskname.endswith("_setscene"): k = fn + "." + taskname[:-9] else: k = fn + "." + taskname - if k in self.taskhash: + if clean: + h = "*" + taskname = taskname + "*" + elif k in self.taskhash: h = self.taskhash[k] else: # If k is not in basehash, then error h = self.basehash[k] return ("%s.%s.%s.%s" % (stampbase, taskname, h, extrainfo)).rstrip('.') + def stampcleanmask(self, stampbase, fn, taskname, extrainfo): + return self.stampfile(stampbase, fn, taskname, extrainfo, clean=True) + def invalidate_task(self, task, d, fn): bb.note("Tainting hash to force rebuild of task %s, %s" % (fn, task)) bb.build.write_taint(task, d, fn)