1*4882a593Smuzhiyun""" 2*4882a593Smuzhiyun AbstractSyntaxTree classes for the Bitbake language 3*4882a593Smuzhiyun""" 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Chris Larson 6*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Phil Blundell 7*4882a593Smuzhiyun# Copyright (C) 2009 Holger Hans Peter Freyther 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 10*4882a593Smuzhiyun# 11*4882a593Smuzhiyun 12*4882a593Smuzhiyunimport bb 13*4882a593Smuzhiyunfrom bb import methodpool 14*4882a593Smuzhiyunfrom bb.parse import logger 15*4882a593Smuzhiyun 16*4882a593Smuzhiyunclass StatementGroup(list): 17*4882a593Smuzhiyun def eval(self, data): 18*4882a593Smuzhiyun for statement in self: 19*4882a593Smuzhiyun statement.eval(data) 20*4882a593Smuzhiyun 21*4882a593Smuzhiyunclass AstNode(object): 22*4882a593Smuzhiyun def __init__(self, filename, lineno): 23*4882a593Smuzhiyun self.filename = filename 24*4882a593Smuzhiyun self.lineno = lineno 25*4882a593Smuzhiyun 26*4882a593Smuzhiyunclass IncludeNode(AstNode): 27*4882a593Smuzhiyun def __init__(self, filename, lineno, what_file, force): 28*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 29*4882a593Smuzhiyun self.what_file = what_file 30*4882a593Smuzhiyun self.force = force 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun def eval(self, data): 33*4882a593Smuzhiyun """ 34*4882a593Smuzhiyun Include the file and evaluate the statements 35*4882a593Smuzhiyun """ 36*4882a593Smuzhiyun s = data.expand(self.what_file) 37*4882a593Smuzhiyun logger.debug2("CONF %s:%s: including %s", self.filename, self.lineno, s) 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun # TODO: Cache those includes... maybe not here though 40*4882a593Smuzhiyun if self.force: 41*4882a593Smuzhiyun bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, "include required") 42*4882a593Smuzhiyun else: 43*4882a593Smuzhiyun bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, False) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyunclass ExportNode(AstNode): 46*4882a593Smuzhiyun def __init__(self, filename, lineno, var): 47*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 48*4882a593Smuzhiyun self.var = var 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun def eval(self, data): 51*4882a593Smuzhiyun data.setVarFlag(self.var, "export", 1, op = 'exported') 52*4882a593Smuzhiyun 53*4882a593Smuzhiyunclass UnsetNode(AstNode): 54*4882a593Smuzhiyun def __init__(self, filename, lineno, var): 55*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 56*4882a593Smuzhiyun self.var = var 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun def eval(self, data): 59*4882a593Smuzhiyun loginfo = { 60*4882a593Smuzhiyun 'variable': self.var, 61*4882a593Smuzhiyun 'file': self.filename, 62*4882a593Smuzhiyun 'line': self.lineno, 63*4882a593Smuzhiyun } 64*4882a593Smuzhiyun data.delVar(self.var,**loginfo) 65*4882a593Smuzhiyun 66*4882a593Smuzhiyunclass UnsetFlagNode(AstNode): 67*4882a593Smuzhiyun def __init__(self, filename, lineno, var, flag): 68*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 69*4882a593Smuzhiyun self.var = var 70*4882a593Smuzhiyun self.flag = flag 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun def eval(self, data): 73*4882a593Smuzhiyun loginfo = { 74*4882a593Smuzhiyun 'variable': self.var, 75*4882a593Smuzhiyun 'file': self.filename, 76*4882a593Smuzhiyun 'line': self.lineno, 77*4882a593Smuzhiyun } 78*4882a593Smuzhiyun data.delVarFlag(self.var, self.flag, **loginfo) 79*4882a593Smuzhiyun 80*4882a593Smuzhiyunclass DataNode(AstNode): 81*4882a593Smuzhiyun """ 82*4882a593Smuzhiyun Various data related updates. For the sake of sanity 83*4882a593Smuzhiyun we have one class doing all this. This means that all 84*4882a593Smuzhiyun this need to be re-evaluated... we might be able to do 85*4882a593Smuzhiyun that faster with multiple classes. 86*4882a593Smuzhiyun """ 87*4882a593Smuzhiyun def __init__(self, filename, lineno, groupd): 88*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 89*4882a593Smuzhiyun self.groupd = groupd 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun def getFunc(self, key, data): 92*4882a593Smuzhiyun if 'flag' in self.groupd and self.groupd['flag'] is not None: 93*4882a593Smuzhiyun return data.getVarFlag(key, self.groupd['flag'], expand=False, noweakdefault=True) 94*4882a593Smuzhiyun else: 95*4882a593Smuzhiyun return data.getVar(key, False, noweakdefault=True, parsing=True) 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun def eval(self, data): 98*4882a593Smuzhiyun groupd = self.groupd 99*4882a593Smuzhiyun key = groupd["var"] 100*4882a593Smuzhiyun loginfo = { 101*4882a593Smuzhiyun 'variable': key, 102*4882a593Smuzhiyun 'file': self.filename, 103*4882a593Smuzhiyun 'line': self.lineno, 104*4882a593Smuzhiyun } 105*4882a593Smuzhiyun if "exp" in groupd and groupd["exp"] is not None: 106*4882a593Smuzhiyun data.setVarFlag(key, "export", 1, op = 'exported', **loginfo) 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun op = "set" 109*4882a593Smuzhiyun if "ques" in groupd and groupd["ques"] is not None: 110*4882a593Smuzhiyun val = self.getFunc(key, data) 111*4882a593Smuzhiyun op = "set?" 112*4882a593Smuzhiyun if val is None: 113*4882a593Smuzhiyun val = groupd["value"] 114*4882a593Smuzhiyun elif "colon" in groupd and groupd["colon"] is not None: 115*4882a593Smuzhiyun e = data.createCopy() 116*4882a593Smuzhiyun op = "immediate" 117*4882a593Smuzhiyun val = e.expand(groupd["value"], key + "[:=]") 118*4882a593Smuzhiyun elif "append" in groupd and groupd["append"] is not None: 119*4882a593Smuzhiyun op = "append" 120*4882a593Smuzhiyun val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"]) 121*4882a593Smuzhiyun elif "prepend" in groupd and groupd["prepend"] is not None: 122*4882a593Smuzhiyun op = "prepend" 123*4882a593Smuzhiyun val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or "")) 124*4882a593Smuzhiyun elif "postdot" in groupd and groupd["postdot"] is not None: 125*4882a593Smuzhiyun op = "postdot" 126*4882a593Smuzhiyun val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"]) 127*4882a593Smuzhiyun elif "predot" in groupd and groupd["predot"] is not None: 128*4882a593Smuzhiyun op = "predot" 129*4882a593Smuzhiyun val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or "")) 130*4882a593Smuzhiyun else: 131*4882a593Smuzhiyun val = groupd["value"] 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun if ":append" in key or ":remove" in key or ":prepend" in key: 134*4882a593Smuzhiyun if op in ["append", "prepend", "postdot", "predot", "ques"]: 135*4882a593Smuzhiyun bb.warn(key + " " + groupd[op] + " is not a recommended operator combination, please replace it.") 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun flag = None 138*4882a593Smuzhiyun if 'flag' in groupd and groupd['flag'] is not None: 139*4882a593Smuzhiyun flag = groupd['flag'] 140*4882a593Smuzhiyun elif groupd["lazyques"]: 141*4882a593Smuzhiyun flag = "_defaultval" 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun loginfo['op'] = op 144*4882a593Smuzhiyun loginfo['detail'] = groupd["value"] 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun if flag: 147*4882a593Smuzhiyun data.setVarFlag(key, flag, val, **loginfo) 148*4882a593Smuzhiyun else: 149*4882a593Smuzhiyun data.setVar(key, val, parsing=True, **loginfo) 150*4882a593Smuzhiyun 151*4882a593Smuzhiyunclass MethodNode(AstNode): 152*4882a593Smuzhiyun tr_tbl = str.maketrans('/.+-@%&~', '________') 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun def __init__(self, filename, lineno, func_name, body, python, fakeroot): 155*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 156*4882a593Smuzhiyun self.func_name = func_name 157*4882a593Smuzhiyun self.body = body 158*4882a593Smuzhiyun self.python = python 159*4882a593Smuzhiyun self.fakeroot = fakeroot 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun def eval(self, data): 162*4882a593Smuzhiyun text = '\n'.join(self.body) 163*4882a593Smuzhiyun funcname = self.func_name 164*4882a593Smuzhiyun if self.func_name == "__anonymous": 165*4882a593Smuzhiyun funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(MethodNode.tr_tbl))) 166*4882a593Smuzhiyun self.python = True 167*4882a593Smuzhiyun text = "def %s(d):\n" % (funcname) + text 168*4882a593Smuzhiyun bb.methodpool.insert_method(funcname, text, self.filename, self.lineno - len(self.body) - 1) 169*4882a593Smuzhiyun anonfuncs = data.getVar('__BBANONFUNCS', False) or [] 170*4882a593Smuzhiyun anonfuncs.append(funcname) 171*4882a593Smuzhiyun data.setVar('__BBANONFUNCS', anonfuncs) 172*4882a593Smuzhiyun if data.getVar(funcname, False): 173*4882a593Smuzhiyun # clean up old version of this piece of metadata, as its 174*4882a593Smuzhiyun # flags could cause problems 175*4882a593Smuzhiyun data.delVarFlag(funcname, 'python') 176*4882a593Smuzhiyun data.delVarFlag(funcname, 'fakeroot') 177*4882a593Smuzhiyun if self.python: 178*4882a593Smuzhiyun data.setVarFlag(funcname, "python", "1") 179*4882a593Smuzhiyun if self.fakeroot: 180*4882a593Smuzhiyun data.setVarFlag(funcname, "fakeroot", "1") 181*4882a593Smuzhiyun data.setVarFlag(funcname, "func", 1) 182*4882a593Smuzhiyun data.setVar(funcname, text, parsing=True) 183*4882a593Smuzhiyun data.setVarFlag(funcname, 'filename', self.filename) 184*4882a593Smuzhiyun data.setVarFlag(funcname, 'lineno', str(self.lineno - len(self.body))) 185*4882a593Smuzhiyun 186*4882a593Smuzhiyunclass PythonMethodNode(AstNode): 187*4882a593Smuzhiyun def __init__(self, filename, lineno, function, modulename, body): 188*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 189*4882a593Smuzhiyun self.function = function 190*4882a593Smuzhiyun self.modulename = modulename 191*4882a593Smuzhiyun self.body = body 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun def eval(self, data): 194*4882a593Smuzhiyun # Note we will add root to parsedmethods after having parse 195*4882a593Smuzhiyun # 'this' file. This means we will not parse methods from 196*4882a593Smuzhiyun # bb classes twice 197*4882a593Smuzhiyun text = '\n'.join(self.body) 198*4882a593Smuzhiyun bb.methodpool.insert_method(self.modulename, text, self.filename, self.lineno - len(self.body) - 1) 199*4882a593Smuzhiyun data.setVarFlag(self.function, "func", 1) 200*4882a593Smuzhiyun data.setVarFlag(self.function, "python", 1) 201*4882a593Smuzhiyun data.setVar(self.function, text, parsing=True) 202*4882a593Smuzhiyun data.setVarFlag(self.function, 'filename', self.filename) 203*4882a593Smuzhiyun data.setVarFlag(self.function, 'lineno', str(self.lineno - len(self.body) - 1)) 204*4882a593Smuzhiyun 205*4882a593Smuzhiyunclass ExportFuncsNode(AstNode): 206*4882a593Smuzhiyun def __init__(self, filename, lineno, fns, classname): 207*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 208*4882a593Smuzhiyun self.n = fns.split() 209*4882a593Smuzhiyun self.classname = classname 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun def eval(self, data): 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun for func in self.n: 214*4882a593Smuzhiyun calledfunc = self.classname + "_" + func 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False): 217*4882a593Smuzhiyun continue 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun if data.getVar(func, False): 220*4882a593Smuzhiyun data.setVarFlag(func, 'python', None) 221*4882a593Smuzhiyun data.setVarFlag(func, 'func', None) 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun for flag in [ "func", "python" ]: 224*4882a593Smuzhiyun if data.getVarFlag(calledfunc, flag, False): 225*4882a593Smuzhiyun data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False)) 226*4882a593Smuzhiyun for flag in ["dirs", "cleandirs", "fakeroot"]: 227*4882a593Smuzhiyun if data.getVarFlag(func, flag, False): 228*4882a593Smuzhiyun data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False)) 229*4882a593Smuzhiyun data.setVarFlag(func, "filename", "autogenerated") 230*4882a593Smuzhiyun data.setVarFlag(func, "lineno", 1) 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun if data.getVarFlag(calledfunc, "python", False): 233*4882a593Smuzhiyun data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) 234*4882a593Smuzhiyun else: 235*4882a593Smuzhiyun if "-" in self.classname: 236*4882a593Smuzhiyun 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)) 237*4882a593Smuzhiyun data.setVar(func, " " + calledfunc + "\n", parsing=True) 238*4882a593Smuzhiyun data.setVarFlag(func, 'export_func', '1') 239*4882a593Smuzhiyun 240*4882a593Smuzhiyunclass AddTaskNode(AstNode): 241*4882a593Smuzhiyun def __init__(self, filename, lineno, func, before, after): 242*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 243*4882a593Smuzhiyun self.func = func 244*4882a593Smuzhiyun self.before = before 245*4882a593Smuzhiyun self.after = after 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun def eval(self, data): 248*4882a593Smuzhiyun bb.build.addtask(self.func, self.before, self.after, data) 249*4882a593Smuzhiyun 250*4882a593Smuzhiyunclass DelTaskNode(AstNode): 251*4882a593Smuzhiyun def __init__(self, filename, lineno, tasks): 252*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 253*4882a593Smuzhiyun self.tasks = tasks 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun def eval(self, data): 256*4882a593Smuzhiyun tasks = data.expand(self.tasks).split() 257*4882a593Smuzhiyun for task in tasks: 258*4882a593Smuzhiyun bb.build.deltask(task, data) 259*4882a593Smuzhiyun 260*4882a593Smuzhiyunclass BBHandlerNode(AstNode): 261*4882a593Smuzhiyun def __init__(self, filename, lineno, fns): 262*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 263*4882a593Smuzhiyun self.hs = fns.split() 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun def eval(self, data): 266*4882a593Smuzhiyun bbhands = data.getVar('__BBHANDLERS', False) or [] 267*4882a593Smuzhiyun for h in self.hs: 268*4882a593Smuzhiyun bbhands.append(h) 269*4882a593Smuzhiyun data.setVarFlag(h, "handler", 1) 270*4882a593Smuzhiyun data.setVar('__BBHANDLERS', bbhands) 271*4882a593Smuzhiyun 272*4882a593Smuzhiyunclass InheritNode(AstNode): 273*4882a593Smuzhiyun def __init__(self, filename, lineno, classes): 274*4882a593Smuzhiyun AstNode.__init__(self, filename, lineno) 275*4882a593Smuzhiyun self.classes = classes 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun def eval(self, data): 278*4882a593Smuzhiyun bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data) 279*4882a593Smuzhiyun 280*4882a593Smuzhiyundef handleInclude(statements, filename, lineno, m, force): 281*4882a593Smuzhiyun statements.append(IncludeNode(filename, lineno, m.group(1), force)) 282*4882a593Smuzhiyun 283*4882a593Smuzhiyundef handleExport(statements, filename, lineno, m): 284*4882a593Smuzhiyun statements.append(ExportNode(filename, lineno, m.group(1))) 285*4882a593Smuzhiyun 286*4882a593Smuzhiyundef handleUnset(statements, filename, lineno, m): 287*4882a593Smuzhiyun statements.append(UnsetNode(filename, lineno, m.group(1))) 288*4882a593Smuzhiyun 289*4882a593Smuzhiyundef handleUnsetFlag(statements, filename, lineno, m): 290*4882a593Smuzhiyun statements.append(UnsetFlagNode(filename, lineno, m.group(1), m.group(2))) 291*4882a593Smuzhiyun 292*4882a593Smuzhiyundef handleData(statements, filename, lineno, groupd): 293*4882a593Smuzhiyun statements.append(DataNode(filename, lineno, groupd)) 294*4882a593Smuzhiyun 295*4882a593Smuzhiyundef handleMethod(statements, filename, lineno, func_name, body, python, fakeroot): 296*4882a593Smuzhiyun statements.append(MethodNode(filename, lineno, func_name, body, python, fakeroot)) 297*4882a593Smuzhiyun 298*4882a593Smuzhiyundef handlePythonMethod(statements, filename, lineno, funcname, modulename, body): 299*4882a593Smuzhiyun statements.append(PythonMethodNode(filename, lineno, funcname, modulename, body)) 300*4882a593Smuzhiyun 301*4882a593Smuzhiyundef handleExportFuncs(statements, filename, lineno, m, classname): 302*4882a593Smuzhiyun statements.append(ExportFuncsNode(filename, lineno, m.group(1), classname)) 303*4882a593Smuzhiyun 304*4882a593Smuzhiyundef handleAddTask(statements, filename, lineno, m): 305*4882a593Smuzhiyun func = m.group("func") 306*4882a593Smuzhiyun before = m.group("before") 307*4882a593Smuzhiyun after = m.group("after") 308*4882a593Smuzhiyun if func is None: 309*4882a593Smuzhiyun return 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun statements.append(AddTaskNode(filename, lineno, func, before, after)) 312*4882a593Smuzhiyun 313*4882a593Smuzhiyundef handleDelTask(statements, filename, lineno, m): 314*4882a593Smuzhiyun func = m.group(1) 315*4882a593Smuzhiyun if func is None: 316*4882a593Smuzhiyun return 317*4882a593Smuzhiyun 318*4882a593Smuzhiyun statements.append(DelTaskNode(filename, lineno, func)) 319*4882a593Smuzhiyun 320*4882a593Smuzhiyundef handleBBHandlers(statements, filename, lineno, m): 321*4882a593Smuzhiyun statements.append(BBHandlerNode(filename, lineno, m.group(1))) 322*4882a593Smuzhiyun 323*4882a593Smuzhiyundef handleInherit(statements, filename, lineno, m): 324*4882a593Smuzhiyun classes = m.group(1) 325*4882a593Smuzhiyun statements.append(InheritNode(filename, lineno, classes)) 326*4882a593Smuzhiyun 327*4882a593Smuzhiyundef runAnonFuncs(d): 328*4882a593Smuzhiyun code = [] 329*4882a593Smuzhiyun for funcname in d.getVar("__BBANONFUNCS", False) or []: 330*4882a593Smuzhiyun code.append("%s(d)" % funcname) 331*4882a593Smuzhiyun bb.utils.better_exec("\n".join(code), {"d": d}) 332*4882a593Smuzhiyun 333*4882a593Smuzhiyundef finalize(fn, d, variant = None): 334*4882a593Smuzhiyun saved_handlers = bb.event.get_handlers().copy() 335*4882a593Smuzhiyun try: 336*4882a593Smuzhiyun # Found renamed variables. Exit immediately 337*4882a593Smuzhiyun if d.getVar("_FAILPARSINGERRORHANDLED", False) == True: 338*4882a593Smuzhiyun raise bb.BBHandledException() 339*4882a593Smuzhiyun 340*4882a593Smuzhiyun for var in d.getVar('__BBHANDLERS', False) or []: 341*4882a593Smuzhiyun # try to add the handler 342*4882a593Smuzhiyun handlerfn = d.getVarFlag(var, "filename", False) 343*4882a593Smuzhiyun if not handlerfn: 344*4882a593Smuzhiyun bb.fatal("Undefined event handler function '%s'" % var) 345*4882a593Smuzhiyun handlerln = int(d.getVarFlag(var, "lineno", False)) 346*4882a593Smuzhiyun bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data=d) 347*4882a593Smuzhiyun 348*4882a593Smuzhiyun bb.event.fire(bb.event.RecipePreFinalise(fn), d) 349*4882a593Smuzhiyun 350*4882a593Smuzhiyun bb.data.expandKeys(d) 351*4882a593Smuzhiyun 352*4882a593Smuzhiyun bb.event.fire(bb.event.RecipePostKeyExpansion(fn), d) 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun runAnonFuncs(d) 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun tasklist = d.getVar('__BBTASKS', False) or [] 357*4882a593Smuzhiyun bb.event.fire(bb.event.RecipeTaskPreProcess(fn, list(tasklist)), d) 358*4882a593Smuzhiyun bb.build.add_tasks(tasklist, d) 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun bb.parse.siggen.finalise(fn, d, variant) 361*4882a593Smuzhiyun 362*4882a593Smuzhiyun d.setVar('BBINCLUDED', bb.parse.get_file_depends(d)) 363*4882a593Smuzhiyun 364*4882a593Smuzhiyun bb.event.fire(bb.event.RecipeParsed(fn), d) 365*4882a593Smuzhiyun finally: 366*4882a593Smuzhiyun bb.event.set_handlers(saved_handlers) 367*4882a593Smuzhiyun 368*4882a593Smuzhiyundef _create_variants(datastores, names, function, onlyfinalise): 369*4882a593Smuzhiyun def create_variant(name, orig_d, arg = None): 370*4882a593Smuzhiyun if onlyfinalise and name not in onlyfinalise: 371*4882a593Smuzhiyun return 372*4882a593Smuzhiyun new_d = bb.data.createCopy(orig_d) 373*4882a593Smuzhiyun function(arg or name, new_d) 374*4882a593Smuzhiyun datastores[name] = new_d 375*4882a593Smuzhiyun 376*4882a593Smuzhiyun for variant in list(datastores.keys()): 377*4882a593Smuzhiyun for name in names: 378*4882a593Smuzhiyun if not variant: 379*4882a593Smuzhiyun # Based on main recipe 380*4882a593Smuzhiyun create_variant(name, datastores[""]) 381*4882a593Smuzhiyun else: 382*4882a593Smuzhiyun create_variant("%s-%s" % (variant, name), datastores[variant], name) 383*4882a593Smuzhiyun 384*4882a593Smuzhiyundef multi_finalize(fn, d): 385*4882a593Smuzhiyun appends = (d.getVar("__BBAPPEND") or "").split() 386*4882a593Smuzhiyun for append in appends: 387*4882a593Smuzhiyun logger.debug("Appending .bbappend file %s to %s", append, fn) 388*4882a593Smuzhiyun bb.parse.BBHandler.handle(append, d, True) 389*4882a593Smuzhiyun 390*4882a593Smuzhiyun onlyfinalise = d.getVar("__ONLYFINALISE", False) 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun safe_d = d 393*4882a593Smuzhiyun d = bb.data.createCopy(safe_d) 394*4882a593Smuzhiyun try: 395*4882a593Smuzhiyun finalize(fn, d) 396*4882a593Smuzhiyun except bb.parse.SkipRecipe as e: 397*4882a593Smuzhiyun d.setVar("__SKIPPED", e.args[0]) 398*4882a593Smuzhiyun datastores = {"": safe_d} 399*4882a593Smuzhiyun 400*4882a593Smuzhiyun extended = d.getVar("BBCLASSEXTEND") or "" 401*4882a593Smuzhiyun if extended: 402*4882a593Smuzhiyun # the following is to support bbextends with arguments, for e.g. multilib 403*4882a593Smuzhiyun # an example is as follows: 404*4882a593Smuzhiyun # BBCLASSEXTEND = "multilib:lib32" 405*4882a593Smuzhiyun # it will create foo-lib32, inheriting multilib.bbclass and set 406*4882a593Smuzhiyun # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32" 407*4882a593Smuzhiyun extendedmap = {} 408*4882a593Smuzhiyun variantmap = {} 409*4882a593Smuzhiyun 410*4882a593Smuzhiyun for ext in extended.split(): 411*4882a593Smuzhiyun eext = ext.split(':', 2) 412*4882a593Smuzhiyun if len(eext) > 1: 413*4882a593Smuzhiyun extendedmap[ext] = eext[0] 414*4882a593Smuzhiyun variantmap[ext] = eext[1] 415*4882a593Smuzhiyun else: 416*4882a593Smuzhiyun extendedmap[ext] = ext 417*4882a593Smuzhiyun 418*4882a593Smuzhiyun pn = d.getVar("PN") 419*4882a593Smuzhiyun def extendfunc(name, d): 420*4882a593Smuzhiyun if name != extendedmap[name]: 421*4882a593Smuzhiyun d.setVar("BBEXTENDCURR", extendedmap[name]) 422*4882a593Smuzhiyun d.setVar("BBEXTENDVARIANT", variantmap[name]) 423*4882a593Smuzhiyun else: 424*4882a593Smuzhiyun d.setVar("PN", "%s-%s" % (pn, name)) 425*4882a593Smuzhiyun bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d) 426*4882a593Smuzhiyun 427*4882a593Smuzhiyun safe_d.setVar("BBCLASSEXTEND", extended) 428*4882a593Smuzhiyun _create_variants(datastores, extendedmap.keys(), extendfunc, onlyfinalise) 429*4882a593Smuzhiyun 430*4882a593Smuzhiyun for variant in datastores.keys(): 431*4882a593Smuzhiyun if variant: 432*4882a593Smuzhiyun try: 433*4882a593Smuzhiyun if not onlyfinalise or variant in onlyfinalise: 434*4882a593Smuzhiyun finalize(fn, datastores[variant], variant) 435*4882a593Smuzhiyun except bb.parse.SkipRecipe as e: 436*4882a593Smuzhiyun datastores[variant].setVar("__SKIPPED", e.args[0]) 437*4882a593Smuzhiyun 438*4882a593Smuzhiyun datastores[""] = d 439*4882a593Smuzhiyun return datastores 440