summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/codeparser.py
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-11-27 21:16:16 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-12-17 08:52:28 +0000
commitf3bcd3c9a91f6212c30b9c778c11f3c8a9f6f1d4 (patch)
tree760b8dac27191ea1a625476d84c0651aa2788a5f /bitbake/lib/bb/codeparser.py
parenta225aa3ec4726161172ca4b03d02751b1250e7ae (diff)
downloadpoky-f3bcd3c9a91f6212c30b9c778c11f3c8a9f6f1d4.tar.gz
bitbake: ast/data/codeparser: Add dependencies from python module functions
Moving code into python modules is a very effective way to reduce parsing time and overhead in recipes. The downside has always been that any dependency information on which variables those functions access is lost and the hashes can therefore become less reliable. This patch adds parsing of the imported module functions and that dependency information is them injected back into the hash dependency information. Intermodule function references are resolved to the full function call names in our module namespace to ensure interfunction dependencies are correctly handled too. (Bitbake rev: 605c478ce14cdc3c02d6ef6d57146a76d436a83c) (Bitbake rev: 91441e157e495b02db44e19e836afad366ee8924) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/codeparser.py')
-rw-r--r--bitbake/lib/bb/codeparser.py43
1 files changed, 38 insertions, 5 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py
index 9d66d3ae41..c0b1d7966f 100644
--- a/bitbake/lib/bb/codeparser.py
+++ b/bitbake/lib/bb/codeparser.py
@@ -27,6 +27,7 @@ import ast
27import sys 27import sys
28import codegen 28import codegen
29import logging 29import logging
30import inspect
30import bb.pysh as pysh 31import bb.pysh as pysh
31import bb.utils, bb.data 32import bb.utils, bb.data
32import hashlib 33import hashlib
@@ -58,10 +59,33 @@ def check_indent(codestr):
58 59
59 return codestr 60 return codestr
60 61
61# A custom getstate/setstate using tuples is actually worth 15% cachesize by 62modulecode_deps = {}
62# avoiding duplication of the attribute names!
63 63
64def add_module_functions(fn, functions, namespace):
65 fstat = os.stat(fn)
66 fixedhash = fn + ":" + str(fstat.st_size) + ":" + str(fstat.st_mtime)
67 for f in functions:
68 name = "%s.%s" % (namespace, f)
69 parser = PythonParser(name, logger)
70 try:
71 parser.parse_python(None, filename=fn, lineno=1, fixedhash=fixedhash+f)
72 #bb.warn("Cached %s" % f)
73 except KeyError:
74 lines, lineno = inspect.getsourcelines(functions[f])
75 src = "".join(lines)
76 parser.parse_python(src, filename=fn, lineno=lineno, fixedhash=fixedhash+f)
77 #bb.warn("Not cached %s" % f)
78 execs = parser.execs.copy()
79 # Expand internal module exec references
80 for e in parser.execs:
81 if e in functions:
82 execs.remove(e)
83 execs.add(namespace + "." + e)
84 modulecode_deps[name] = [parser.references.copy(), execs, parser.var_execs.copy(), parser.contains.copy()]
85 #bb.warn("%s: %s\nRefs:%s Execs: %s %s %s" % (name, src, parser.references, parser.execs, parser.var_execs, parser.contains))
64 86
87# A custom getstate/setstate using tuples is actually worth 15% cachesize by
88# avoiding duplication of the attribute names!
65class SetCache(object): 89class SetCache(object):
66 def __init__(self): 90 def __init__(self):
67 self.setcache = {} 91 self.setcache = {}
@@ -289,11 +313,17 @@ class PythonParser():
289 self.unhandled_message = "in call of %s, argument '%s' is not a string literal" 313 self.unhandled_message = "in call of %s, argument '%s' is not a string literal"
290 self.unhandled_message = "while parsing %s, %s" % (name, self.unhandled_message) 314 self.unhandled_message = "while parsing %s, %s" % (name, self.unhandled_message)
291 315
292 def parse_python(self, node, lineno=0, filename="<string>"): 316 # For the python module code it is expensive to have the function text so it is
293 if not node or not node.strip(): 317 # uses a different fixedhash to cache against. We can take the hit on obtaining the
318 # text if it isn't in the cache.
319 def parse_python(self, node, lineno=0, filename="<string>", fixedhash=None):
320 if not fixedhash and (not node or not node.strip()):
294 return 321 return
295 322
296 h = bbhash(str(node)) 323 if fixedhash:
324 h = fixedhash
325 else:
326 h = bbhash(str(node))
297 327
298 if h in codeparsercache.pythoncache: 328 if h in codeparsercache.pythoncache:
299 self.references = set(codeparsercache.pythoncache[h].refs) 329 self.references = set(codeparsercache.pythoncache[h].refs)
@@ -311,6 +341,9 @@ class PythonParser():
311 self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i]) 341 self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i])
312 return 342 return
313 343
344 if fixedhash and not node:
345 raise KeyError
346
314 # Need to parse so take the hit on the real log buffer 347 # Need to parse so take the hit on the real log buffer
315 self.log = BufferedLogger('BitBake.Data.PythonParser', logging.DEBUG, self._log) 348 self.log = BufferedLogger('BitBake.Data.PythonParser', logging.DEBUG, self._log)
316 349