diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-06-27 15:13:45 +0100 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2024-07-26 07:43:46 -0700 |
commit | 7b4cc330228d1853a74e85fb415f9a06b8183927 (patch) | |
tree | 9345f55fe47f72f7ec57fd34d0ba9e3c77d3d372 /bitbake | |
parent | 688146cd1893d81dc6deed56a05250c52e6432bb (diff) | |
download | poky-7b4cc330228d1853a74e85fb415f9a06b8183927.tar.gz |
bitbake: codeparser/data: Ensure module function contents changing is accounted for
Currently, if a pylib function changes contents, the taskhash remains
unchanged since we assume the functions have stable output. This is
probably a poor assumption so take the code of the function into account
in the taskhashes. This avoids certain frustrating build failures we've
been seeing in automated testing.
To make this work we have to add an extra entry to the python code parsing
cache so that we can store the hashed function contents for efficiency as
in the python module case, that isn't used as the key to the cache.
The cache version changes since we're adding data to the cache.
(Bitbake rev: 4bf332ccac283ca3440e81d8c781fcc23fe10b98)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit b2c3438ebe62793ebabe2c282534893908d520b4)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'bitbake')
-rw-r--r-- | bitbake/lib/bb/codeparser.py | 28 | ||||
-rw-r--r-- | bitbake/lib/bb/data.py | 2 |
2 files changed, 18 insertions, 12 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py index 2e8b7ced3c..0b2890cf8a 100644 --- a/bitbake/lib/bb/codeparser.py +++ b/bitbake/lib/bb/codeparser.py | |||
@@ -82,14 +82,14 @@ def add_module_functions(fn, functions, namespace): | |||
82 | if e in functions: | 82 | if e in functions: |
83 | execs.remove(e) | 83 | execs.remove(e) |
84 | execs.add(namespace + "." + e) | 84 | execs.add(namespace + "." + e) |
85 | modulecode_deps[name] = [parser.references.copy(), execs, parser.var_execs.copy(), parser.contains.copy()] | 85 | modulecode_deps[name] = [parser.references.copy(), execs, parser.var_execs.copy(), parser.contains.copy(), parser.extra] |
86 | #bb.warn("%s: %s\nRefs:%s Execs: %s %s %s" % (name, fn, parser.references, parser.execs, parser.var_execs, parser.contains)) | 86 | #bb.warn("%s: %s\nRefs:%s Execs: %s %s %s" % (name, fn, parser.references, parser.execs, parser.var_execs, parser.contains)) |
87 | 87 | ||
88 | def update_module_dependencies(d): | 88 | def update_module_dependencies(d): |
89 | for mod in modulecode_deps: | 89 | for mod in modulecode_deps: |
90 | excludes = set((d.getVarFlag(mod, "vardepsexclude") or "").split()) | 90 | excludes = set((d.getVarFlag(mod, "vardepsexclude") or "").split()) |
91 | if excludes: | 91 | if excludes: |
92 | modulecode_deps[mod] = [modulecode_deps[mod][0] - excludes, modulecode_deps[mod][1] - excludes, modulecode_deps[mod][2] - excludes, modulecode_deps[mod][3]] | 92 | modulecode_deps[mod] = [modulecode_deps[mod][0] - excludes, modulecode_deps[mod][1] - excludes, modulecode_deps[mod][2] - excludes, modulecode_deps[mod][3], modulecode_deps[mod][4]] |
93 | 93 | ||
94 | # A custom getstate/setstate using tuples is actually worth 15% cachesize by | 94 | # A custom getstate/setstate using tuples is actually worth 15% cachesize by |
95 | # avoiding duplication of the attribute names! | 95 | # avoiding duplication of the attribute names! |
@@ -112,21 +112,22 @@ class SetCache(object): | |||
112 | codecache = SetCache() | 112 | codecache = SetCache() |
113 | 113 | ||
114 | class pythonCacheLine(object): | 114 | class pythonCacheLine(object): |
115 | def __init__(self, refs, execs, contains): | 115 | def __init__(self, refs, execs, contains, extra): |
116 | self.refs = codecache.internSet(refs) | 116 | self.refs = codecache.internSet(refs) |
117 | self.execs = codecache.internSet(execs) | 117 | self.execs = codecache.internSet(execs) |
118 | self.contains = {} | 118 | self.contains = {} |
119 | for c in contains: | 119 | for c in contains: |
120 | self.contains[c] = codecache.internSet(contains[c]) | 120 | self.contains[c] = codecache.internSet(contains[c]) |
121 | self.extra = extra | ||
121 | 122 | ||
122 | def __getstate__(self): | 123 | def __getstate__(self): |
123 | return (self.refs, self.execs, self.contains) | 124 | return (self.refs, self.execs, self.contains, self.extra) |
124 | 125 | ||
125 | def __setstate__(self, state): | 126 | def __setstate__(self, state): |
126 | (refs, execs, contains) = state | 127 | (refs, execs, contains, extra) = state |
127 | self.__init__(refs, execs, contains) | 128 | self.__init__(refs, execs, contains, extra) |
128 | def __hash__(self): | 129 | def __hash__(self): |
129 | l = (hash(self.refs), hash(self.execs)) | 130 | l = (hash(self.refs), hash(self.execs), hash(self.extra)) |
130 | for c in sorted(self.contains.keys()): | 131 | for c in sorted(self.contains.keys()): |
131 | l = l + (c, hash(self.contains[c])) | 132 | l = l + (c, hash(self.contains[c])) |
132 | return hash(l) | 133 | return hash(l) |
@@ -155,7 +156,7 @@ class CodeParserCache(MultiProcessCache): | |||
155 | # so that an existing cache gets invalidated. Additionally you'll need | 156 | # so that an existing cache gets invalidated. Additionally you'll need |
156 | # to increment __cache_version__ in cache.py in order to ensure that old | 157 | # to increment __cache_version__ in cache.py in order to ensure that old |
157 | # recipe caches don't trigger "Taskhash mismatch" errors. | 158 | # recipe caches don't trigger "Taskhash mismatch" errors. |
158 | CACHE_VERSION = 11 | 159 | CACHE_VERSION = 12 |
159 | 160 | ||
160 | def __init__(self): | 161 | def __init__(self): |
161 | MultiProcessCache.__init__(self) | 162 | MultiProcessCache.__init__(self) |
@@ -169,8 +170,8 @@ class CodeParserCache(MultiProcessCache): | |||
169 | self.pythoncachelines = {} | 170 | self.pythoncachelines = {} |
170 | self.shellcachelines = {} | 171 | self.shellcachelines = {} |
171 | 172 | ||
172 | def newPythonCacheLine(self, refs, execs, contains): | 173 | def newPythonCacheLine(self, refs, execs, contains, extra): |
173 | cacheline = pythonCacheLine(refs, execs, contains) | 174 | cacheline = pythonCacheLine(refs, execs, contains, extra) |
174 | h = hash(cacheline) | 175 | h = hash(cacheline) |
175 | if h in self.pythoncachelines: | 176 | if h in self.pythoncachelines: |
176 | return self.pythoncachelines[h] | 177 | return self.pythoncachelines[h] |
@@ -338,6 +339,7 @@ class PythonParser(): | |||
338 | self.contains = {} | 339 | self.contains = {} |
339 | for i in codeparsercache.pythoncache[h].contains: | 340 | for i in codeparsercache.pythoncache[h].contains: |
340 | self.contains[i] = set(codeparsercache.pythoncache[h].contains[i]) | 341 | self.contains[i] = set(codeparsercache.pythoncache[h].contains[i]) |
342 | self.extra = codeparsercache.pythoncache[h].extra | ||
341 | return | 343 | return |
342 | 344 | ||
343 | if h in codeparsercache.pythoncacheextras: | 345 | if h in codeparsercache.pythoncacheextras: |
@@ -346,6 +348,7 @@ class PythonParser(): | |||
346 | self.contains = {} | 348 | self.contains = {} |
347 | for i in codeparsercache.pythoncacheextras[h].contains: | 349 | for i in codeparsercache.pythoncacheextras[h].contains: |
348 | self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i]) | 350 | self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i]) |
351 | self.extra = codeparsercache.pythoncacheextras[h].extra | ||
349 | return | 352 | return |
350 | 353 | ||
351 | if fixedhash and not node: | 354 | if fixedhash and not node: |
@@ -364,8 +367,11 @@ class PythonParser(): | |||
364 | self.visit_Call(n) | 367 | self.visit_Call(n) |
365 | 368 | ||
366 | self.execs.update(self.var_execs) | 369 | self.execs.update(self.var_execs) |
370 | self.extra = None | ||
371 | if fixedhash: | ||
372 | self.extra = bbhash(str(node)) | ||
367 | 373 | ||
368 | codeparsercache.pythoncacheextras[h] = codeparsercache.newPythonCacheLine(self.references, self.execs, self.contains) | 374 | codeparsercache.pythoncacheextras[h] = codeparsercache.newPythonCacheLine(self.references, self.execs, self.contains, self.extra) |
369 | 375 | ||
370 | class ShellParser(): | 376 | class ShellParser(): |
371 | def __init__(self, name, log): | 377 | def __init__(self, name, log): |
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py index 505f42950f..f672a84451 100644 --- a/bitbake/lib/bb/data.py +++ b/bitbake/lib/bb/data.py | |||
@@ -293,7 +293,7 @@ def build_dependencies(key, keys, mod_funcs, shelldeps, varflagsexcl, ignored_va | |||
293 | if key in mod_funcs: | 293 | if key in mod_funcs: |
294 | exclusions = set() | 294 | exclusions = set() |
295 | moddep = bb.codeparser.modulecode_deps[key] | 295 | moddep = bb.codeparser.modulecode_deps[key] |
296 | value = handle_contains("", moddep[3], exclusions, d) | 296 | value = handle_contains(moddep[4], moddep[3], exclusions, d) |
297 | return frozenset((moddep[0] | keys & moddep[1]) - ignored_vars), value | 297 | return frozenset((moddep[0] | keys & moddep[1]) - ignored_vars), value |
298 | 298 | ||
299 | if key[-1] == ']': | 299 | if key[-1] == ']': |