summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorPhilip Lorenz <philip.lorenz@bmw.de>2024-10-30 10:26:43 +0100
committerSteve Sakoman <steve@sakoman.com>2024-11-15 06:05:32 -0800
commit3aaed26728b2d8bcb66db94792fc080a37e2d9d3 (patch)
tree3f3d9fcba6c7783a4ee9d831c73e8e0ab46e6477 /bitbake
parent51bd4260cb9592af4b63059a30f4f977e0a2fad6 (diff)
downloadpoky-3aaed26728b2d8bcb66db94792fc080a37e2d9d3.tar.gz
bitbake: codeparser: Fix handling of string AST nodes with older Python versions
Commits 4591011449212c8e494ea42348acb2d27a82a51b and 6c19b6cf105ac321ec89da1a876a317020c45ab7 unconditionally changed codeparser to rely on CPython 3.8 semantics. However, kirkstone continues to support CPython versions >= 3.6.0 and as such string AST nodes were no longer correctly identified. Fix this by continuing to use `ast.Str` for Python versions < 3.8.0 and only using the new code path for more recent versions. Detecting which version of the AST API to use seems to be non-trivial so the Python feature version is used instead. Instances of this issue can be identified when executing bitbake with debug logging: while parsing MACHINE_ARCH, in call of d.getVar, argument ''TUNE_PKGARCH'' is not a string literal As a consequence of these parsing issues, bitbake may assume that task inputs haven't changed and as such erroneously reuse sstate objects when it shouldn't. (Bitbake rev: fb73c495c45d1d4107cfd60b67a5b4f11a99647b) Signed-off-by: Philip Lorenz <philip.lorenz@bmw.de> Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/codeparser.py46
1 files changed, 33 insertions, 13 deletions
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py
index 6ce0c5182f..39dba266cd 100644
--- a/bitbake/lib/bb/codeparser.py
+++ b/bitbake/lib/bb/codeparser.py
@@ -201,6 +201,22 @@ class DummyLogger():
201 def flush(self): 201 def flush(self):
202 return 202 return
203 203
204
205# Starting with Python 3.8, the ast module exposes all string nodes as a
206# Constant. While earlier versions of the module also have the Constant type
207# those use the Str type to encapsulate strings.
208if sys.version_info < (3, 8):
209 def node_str_value(node):
210 if isinstance(node, ast.Str):
211 return node.s
212 return None
213else:
214 def node_str_value(node):
215 if isinstance(node, ast.Constant) and isinstance(node.value, str):
216 return node.value
217 return None
218
219
204class PythonParser(): 220class PythonParser():
205 getvars = (".getVar", ".appendVar", ".prependVar", "oe.utils.conditional") 221 getvars = (".getVar", ".appendVar", ".prependVar", "oe.utils.conditional")
206 getvarflags = (".getVarFlag", ".appendVarFlag", ".prependVarFlag") 222 getvarflags = (".getVarFlag", ".appendVarFlag", ".prependVarFlag")
@@ -225,19 +241,22 @@ class PythonParser():
225 def visit_Call(self, node): 241 def visit_Call(self, node):
226 name = self.called_node_name(node.func) 242 name = self.called_node_name(node.func)
227 if name and (name.endswith(self.getvars) or name.endswith(self.getvarflags) or name in self.containsfuncs or name in self.containsanyfuncs): 243 if name and (name.endswith(self.getvars) or name.endswith(self.getvarflags) or name in self.containsfuncs or name in self.containsanyfuncs):
228 if isinstance(node.args[0], ast.Constant) and isinstance(node.args[0].value, str): 244 varname = node_str_value(node.args[0])
229 varname = node.args[0].value 245 if varname is not None:
230 if name in self.containsfuncs and isinstance(node.args[1], ast.Constant): 246 arg_str_value = None
247 if len(node.args) >= 2:
248 arg_str_value = node_str_value(node.args[1])
249 if name in self.containsfuncs and arg_str_value is not None:
231 if varname not in self.contains: 250 if varname not in self.contains:
232 self.contains[varname] = set() 251 self.contains[varname] = set()
233 self.contains[varname].add(node.args[1].value) 252 self.contains[varname].add(arg_str_value)
234 elif name in self.containsanyfuncs and isinstance(node.args[1], ast.Constant): 253 elif name in self.containsanyfuncs and arg_str_value is not None:
235 if varname not in self.contains: 254 if varname not in self.contains:
236 self.contains[varname] = set() 255 self.contains[varname] = set()
237 self.contains[varname].update(node.args[1].value.split()) 256 self.contains[varname].update(arg_str_value.split())
238 elif name.endswith(self.getvarflags): 257 elif name.endswith(self.getvarflags):
239 if isinstance(node.args[1], ast.Constant): 258 if arg_str_value is not None:
240 self.references.add('%s[%s]' % (varname, node.args[1].value)) 259 self.references.add('%s[%s]' % (varname, arg_str_value))
241 else: 260 else:
242 self.warn(node.func, node.args[1]) 261 self.warn(node.func, node.args[1])
243 else: 262 else:
@@ -245,10 +264,10 @@ class PythonParser():
245 else: 264 else:
246 self.warn(node.func, node.args[0]) 265 self.warn(node.func, node.args[0])
247 elif name and name.endswith(".expand"): 266 elif name and name.endswith(".expand"):
248 if isinstance(node.args[0], ast.Constant): 267 arg_str_value = node_str_value(node.args[0])
249 value = node.args[0].value 268 if arg_str_value is not None:
250 d = bb.data.init() 269 d = bb.data.init()
251 parser = d.expandWithRefs(value, self.name) 270 parser = d.expandWithRefs(arg_str_value, self.name)
252 self.references |= parser.references 271 self.references |= parser.references
253 self.execs |= parser.execs 272 self.execs |= parser.execs
254 for varname in parser.contains: 273 for varname in parser.contains:
@@ -256,8 +275,9 @@ class PythonParser():
256 self.contains[varname] = set() 275 self.contains[varname] = set()
257 self.contains[varname] |= parser.contains[varname] 276 self.contains[varname] |= parser.contains[varname]
258 elif name in self.execfuncs: 277 elif name in self.execfuncs:
259 if isinstance(node.args[0], ast.Constant): 278 arg_str_value = node_str_value(node.args[0])
260 self.var_execs.add(node.args[0].value) 279 if arg_str_value is not None:
280 self.var_execs.add(arg_str_value)
261 else: 281 else:
262 self.warn(node.func, node.args[0]) 282 self.warn(node.func, node.args[0])
263 elif name and isinstance(node.func, (ast.Name, ast.Attribute)): 283 elif name and isinstance(node.func, (ast.Name, ast.Attribute)):