blob: f3ae06202285d599ef226096183d3e2a1d6a8180 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2BitBake 'Data' implementations
3
4Functions for interacting with the data structure used by the
5BitBake build tools.
6
Patrick Williams7784c422022-11-17 07:29:11 -06007expandKeys and datastore iteration are the most expensive
8operations. Updating overrides is now "on the fly" but still based
9on the idea of the cookie monster introduced by zecke:
10"At night the cookie monster came by and
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011suggested 'give me cookies on setting the variables and
12things will work out'. Taking this suggestion into account
13applying the skills from the not yet passed 'Entwurf und
14Analyse von Algorithmen' lecture and the cookie
15monster seems to be right. We will track setVar more carefully
Patrick Williams7784c422022-11-17 07:29:11 -060016to have faster datastore operations."
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017
18This is a trade-off between speed and memory again but
19the speed is more critical here.
20"""
21
22# Copyright (C) 2003, 2004 Chris Larson
23# Copyright (C) 2005 Holger Hans Peter Freyther
24#
Brad Bishopc342db32019-05-15 21:57:59 -040025# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026#
27# Based on functions from the base bb module, Copyright 2003 Holger Schurig
28
29import sys, os, re
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080030import hashlib
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031from itertools import groupby
32
33from bb import data_smart
34from bb import codeparser
35import bb
36
37logger = data_smart.logger
38_dict_type = data_smart.DataSmart
39
40def init():
41 """Return a new object representing the Bitbake data"""
42 return _dict_type()
43
44def init_db(parent = None):
45 """Return a new object representing the Bitbake data,
46 optionally based on an existing object"""
47 if parent is not None:
48 return parent.createCopy()
49 else:
50 return _dict_type()
51
52def createCopy(source):
53 """Link the source set to the destination
54 If one does not find the value in the destination set,
55 search will go on to the source set to get the value.
56 Value from source are copy-on-write. i.e. any try to
57 modify one of them will end up putting the modified value
58 in the destination set.
59 """
60 return source.createCopy()
61
62def initVar(var, d):
63 """Non-destructive var init for data structure"""
64 d.initVar(var)
65
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066def keys(d):
67 """Return a list of keys in d"""
68 return d.keys()
69
Patrick Williamsc124f4f2015-09-15 14:41:29 -050070def expand(s, d, varname = None):
71 """Variable expansion using the data store"""
72 return d.expand(s, varname)
73
74def expandKeys(alterdata, readdata = None):
Andrew Geissler82c905d2020-04-13 13:39:40 -050075 if readdata is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076 readdata = alterdata
77
78 todolist = {}
79 for key in alterdata:
80 if not '${' in key:
81 continue
82
83 ekey = expand(key, readdata)
84 if key == ekey:
85 continue
86 todolist[key] = ekey
87
88 # These two for loops are split for performance to maximise the
89 # usefulness of the expand cache
90 for key in sorted(todolist):
91 ekey = todolist[key]
92 newval = alterdata.getVar(ekey, False)
93 if newval is not None:
94 val = alterdata.getVar(key, False)
95 if val is not None:
96 bb.warn("Variable key %s (%s) replaces original key %s (%s)." % (key, val, ekey, newval))
97 alterdata.renameVar(key, ekey)
98
99def inheritFromOS(d, savedenv, permitted):
100 """Inherit variables from the initial environment."""
101 exportlist = bb.utils.preserved_envvars_exported()
102 for s in savedenv.keys():
103 if s in permitted:
104 try:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500105 d.setVar(s, savedenv.getVar(s), op = 'from env')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500106 if s in exportlist:
107 d.setVarFlag(s, "export", True, op = 'auto env export')
108 except TypeError:
109 pass
110
111def emit_var(var, o=sys.__stdout__, d = init(), all=False):
112 """Emit a variable to be sourced by a shell."""
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600113 func = d.getVarFlag(var, "func", False)
114 if d.getVarFlag(var, 'python', False) and func:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115 return False
116
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500117 export = d.getVarFlag(var, "export", False)
118 unexport = d.getVarFlag(var, "unexport", False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119 if not all and not export and not unexport and not func:
120 return False
121
122 try:
123 if all:
124 oval = d.getVar(var, False)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500125 val = d.getVar(var)
Brad Bishop08902b02019-08-20 09:16:51 -0400126 except (KeyboardInterrupt):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127 raise
128 except Exception as exc:
129 o.write('# expansion of %s threw %s: %s\n' % (var, exc.__class__.__name__, str(exc)))
130 return False
131
132 if all:
133 d.varhistory.emit(var, oval, val, o, d)
134
135 if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
136 return False
137
138 varExpanded = d.expand(var)
139
140 if unexport:
141 o.write('unset %s\n' % varExpanded)
142 return False
143
144 if val is None:
145 return False
146
147 val = str(val)
148
149 if varExpanded.startswith("BASH_FUNC_"):
150 varExpanded = varExpanded[10:-2]
151 val = val[3:] # Strip off "() "
152 o.write("%s() %s\n" % (varExpanded, val))
153 o.write("export -f %s\n" % (varExpanded))
154 return True
155
156 if func:
Andrew Geissler635e0e42020-08-21 15:58:33 -0500157 # Write a comment indicating where the shell function came from (line number and filename) to make it easier
158 # for the user to diagnose task failures. This comment is also used by build.py to determine the metadata
159 # location of shell functions.
160 o.write("# line: {0}, file: {1}\n".format(
161 d.getVarFlag(var, "lineno", False),
162 d.getVarFlag(var, "filename", False)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163 # NOTE: should probably check for unbalanced {} within the var
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500164 val = val.rstrip('\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500165 o.write("%s() {\n%s\n}\n" % (varExpanded, val))
166 return 1
167
168 if export:
169 o.write('export ')
170
171 # if we're going to output this within doublequotes,
172 # to a shell, we need to escape the quotes in the var
173 alter = re.sub('"', '\\"', val)
174 alter = re.sub('\n', ' \\\n', alter)
175 alter = re.sub('\\$', '\\\\$', alter)
176 o.write('%s="%s"\n' % (varExpanded, alter))
177 return False
178
179def emit_env(o=sys.__stdout__, d = init(), all=False):
180 """Emits all items in the data store in a format such that it can be sourced by a shell."""
181
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500182 isfunc = lambda key: bool(d.getVarFlag(key, "func", False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183 keys = sorted((key for key in d.keys() if not key.startswith("__")), key=isfunc)
184 grouped = groupby(keys, isfunc)
185 for isfunc, keys in grouped:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500186 for key in sorted(keys):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500187 emit_var(key, o, d, all and not isfunc) and o.write('\n')
188
189def exported_keys(d):
190 return (key for key in d.keys() if not key.startswith('__') and
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500191 d.getVarFlag(key, 'export', False) and
192 not d.getVarFlag(key, 'unexport', False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500193
194def exported_vars(d):
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500195 k = list(exported_keys(d))
196 for key in k:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197 try:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500198 value = d.getVar(key)
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500199 except Exception as err:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500200 bb.warn("%s: Unable to export ${%s}: %s" % (d.getVar("FILE"), key, err))
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500201 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202
203 if value is not None:
204 yield key, str(value)
205
206def emit_func(func, o=sys.__stdout__, d = init()):
207 """Emits all items in the data store in a format such that it can be sourced by a shell."""
208
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500209 keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func", False))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500210 for key in sorted(keys):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500211 emit_var(key, o, d, False)
212
213 o.write('\n')
214 emit_var(func, o, d, False) and o.write('\n')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500215 newdeps = bb.codeparser.ShellParser(func, logger).parse_shell(d.getVar(func))
216 newdeps |= set((d.getVarFlag(func, "vardeps") or "").split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500217 seen = set()
218 while newdeps:
219 deps = newdeps
220 seen |= deps
221 newdeps = set()
Patrick Williams93c203f2021-10-06 16:15:23 -0500222 for dep in sorted(deps):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500223 if d.getVarFlag(dep, "func", False) and not d.getVarFlag(dep, "python", False):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500224 emit_var(dep, o, d, False) and o.write('\n')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500225 newdeps |= bb.codeparser.ShellParser(dep, logger).parse_shell(d.getVar(dep))
226 newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500227 newdeps -= seen
228
229_functionfmt = """
230def {function}(d):
231{body}"""
232
233def emit_func_python(func, o=sys.__stdout__, d = init()):
234 """Emits all items in the data store in a format such that it can be sourced by a shell."""
235
236 def write_func(func, o, call = False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500237 body = d.getVar(func, False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500238 if not body.startswith("def"):
239 body = _functionfmt.format(function=func, body=body)
240
241 o.write(body.strip() + "\n\n")
242 if call:
243 o.write(func + "(d)" + "\n\n")
244
245 write_func(func, o, True)
246 pp = bb.codeparser.PythonParser(func, logger)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500247 pp.parse_python(d.getVar(func, False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 newdeps = pp.execs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500249 newdeps |= set((d.getVarFlag(func, "vardeps") or "").split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250 seen = set()
251 while newdeps:
252 deps = newdeps
253 seen |= deps
254 newdeps = set()
255 for dep in deps:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500256 if d.getVarFlag(dep, "func", False) and d.getVarFlag(dep, "python", False):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257 write_func(dep, o)
258 pp = bb.codeparser.PythonParser(dep, logger)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500259 pp.parse_python(d.getVar(dep, False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500260 newdeps |= pp.execs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500261 newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500262 newdeps -= seen
263
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600264def build_dependencies(key, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparsedata):
Andrew Geissler517393d2023-01-13 08:55:19 -0600265 def handle_contains(value, contains, exclusions, d):
266 newvalue = []
267 if value:
268 newvalue.append(str(value))
269 for k in sorted(contains):
270 if k in exclusions or k in ignored_vars:
271 continue
272 l = (d.getVar(k) or "").split()
273 for item in sorted(contains[k]):
274 for word in item.split():
275 if not word in l:
276 newvalue.append("\n%s{%s} = Unset" % (k, item))
277 break
278 else:
279 newvalue.append("\n%s{%s} = Set" % (k, item))
280 return "".join(newvalue)
281
282 def handle_remove(value, deps, removes, d):
283 for r in sorted(removes):
284 r2 = d.expandWithRefs(r, None)
285 value += "\n_remove of %s" % r
286 deps |= r2.references
287 deps = deps | (keys & r2.execs)
288 return value
289
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290 deps = set()
291 try:
Andrew Geissler517393d2023-01-13 08:55:19 -0600292 if key in mod_funcs:
293 exclusions = set()
294 moddep = bb.codeparser.modulecode_deps[key]
295 value = handle_contains("", moddep[3], exclusions, d)
296 return frozenset((moddep[0] | keys & moddep[1]) - ignored_vars), value
297
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298 if key[-1] == ']':
299 vf = key[:-1].split('[')
Andrew Geisslerd5838332022-05-27 11:33:10 -0500300 if vf[1] == "vardepvalueexclude":
301 return deps, ""
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800302 value, parser = d.getVarFlag(vf[0], vf[1], False, retparser=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303 deps |= parser.references
304 deps = deps | (keys & parser.execs)
Andrew Geissler517393d2023-01-13 08:55:19 -0600305 deps -= ignored_vars
306 return frozenset(deps), value
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600307 varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "exports", "postfuncs", "prefuncs", "lineno", "filename"]) or {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500308 vardeps = varflags.get("vardeps")
Patrick Williamsde0582f2022-04-08 10:23:27 -0500309 exclusions = varflags.get("vardepsexclude", "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500310
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500311 if "vardepvalue" in varflags:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800312 value = varflags.get("vardepvalue")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500313 elif varflags.get("func"):
314 if varflags.get("python"):
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600315 value = codeparsedata.getVarFlag(key, "_content", False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500316 parser = bb.codeparser.PythonParser(key, logger)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500317 parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500318 deps = deps | parser.references
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500319 deps = deps | (keys & parser.execs)
Patrick Williamsde0582f2022-04-08 10:23:27 -0500320 value = handle_contains(value, parser.contains, exclusions, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500321 else:
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600322 value, parsedvar = codeparsedata.getVarFlag(key, "_content", False, retparser=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500323 parser = bb.codeparser.ShellParser(key, logger)
324 parser.parse_shell(parsedvar.value)
325 deps = deps | shelldeps
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500326 deps = deps | parsedvar.references
327 deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
Patrick Williamsde0582f2022-04-08 10:23:27 -0500328 value = handle_contains(value, parsedvar.contains, exclusions, d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800329 if hasattr(parsedvar, "removes"):
330 value = handle_remove(value, deps, parsedvar.removes, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500331 if vardeps is None:
332 parser.log.flush()
333 if "prefuncs" in varflags:
334 deps = deps | set(varflags["prefuncs"].split())
335 if "postfuncs" in varflags:
336 deps = deps | set(varflags["postfuncs"].split())
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600337 if "exports" in varflags:
338 deps = deps | set(varflags["exports"].split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500339 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800340 value, parser = d.getVarFlag(key, "_content", False, retparser=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500341 deps |= parser.references
342 deps = deps | (keys & parser.execs)
Patrick Williamsde0582f2022-04-08 10:23:27 -0500343 value = handle_contains(value, parser.contains, exclusions, d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800344 if hasattr(parser, "removes"):
345 value = handle_remove(value, deps, parser.removes, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500346
347 if "vardepvalueexclude" in varflags:
348 exclude = varflags.get("vardepvalueexclude")
349 for excl in exclude.split('|'):
350 if excl:
351 value = value.replace(excl, '')
352
353 # Add varflags, assuming an exclusion list is set
354 if varflagsexcl:
355 varfdeps = []
356 for f in varflags:
357 if f not in varflagsexcl:
358 varfdeps.append('%s[%s]' % (key, f))
359 if varfdeps:
360 deps |= set(varfdeps)
361
362 deps |= set((vardeps or "").split())
Patrick Williamsde0582f2022-04-08 10:23:27 -0500363 deps -= set(exclusions)
Andrew Geissler517393d2023-01-13 08:55:19 -0600364 deps -= ignored_vars
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500365 except bb.parse.SkipRecipe:
366 raise
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500367 except Exception as e:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500368 bb.warn("Exception during build_dependencies for %s" % key)
369 raise
Andrew Geissler517393d2023-01-13 08:55:19 -0600370 return frozenset(deps), value
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 #bb.note("Variable %s references %s and calls %s" % (key, str(deps), str(execs)))
372 #d.setVarFlag(key, "vardeps", deps)
373
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000374def generate_dependencies(d, ignored_vars):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375
Andrew Geissler517393d2023-01-13 08:55:19 -0600376 mod_funcs = set(bb.codeparser.modulecode_deps.keys())
377 keys = set(key for key in d if not key.startswith("__")) | mod_funcs
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500378 shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500379 varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500380
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600381 codeparserd = d.createCopy()
382 for forced in (d.getVar('BB_HASH_CODEPARSER_VALS') or "").split():
383 key, value = forced.split("=", 1)
384 codeparserd.setVar(key, value)
385
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500386 deps = {}
387 values = {}
388
389 tasklist = d.getVar('__BBTASKS', False) or []
390 for task in tasklist:
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600391 deps[task], values[task] = build_dependencies(task, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparserd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500392 newdeps = deps[task]
393 seen = set()
394 while newdeps:
Andrew Geissler517393d2023-01-13 08:55:19 -0600395 nextdeps = newdeps
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500396 seen |= nextdeps
397 newdeps = set()
398 for dep in nextdeps:
399 if dep not in deps:
Andrew Geisslerc5535c92023-01-27 16:10:19 -0600400 deps[dep], values[dep] = build_dependencies(dep, keys, mod_funcs, shelldeps, varflagsexcl, ignored_vars, d, codeparserd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500401 newdeps |= deps[dep]
402 newdeps -= seen
403 #print "For %s: %s" % (task, str(deps[task]))
404 return tasklist, deps, values
405
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000406def generate_dependency_hash(tasklist, gendeps, lookupcache, ignored_vars, fn):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800407 taskdeps = {}
408 basehash = {}
409
410 for task in tasklist:
411 data = lookupcache[task]
412
413 if data is None:
414 bb.error("Task %s from %s seems to be empty?!" % (task, fn))
Andrew Geissler595f6302022-01-24 19:11:47 +0000415 data = []
416 else:
417 data = [data]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800418
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800419 newdeps = gendeps[task]
420 seen = set()
421 while newdeps:
422 nextdeps = newdeps
423 seen |= nextdeps
424 newdeps = set()
425 for dep in nextdeps:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800426 newdeps |= gendeps[dep]
427 newdeps -= seen
428
429 alldeps = sorted(seen)
430 for dep in alldeps:
Andrew Geissler595f6302022-01-24 19:11:47 +0000431 data.append(dep)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800432 var = lookupcache[dep]
433 if var is not None:
Andrew Geissler595f6302022-01-24 19:11:47 +0000434 data.append(str(var))
Brad Bishop08902b02019-08-20 09:16:51 -0400435 k = fn + ":" + task
Andrew Geissler595f6302022-01-24 19:11:47 +0000436 basehash[k] = hashlib.sha256("".join(data).encode("utf-8")).hexdigest()
Andrew Geissler517393d2023-01-13 08:55:19 -0600437 taskdeps[task] = frozenset(seen)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800438
439 return taskdeps, basehash
440
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500441def inherits_class(klass, d):
442 val = d.getVar('__inherit_cache', False) or []
Patrick Williams92b42cb2022-09-03 06:53:57 -0500443 needle = '/%s.bbclass' % klass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500444 for v in val:
445 if v.endswith(needle):
446 return True
447 return False