blob: 375ba3cb7941694b9deae5480281dcf7188026ee [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2 AbstractSyntaxTree classes for the Bitbake language
3"""
4
5# Copyright (C) 2003, 2004 Chris Larson
6# Copyright (C) 2003, 2004 Phil Blundell
7# Copyright (C) 2009 Holger Hans Peter Freyther
8#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
Patrick Williamsc0f7c042017-02-23 20:41:17 -060011
Andrew Geissler517393d2023-01-13 08:55:19 -060012import sys
Patrick Williamsc124f4f2015-09-15 14:41:29 -050013import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014from bb import methodpool
15from bb.parse import logger
16
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017class StatementGroup(list):
18 def eval(self, data):
19 for statement in self:
20 statement.eval(data)
21
22class AstNode(object):
23 def __init__(self, filename, lineno):
24 self.filename = filename
25 self.lineno = lineno
26
27class IncludeNode(AstNode):
28 def __init__(self, filename, lineno, what_file, force):
29 AstNode.__init__(self, filename, lineno)
30 self.what_file = what_file
31 self.force = force
32
33 def eval(self, data):
34 """
35 Include the file and evaluate the statements
36 """
37 s = data.expand(self.what_file)
Andrew Geisslerd1e89492021-02-12 15:35:20 -060038 logger.debug2("CONF %s:%s: including %s", self.filename, self.lineno, s)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039
40 # TODO: Cache those includes... maybe not here though
41 if self.force:
42 bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, "include required")
43 else:
44 bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, False)
45
46class ExportNode(AstNode):
47 def __init__(self, filename, lineno, var):
48 AstNode.__init__(self, filename, lineno)
49 self.var = var
50
51 def eval(self, data):
52 data.setVarFlag(self.var, "export", 1, op = 'exported')
53
Patrick Williamsc0f7c042017-02-23 20:41:17 -060054class UnsetNode(AstNode):
55 def __init__(self, filename, lineno, var):
56 AstNode.__init__(self, filename, lineno)
57 self.var = var
58
59 def eval(self, data):
60 loginfo = {
61 'variable': self.var,
62 'file': self.filename,
63 'line': self.lineno,
64 }
65 data.delVar(self.var,**loginfo)
66
67class UnsetFlagNode(AstNode):
68 def __init__(self, filename, lineno, var, flag):
69 AstNode.__init__(self, filename, lineno)
70 self.var = var
71 self.flag = flag
72
73 def eval(self, data):
74 loginfo = {
75 'variable': self.var,
76 'file': self.filename,
77 'line': self.lineno,
78 }
79 data.delVarFlag(self.var, self.flag, **loginfo)
80
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081class DataNode(AstNode):
82 """
83 Various data related updates. For the sake of sanity
84 we have one class doing all this. This means that all
85 this need to be re-evaluated... we might be able to do
86 that faster with multiple classes.
87 """
88 def __init__(self, filename, lineno, groupd):
89 AstNode.__init__(self, filename, lineno)
90 self.groupd = groupd
91
92 def getFunc(self, key, data):
Andrew Geissler82c905d2020-04-13 13:39:40 -050093 if 'flag' in self.groupd and self.groupd['flag'] is not None:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050094 return data.getVarFlag(key, self.groupd['flag'], expand=False, noweakdefault=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095 else:
96 return data.getVar(key, False, noweakdefault=True, parsing=True)
97
98 def eval(self, data):
99 groupd = self.groupd
100 key = groupd["var"]
101 loginfo = {
102 'variable': key,
103 'file': self.filename,
104 'line': self.lineno,
105 }
Andrew Geissler82c905d2020-04-13 13:39:40 -0500106 if "exp" in groupd and groupd["exp"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107 data.setVarFlag(key, "export", 1, op = 'exported', **loginfo)
108
109 op = "set"
Andrew Geissler82c905d2020-04-13 13:39:40 -0500110 if "ques" in groupd and groupd["ques"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500111 val = self.getFunc(key, data)
112 op = "set?"
Andrew Geissler82c905d2020-04-13 13:39:40 -0500113 if val is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500114 val = groupd["value"]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500115 elif "colon" in groupd and groupd["colon"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116 e = data.createCopy()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500117 op = "immediate"
118 val = e.expand(groupd["value"], key + "[:=]")
Andrew Geissler82c905d2020-04-13 13:39:40 -0500119 elif "append" in groupd and groupd["append"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500120 op = "append"
121 val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500122 elif "prepend" in groupd and groupd["prepend"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500123 op = "prepend"
124 val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or ""))
Andrew Geissler82c905d2020-04-13 13:39:40 -0500125 elif "postdot" in groupd and groupd["postdot"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500126 op = "postdot"
127 val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500128 elif "predot" in groupd and groupd["predot"] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 op = "predot"
130 val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or ""))
131 else:
132 val = groupd["value"]
133
Andrew Geissler595f6302022-01-24 19:11:47 +0000134 if ":append" in key or ":remove" in key or ":prepend" in key:
135 if op in ["append", "prepend", "postdot", "predot", "ques"]:
136 bb.warn(key + " " + groupd[op] + " is not a recommended operator combination, please replace it.")
137
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500138 flag = None
Andrew Geissler82c905d2020-04-13 13:39:40 -0500139 if 'flag' in groupd and groupd['flag'] is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500140 flag = groupd['flag']
141 elif groupd["lazyques"]:
142 flag = "_defaultval"
143
144 loginfo['op'] = op
145 loginfo['detail'] = groupd["value"]
146
147 if flag:
148 data.setVarFlag(key, flag, val, **loginfo)
149 else:
150 data.setVar(key, val, parsing=True, **loginfo)
151
152class MethodNode(AstNode):
Patrick Williams213cb262021-08-07 19:21:33 -0500153 tr_tbl = str.maketrans('/.+-@%&~', '________')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500154
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500155 def __init__(self, filename, lineno, func_name, body, python, fakeroot):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156 AstNode.__init__(self, filename, lineno)
157 self.func_name = func_name
158 self.body = body
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500159 self.python = python
160 self.fakeroot = fakeroot
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500161
162 def eval(self, data):
163 text = '\n'.join(self.body)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500164 funcname = self.func_name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500165 if self.func_name == "__anonymous":
166 funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(MethodNode.tr_tbl)))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500167 self.python = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500168 text = "def %s(d):\n" % (funcname) + text
Brad Bishop19323692019-04-05 15:28:33 -0400169 bb.methodpool.insert_method(funcname, text, self.filename, self.lineno - len(self.body) - 1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500170 anonfuncs = data.getVar('__BBANONFUNCS', False) or []
171 anonfuncs.append(funcname)
172 data.setVar('__BBANONFUNCS', anonfuncs)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500173 if data.getVar(funcname, False):
174 # clean up old version of this piece of metadata, as its
175 # flags could cause problems
176 data.delVarFlag(funcname, 'python')
177 data.delVarFlag(funcname, 'fakeroot')
178 if self.python:
179 data.setVarFlag(funcname, "python", "1")
180 if self.fakeroot:
181 data.setVarFlag(funcname, "fakeroot", "1")
182 data.setVarFlag(funcname, "func", 1)
183 data.setVar(funcname, text, parsing=True)
184 data.setVarFlag(funcname, 'filename', self.filename)
185 data.setVarFlag(funcname, 'lineno', str(self.lineno - len(self.body)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186
187class PythonMethodNode(AstNode):
188 def __init__(self, filename, lineno, function, modulename, body):
189 AstNode.__init__(self, filename, lineno)
190 self.function = function
191 self.modulename = modulename
192 self.body = body
193
194 def eval(self, data):
195 # Note we will add root to parsedmethods after having parse
196 # 'this' file. This means we will not parse methods from
197 # bb classes twice
198 text = '\n'.join(self.body)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500199 bb.methodpool.insert_method(self.modulename, text, self.filename, self.lineno - len(self.body) - 1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 data.setVarFlag(self.function, "func", 1)
201 data.setVarFlag(self.function, "python", 1)
202 data.setVar(self.function, text, parsing=True)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500203 data.setVarFlag(self.function, 'filename', self.filename)
204 data.setVarFlag(self.function, 'lineno', str(self.lineno - len(self.body) - 1))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500205
206class ExportFuncsNode(AstNode):
207 def __init__(self, filename, lineno, fns, classname):
208 AstNode.__init__(self, filename, lineno)
209 self.n = fns.split()
210 self.classname = classname
211
212 def eval(self, data):
213
214 for func in self.n:
215 calledfunc = self.classname + "_" + func
216
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500217 if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500218 continue
219
220 if data.getVar(func, False):
221 data.setVarFlag(func, 'python', None)
222 data.setVarFlag(func, 'func', None)
223
224 for flag in [ "func", "python" ]:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500225 if data.getVarFlag(calledfunc, flag, False):
226 data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False))
Patrick Williams03907ee2022-05-01 06:28:52 -0500227 for flag in ["dirs", "cleandirs", "fakeroot"]:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500228 if data.getVarFlag(func, flag, False):
229 data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False))
230 data.setVarFlag(func, "filename", "autogenerated")
231 data.setVarFlag(func, "lineno", 1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500232
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500233 if data.getVarFlag(calledfunc, "python", False):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500234 data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True)
235 else:
236 if "-" in self.classname:
237 bb.fatal("The classname %s contains a dash character and is calling an sh function %s using EXPORT_FUNCTIONS. Since a dash is illegal in sh function names, this cannot work, please rename the class or don't use EXPORT_FUNCTIONS." % (self.classname, calledfunc))
238 data.setVar(func, " " + calledfunc + "\n", parsing=True)
239 data.setVarFlag(func, 'export_func', '1')
240
241class AddTaskNode(AstNode):
242 def __init__(self, filename, lineno, func, before, after):
243 AstNode.__init__(self, filename, lineno)
244 self.func = func
245 self.before = before
246 self.after = after
247
248 def eval(self, data):
249 bb.build.addtask(self.func, self.before, self.after, data)
250
251class DelTaskNode(AstNode):
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500252 def __init__(self, filename, lineno, tasks):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500253 AstNode.__init__(self, filename, lineno)
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500254 self.tasks = tasks
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500255
256 def eval(self, data):
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500257 tasks = data.expand(self.tasks).split()
258 for task in tasks:
259 bb.build.deltask(task, data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500260
261class BBHandlerNode(AstNode):
262 def __init__(self, filename, lineno, fns):
263 AstNode.__init__(self, filename, lineno)
264 self.hs = fns.split()
265
266 def eval(self, data):
267 bbhands = data.getVar('__BBHANDLERS', False) or []
268 for h in self.hs:
269 bbhands.append(h)
270 data.setVarFlag(h, "handler", 1)
271 data.setVar('__BBHANDLERS', bbhands)
272
Andrew Geissler517393d2023-01-13 08:55:19 -0600273class PyLibNode(AstNode):
274 def __init__(self, filename, lineno, libdir, namespace):
275 AstNode.__init__(self, filename, lineno)
276 self.libdir = libdir
277 self.namespace = namespace
278
279 def eval(self, data):
280 global_mods = (data.getVar("BB_GLOBAL_PYMODULES") or "").split()
281 for m in global_mods:
282 if m not in bb.utils._context:
283 bb.utils._context[m] = __import__(m)
284
285 libdir = data.expand(self.libdir)
286 if libdir not in sys.path:
287 sys.path.append(libdir)
288 try:
289 bb.utils._context[self.namespace] = __import__(self.namespace)
290 toimport = getattr(bb.utils._context[self.namespace], "BBIMPORTS", [])
291 for i in toimport:
292 bb.utils._context[self.namespace] = __import__(self.namespace + "." + i)
293 mod = getattr(bb.utils._context[self.namespace], i)
294 fn = getattr(mod, "__file__")
295 funcs = {}
296 for f in dir(mod):
297 if f.startswith("_"):
298 continue
299 fcall = getattr(mod, f)
300 if not callable(fcall):
301 continue
302 funcs[f] = fcall
303 bb.codeparser.add_module_functions(fn, funcs, "%s.%s" % (self.namespace, i))
304
305 except AttributeError as e:
306 bb.error("Error importing OE modules: %s" % str(e))
307
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500308class InheritNode(AstNode):
309 def __init__(self, filename, lineno, classes):
310 AstNode.__init__(self, filename, lineno)
311 self.classes = classes
312
313 def eval(self, data):
314 bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data)
315
316def handleInclude(statements, filename, lineno, m, force):
317 statements.append(IncludeNode(filename, lineno, m.group(1), force))
318
319def handleExport(statements, filename, lineno, m):
320 statements.append(ExportNode(filename, lineno, m.group(1)))
321
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600322def handleUnset(statements, filename, lineno, m):
323 statements.append(UnsetNode(filename, lineno, m.group(1)))
324
325def handleUnsetFlag(statements, filename, lineno, m):
326 statements.append(UnsetFlagNode(filename, lineno, m.group(1), m.group(2)))
327
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500328def handleData(statements, filename, lineno, groupd):
329 statements.append(DataNode(filename, lineno, groupd))
330
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500331def handleMethod(statements, filename, lineno, func_name, body, python, fakeroot):
332 statements.append(MethodNode(filename, lineno, func_name, body, python, fakeroot))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500333
334def handlePythonMethod(statements, filename, lineno, funcname, modulename, body):
335 statements.append(PythonMethodNode(filename, lineno, funcname, modulename, body))
336
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500337def handleExportFuncs(statements, filename, lineno, m, classname):
338 statements.append(ExportFuncsNode(filename, lineno, m.group(1), classname))
339
340def handleAddTask(statements, filename, lineno, m):
341 func = m.group("func")
342 before = m.group("before")
343 after = m.group("after")
344 if func is None:
345 return
346
347 statements.append(AddTaskNode(filename, lineno, func, before, after))
348
349def handleDelTask(statements, filename, lineno, m):
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500350 func = m.group(1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351 if func is None:
352 return
353
354 statements.append(DelTaskNode(filename, lineno, func))
355
356def handleBBHandlers(statements, filename, lineno, m):
357 statements.append(BBHandlerNode(filename, lineno, m.group(1)))
358
Andrew Geissler517393d2023-01-13 08:55:19 -0600359def handlePyLib(statements, filename, lineno, m):
360 statements.append(PyLibNode(filename, lineno, m.group(1), m.group(2)))
361
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500362def handleInherit(statements, filename, lineno, m):
363 classes = m.group(1)
364 statements.append(InheritNode(filename, lineno, classes))
365
Brad Bishop316dfdd2018-06-25 12:45:53 -0400366def runAnonFuncs(d):
367 code = []
368 for funcname in d.getVar("__BBANONFUNCS", False) or []:
369 code.append("%s(d)" % funcname)
370 bb.utils.better_exec("\n".join(code), {"d": d})
371
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500372def finalize(fn, d, variant = None):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600373 saved_handlers = bb.event.get_handlers().copy()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800374 try:
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000375 # Found renamed variables. Exit immediately
376 if d.getVar("_FAILPARSINGERRORHANDLED", False) == True:
377 raise bb.BBHandledException()
378
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800379 for var in d.getVar('__BBHANDLERS', False) or []:
380 # try to add the handler
381 handlerfn = d.getVarFlag(var, "filename", False)
382 if not handlerfn:
383 bb.fatal("Undefined event handler function '%s'" % var)
384 handlerln = int(d.getVarFlag(var, "lineno", False))
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600385 bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data=d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600386
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800387 bb.event.fire(bb.event.RecipePreFinalise(fn), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500388
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800389 bb.data.expandKeys(d)
Andrew Geissler1e34c2d2020-05-29 16:02:59 -0500390
391 bb.event.fire(bb.event.RecipePostKeyExpansion(fn), d)
392
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800393 runAnonFuncs(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500394
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800395 tasklist = d.getVar('__BBTASKS', False) or []
396 bb.event.fire(bb.event.RecipeTaskPreProcess(fn, list(tasklist)), d)
397 bb.build.add_tasks(tasklist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500398
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800399 bb.parse.siggen.finalise(fn, d, variant)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500400
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800401 d.setVar('BBINCLUDED', bb.parse.get_file_depends(d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500402
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800403 bb.event.fire(bb.event.RecipeParsed(fn), d)
404 finally:
405 bb.event.set_handlers(saved_handlers)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406
407def _create_variants(datastores, names, function, onlyfinalise):
408 def create_variant(name, orig_d, arg = None):
409 if onlyfinalise and name not in onlyfinalise:
410 return
411 new_d = bb.data.createCopy(orig_d)
412 function(arg or name, new_d)
413 datastores[name] = new_d
414
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600415 for variant in list(datastores.keys()):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500416 for name in names:
417 if not variant:
418 # Based on main recipe
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600419 create_variant(name, datastores[""])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600421 create_variant("%s-%s" % (variant, name), datastores[variant], name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500422
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500423def multi_finalize(fn, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500424 appends = (d.getVar("__BBAPPEND") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500425 for append in appends:
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600426 logger.debug("Appending .bbappend file %s to %s", append, fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500427 bb.parse.BBHandler.handle(append, d, True)
428
429 onlyfinalise = d.getVar("__ONLYFINALISE", False)
430
431 safe_d = d
432 d = bb.data.createCopy(safe_d)
433 try:
434 finalize(fn, d)
435 except bb.parse.SkipRecipe as e:
436 d.setVar("__SKIPPED", e.args[0])
437 datastores = {"": safe_d}
438
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500439 extended = d.getVar("BBCLASSEXTEND") or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500440 if extended:
441 # the following is to support bbextends with arguments, for e.g. multilib
442 # an example is as follows:
443 # BBCLASSEXTEND = "multilib:lib32"
444 # it will create foo-lib32, inheriting multilib.bbclass and set
445 # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32"
446 extendedmap = {}
447 variantmap = {}
448
449 for ext in extended.split():
450 eext = ext.split(':', 2)
451 if len(eext) > 1:
452 extendedmap[ext] = eext[0]
453 variantmap[ext] = eext[1]
454 else:
455 extendedmap[ext] = ext
456
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500457 pn = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500458 def extendfunc(name, d):
459 if name != extendedmap[name]:
460 d.setVar("BBEXTENDCURR", extendedmap[name])
461 d.setVar("BBEXTENDVARIANT", variantmap[name])
462 else:
463 d.setVar("PN", "%s-%s" % (pn, name))
464 bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d)
465
466 safe_d.setVar("BBCLASSEXTEND", extended)
467 _create_variants(datastores, extendedmap.keys(), extendfunc, onlyfinalise)
468
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600469 for variant in datastores.keys():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500470 if variant:
471 try:
472 if not onlyfinalise or variant in onlyfinalise:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600473 finalize(fn, datastores[variant], variant)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500474 except bb.parse.SkipRecipe as e:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600475 datastores[variant].setVar("__SKIPPED", e.args[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500476
477 datastores[""] = d
478 return datastores