diff options
Diffstat (limited to 'bitbake/lib/bb/parse/ast.py')
-rw-r--r-- | bitbake/lib/bb/parse/ast.py | 128 |
1 files changed, 101 insertions, 27 deletions
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py index f0911e6fb7..7581d003fd 100644 --- a/bitbake/lib/bb/parse/ast.py +++ b/bitbake/lib/bb/parse/ast.py @@ -9,11 +9,8 @@ # SPDX-License-Identifier: GPL-2.0-only # -import re -import string -import logging +import sys import bb -import itertools from bb import methodpool from bb.parse import logger @@ -38,7 +35,7 @@ class IncludeNode(AstNode): Include the file and evaluate the statements """ s = data.expand(self.what_file) - logger.debug(2, "CONF %s:%s: including %s", self.filename, self.lineno, s) + logger.debug2("CONF %s:%s: including %s", self.filename, self.lineno, s) # TODO: Cache those includes... maybe not here though if self.force: @@ -93,7 +90,7 @@ class DataNode(AstNode): self.groupd = groupd def getFunc(self, key, data): - if 'flag' in self.groupd and self.groupd['flag'] != None: + if 'flag' in self.groupd and self.groupd['flag'] is not None: return data.getVarFlag(key, self.groupd['flag'], expand=False, noweakdefault=True) else: return data.getVar(key, False, noweakdefault=True, parsing=True) @@ -106,36 +103,40 @@ class DataNode(AstNode): 'file': self.filename, 'line': self.lineno, } - if "exp" in groupd and groupd["exp"] != None: + if "exp" in groupd and groupd["exp"] is not None: data.setVarFlag(key, "export", 1, op = 'exported', **loginfo) op = "set" - if "ques" in groupd and groupd["ques"] != None: + if "ques" in groupd and groupd["ques"] is not None: val = self.getFunc(key, data) op = "set?" - if val == None: + if val is None: val = groupd["value"] - elif "colon" in groupd and groupd["colon"] != None: + elif "colon" in groupd and groupd["colon"] is not None: e = data.createCopy() op = "immediate" val = e.expand(groupd["value"], key + "[:=]") - elif "append" in groupd and groupd["append"] != None: + elif "append" in groupd and groupd["append"] is not None: op = "append" val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"]) - elif "prepend" in groupd and groupd["prepend"] != None: + elif "prepend" in groupd and groupd["prepend"] is not None: op = "prepend" val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or "")) - elif "postdot" in groupd and groupd["postdot"] != None: + elif "postdot" in groupd and groupd["postdot"] is not None: op = "postdot" val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"]) - elif "predot" in groupd and groupd["predot"] != None: + elif "predot" in groupd and groupd["predot"] is not None: op = "predot" val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or "")) else: val = groupd["value"] + if ":append" in key or ":remove" in key or ":prepend" in key: + if op in ["append", "prepend", "postdot", "predot", "ques"]: + bb.warn(key + " " + groupd[op] + " is not a recommended operator combination, please replace it.") + flag = None - if 'flag' in groupd and groupd['flag'] != None: + if 'flag' in groupd and groupd['flag'] is not None: flag = groupd['flag'] elif groupd["lazyques"]: flag = "_defaultval" @@ -149,7 +150,7 @@ class DataNode(AstNode): data.setVar(key, val, parsing=True, **loginfo) class MethodNode(AstNode): - tr_tbl = str.maketrans('/.+-@%&', '_______') + tr_tbl = str.maketrans('/.+-@%&~', '________') def __init__(self, filename, lineno, func_name, body, python, fakeroot): AstNode.__init__(self, filename, lineno) @@ -210,10 +211,12 @@ class ExportFuncsNode(AstNode): def eval(self, data): + sentinel = " # Export function set\n" for func in self.n: calledfunc = self.classname + "_" + func - if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False): + basevar = data.getVar(func, False) + if basevar and sentinel not in basevar: continue if data.getVar(func, False): @@ -223,19 +226,18 @@ class ExportFuncsNode(AstNode): for flag in [ "func", "python" ]: if data.getVarFlag(calledfunc, flag, False): data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False)) - for flag in [ "dirs" ]: + for flag in ["dirs", "cleandirs", "fakeroot"]: if data.getVarFlag(func, flag, False): data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False)) data.setVarFlag(func, "filename", "autogenerated") data.setVarFlag(func, "lineno", 1) if data.getVarFlag(calledfunc, "python", False): - data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) + data.setVar(func, sentinel + " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) else: if "-" in self.classname: 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)) - data.setVar(func, " " + calledfunc + "\n", parsing=True) - data.setVarFlag(func, 'export_func', '1') + data.setVar(func, sentinel + " " + calledfunc + "\n", parsing=True) class AddTaskNode(AstNode): def __init__(self, filename, lineno, func, before, after): @@ -248,12 +250,14 @@ class AddTaskNode(AstNode): bb.build.addtask(self.func, self.before, self.after, data) class DelTaskNode(AstNode): - def __init__(self, filename, lineno, func): + def __init__(self, filename, lineno, tasks): AstNode.__init__(self, filename, lineno) - self.func = func + self.tasks = tasks def eval(self, data): - bb.build.deltask(self.func, data) + tasks = data.expand(self.tasks).split() + for task in tasks: + bb.build.deltask(task, data) class BBHandlerNode(AstNode): def __init__(self, filename, lineno, fns): @@ -267,6 +271,41 @@ class BBHandlerNode(AstNode): data.setVarFlag(h, "handler", 1) data.setVar('__BBHANDLERS', bbhands) +class PyLibNode(AstNode): + def __init__(self, filename, lineno, libdir, namespace): + AstNode.__init__(self, filename, lineno) + self.libdir = libdir + self.namespace = namespace + + def eval(self, data): + global_mods = (data.getVar("BB_GLOBAL_PYMODULES") or "").split() + for m in global_mods: + if m not in bb.utils._context: + bb.utils._context[m] = __import__(m) + + libdir = data.expand(self.libdir) + if libdir not in sys.path: + sys.path.append(libdir) + try: + bb.utils._context[self.namespace] = __import__(self.namespace) + toimport = getattr(bb.utils._context[self.namespace], "BBIMPORTS", []) + for i in toimport: + bb.utils._context[self.namespace] = __import__(self.namespace + "." + i) + mod = getattr(bb.utils._context[self.namespace], i) + fn = getattr(mod, "__file__") + funcs = {} + for f in dir(mod): + if f.startswith("_"): + continue + fcall = getattr(mod, f) + if not callable(fcall): + continue + funcs[f] = fcall + bb.codeparser.add_module_functions(fn, funcs, "%s.%s" % (self.namespace, i)) + + except AttributeError as e: + bb.error("Error importing OE modules: %s" % str(e)) + class InheritNode(AstNode): def __init__(self, filename, lineno, classes): AstNode.__init__(self, filename, lineno) @@ -275,6 +314,16 @@ class InheritNode(AstNode): def eval(self, data): bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data) +class InheritDeferredNode(AstNode): + def __init__(self, filename, lineno, classes): + AstNode.__init__(self, filename, lineno) + self.inherit = (classes, filename, lineno) + + def eval(self, data): + inherits = data.getVar('__BBDEFINHERITS', False) or [] + inherits.append(self.inherit) + data.setVar('__BBDEFINHERITS', inherits) + def handleInclude(statements, filename, lineno, m, force): statements.append(IncludeNode(filename, lineno, m.group(1), force)) @@ -309,7 +358,7 @@ def handleAddTask(statements, filename, lineno, m): statements.append(AddTaskNode(filename, lineno, func, before, after)) def handleDelTask(statements, filename, lineno, m): - func = m.group("func") + func = m.group(1) if func is None: return @@ -318,10 +367,17 @@ def handleDelTask(statements, filename, lineno, m): def handleBBHandlers(statements, filename, lineno, m): statements.append(BBHandlerNode(filename, lineno, m.group(1))) +def handlePyLib(statements, filename, lineno, m): + statements.append(PyLibNode(filename, lineno, m.group(1), m.group(2))) + def handleInherit(statements, filename, lineno, m): classes = m.group(1) statements.append(InheritNode(filename, lineno, classes)) +def handleInheritDeferred(statements, filename, lineno, m): + classes = m.group(1) + statements.append(InheritDeferredNode(filename, lineno, classes)) + def runAnonFuncs(d): code = [] for funcname in d.getVar("__BBANONFUNCS", False) or []: @@ -331,17 +387,24 @@ def runAnonFuncs(d): def finalize(fn, d, variant = None): saved_handlers = bb.event.get_handlers().copy() try: + # Found renamed variables. Exit immediately + if d.getVar("_FAILPARSINGERRORHANDLED", False) == True: + raise bb.BBHandledException() + for var in d.getVar('__BBHANDLERS', False) or []: # try to add the handler handlerfn = d.getVarFlag(var, "filename", False) if not handlerfn: bb.fatal("Undefined event handler function '%s'" % var) handlerln = int(d.getVarFlag(var, "lineno", False)) - bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln) + bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data=d) bb.event.fire(bb.event.RecipePreFinalise(fn), d) bb.data.expandKeys(d) + + bb.event.fire(bb.event.RecipePostKeyExpansion(fn), d) + runAnonFuncs(d) tasklist = d.getVar('__BBTASKS', False) or [] @@ -352,6 +415,9 @@ def finalize(fn, d, variant = None): d.setVar('BBINCLUDED', bb.parse.get_file_depends(d)) + if d.getVar('__BBAUTOREV_SEEN') and d.getVar('__BBSRCREV_SEEN') and not d.getVar("__BBAUTOREV_ACTED_UPON"): + bb.fatal("AUTOREV/SRCPV set too late for the fetcher to work properly, please set the variables earlier in parsing. Erroring instead of later obtuse build failures.") + bb.event.fire(bb.event.RecipeParsed(fn), d) finally: bb.event.set_handlers(saved_handlers) @@ -375,9 +441,17 @@ def _create_variants(datastores, names, function, onlyfinalise): def multi_finalize(fn, d): appends = (d.getVar("__BBAPPEND") or "").split() for append in appends: - logger.debug(1, "Appending .bbappend file %s to %s", append, fn) + logger.debug("Appending .bbappend file %s to %s", append, fn) bb.parse.BBHandler.handle(append, d, True) + while True: + inherits = d.getVar('__BBDEFINHERITS', False) or [] + if not inherits: + break + inherit, filename, lineno = inherits.pop(0) + d.setVar('__BBDEFINHERITS', inherits) + bb.parse.BBHandler.inherit(inherit, filename, lineno, d, deferred=True) + onlyfinalise = d.getVar("__ONLYFINALISE", False) safe_d = d |