summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/parse
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/parse')
-rw-r--r--bitbake/lib/bb/parse/__init__.py24
-rw-r--r--bitbake/lib/bb/parse/ast.py85
-rw-r--r--bitbake/lib/bb/parse/parse_py/BBHandler.py72
-rw-r--r--bitbake/lib/bb/parse/parse_py/ConfHandler.py38
4 files changed, 169 insertions, 50 deletions
diff --git a/bitbake/lib/bb/parse/__init__.py b/bitbake/lib/bb/parse/__init__.py
index c01807ba87..7ffdaa6fd7 100644
--- a/bitbake/lib/bb/parse/__init__.py
+++ b/bitbake/lib/bb/parse/__init__.py
@@ -49,20 +49,32 @@ class SkipPackage(SkipRecipe):
49__mtime_cache = {} 49__mtime_cache = {}
50def cached_mtime(f): 50def cached_mtime(f):
51 if f not in __mtime_cache: 51 if f not in __mtime_cache:
52 __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 52 res = os.stat(f)
53 __mtime_cache[f] = (res.st_mtime_ns, res.st_size, res.st_ino)
53 return __mtime_cache[f] 54 return __mtime_cache[f]
54 55
55def cached_mtime_noerror(f): 56def cached_mtime_noerror(f):
56 if f not in __mtime_cache: 57 if f not in __mtime_cache:
57 try: 58 try:
58 __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 59 res = os.stat(f)
60 __mtime_cache[f] = (res.st_mtime_ns, res.st_size, res.st_ino)
59 except OSError: 61 except OSError:
60 return 0 62 return 0
61 return __mtime_cache[f] 63 return __mtime_cache[f]
62 64
65def check_mtime(f, mtime):
66 try:
67 res = os.stat(f)
68 current_mtime = (res.st_mtime_ns, res.st_size, res.st_ino)
69 __mtime_cache[f] = current_mtime
70 except OSError:
71 current_mtime = 0
72 return current_mtime == mtime
73
63def update_mtime(f): 74def update_mtime(f):
64 try: 75 try:
65 __mtime_cache[f] = os.stat(f)[stat.ST_MTIME] 76 res = os.stat(f)
77 __mtime_cache[f] = (res.st_mtime_ns, res.st_size, res.st_ino)
66 except OSError: 78 except OSError:
67 if f in __mtime_cache: 79 if f in __mtime_cache:
68 del __mtime_cache[f] 80 del __mtime_cache[f]
@@ -99,12 +111,12 @@ def supports(fn, data):
99 return 1 111 return 1
100 return 0 112 return 0
101 113
102def handle(fn, data, include = 0): 114def handle(fn, data, include=0, baseconfig=False):
103 """Call the handler that is appropriate for this file""" 115 """Call the handler that is appropriate for this file"""
104 for h in handlers: 116 for h in handlers:
105 if h['supports'](fn, data): 117 if h['supports'](fn, data):
106 with data.inchistory.include(fn): 118 with data.inchistory.include(fn):
107 return h['handle'](fn, data, include) 119 return h['handle'](fn, data, include, baseconfig)
108 raise ParseError("not a BitBake file", fn) 120 raise ParseError("not a BitBake file", fn)
109 121
110def init(fn, data): 122def init(fn, data):
@@ -113,6 +125,8 @@ def init(fn, data):
113 return h['init'](data) 125 return h['init'](data)
114 126
115def init_parser(d): 127def init_parser(d):
128 if hasattr(bb.parse, "siggen"):
129 bb.parse.siggen.exit()
116 bb.parse.siggen = bb.siggen.init(d) 130 bb.parse.siggen = bb.siggen.init(d)
117 131
118def resolve_file(fn, d): 132def resolve_file(fn, d):
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py
index 50a88f7da7..7581d003fd 100644
--- a/bitbake/lib/bb/parse/ast.py
+++ b/bitbake/lib/bb/parse/ast.py
@@ -9,6 +9,7 @@
9# SPDX-License-Identifier: GPL-2.0-only 9# SPDX-License-Identifier: GPL-2.0-only
10# 10#
11 11
12import sys
12import bb 13import bb
13from bb import methodpool 14from bb import methodpool
14from bb.parse import logger 15from bb.parse import logger
@@ -130,6 +131,10 @@ class DataNode(AstNode):
130 else: 131 else:
131 val = groupd["value"] 132 val = groupd["value"]
132 133
134 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
133 flag = None 138 flag = None
134 if 'flag' in groupd and groupd['flag'] is not None: 139 if 'flag' in groupd and groupd['flag'] is not None:
135 flag = groupd['flag'] 140 flag = groupd['flag']
@@ -145,7 +150,7 @@ class DataNode(AstNode):
145 data.setVar(key, val, parsing=True, **loginfo) 150 data.setVar(key, val, parsing=True, **loginfo)
146 151
147class MethodNode(AstNode): 152class MethodNode(AstNode):
148 tr_tbl = str.maketrans('/.+-@%&', '_______') 153 tr_tbl = str.maketrans('/.+-@%&~', '________')
149 154
150 def __init__(self, filename, lineno, func_name, body, python, fakeroot): 155 def __init__(self, filename, lineno, func_name, body, python, fakeroot):
151 AstNode.__init__(self, filename, lineno) 156 AstNode.__init__(self, filename, lineno)
@@ -206,10 +211,12 @@ class ExportFuncsNode(AstNode):
206 211
207 def eval(self, data): 212 def eval(self, data):
208 213
214 sentinel = " # Export function set\n"
209 for func in self.n: 215 for func in self.n:
210 calledfunc = self.classname + "_" + func 216 calledfunc = self.classname + "_" + func
211 217
212 if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False): 218 basevar = data.getVar(func, False)
219 if basevar and sentinel not in basevar:
213 continue 220 continue
214 221
215 if data.getVar(func, False): 222 if data.getVar(func, False):
@@ -219,19 +226,18 @@ class ExportFuncsNode(AstNode):
219 for flag in [ "func", "python" ]: 226 for flag in [ "func", "python" ]:
220 if data.getVarFlag(calledfunc, flag, False): 227 if data.getVarFlag(calledfunc, flag, False):
221 data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False)) 228 data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False))
222 for flag in [ "dirs" ]: 229 for flag in ["dirs", "cleandirs", "fakeroot"]:
223 if data.getVarFlag(func, flag, False): 230 if data.getVarFlag(func, flag, False):
224 data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False)) 231 data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False))
225 data.setVarFlag(func, "filename", "autogenerated") 232 data.setVarFlag(func, "filename", "autogenerated")
226 data.setVarFlag(func, "lineno", 1) 233 data.setVarFlag(func, "lineno", 1)
227 234
228 if data.getVarFlag(calledfunc, "python", False): 235 if data.getVarFlag(calledfunc, "python", False):
229 data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True) 236 data.setVar(func, sentinel + " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True)
230 else: 237 else:
231 if "-" in self.classname: 238 if "-" in self.classname:
232 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)) 239 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))
233 data.setVar(func, " " + calledfunc + "\n", parsing=True) 240 data.setVar(func, sentinel + " " + calledfunc + "\n", parsing=True)
234 data.setVarFlag(func, 'export_func', '1')
235 241
236class AddTaskNode(AstNode): 242class AddTaskNode(AstNode):
237 def __init__(self, filename, lineno, func, before, after): 243 def __init__(self, filename, lineno, func, before, after):
@@ -265,6 +271,41 @@ class BBHandlerNode(AstNode):
265 data.setVarFlag(h, "handler", 1) 271 data.setVarFlag(h, "handler", 1)
266 data.setVar('__BBHANDLERS', bbhands) 272 data.setVar('__BBHANDLERS', bbhands)
267 273
274class PyLibNode(AstNode):
275 def __init__(self, filename, lineno, libdir, namespace):
276 AstNode.__init__(self, filename, lineno)
277 self.libdir = libdir
278 self.namespace = namespace
279
280 def eval(self, data):
281 global_mods = (data.getVar("BB_GLOBAL_PYMODULES") or "").split()
282 for m in global_mods:
283 if m not in bb.utils._context:
284 bb.utils._context[m] = __import__(m)
285
286 libdir = data.expand(self.libdir)
287 if libdir not in sys.path:
288 sys.path.append(libdir)
289 try:
290 bb.utils._context[self.namespace] = __import__(self.namespace)
291 toimport = getattr(bb.utils._context[self.namespace], "BBIMPORTS", [])
292 for i in toimport:
293 bb.utils._context[self.namespace] = __import__(self.namespace + "." + i)
294 mod = getattr(bb.utils._context[self.namespace], i)
295 fn = getattr(mod, "__file__")
296 funcs = {}
297 for f in dir(mod):
298 if f.startswith("_"):
299 continue
300 fcall = getattr(mod, f)
301 if not callable(fcall):
302 continue
303 funcs[f] = fcall
304 bb.codeparser.add_module_functions(fn, funcs, "%s.%s" % (self.namespace, i))
305
306 except AttributeError as e:
307 bb.error("Error importing OE modules: %s" % str(e))
308
268class InheritNode(AstNode): 309class InheritNode(AstNode):
269 def __init__(self, filename, lineno, classes): 310 def __init__(self, filename, lineno, classes):
270 AstNode.__init__(self, filename, lineno) 311 AstNode.__init__(self, filename, lineno)
@@ -273,6 +314,16 @@ class InheritNode(AstNode):
273 def eval(self, data): 314 def eval(self, data):
274 bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data) 315 bb.parse.BBHandler.inherit(self.classes, self.filename, self.lineno, data)
275 316
317class InheritDeferredNode(AstNode):
318 def __init__(self, filename, lineno, classes):
319 AstNode.__init__(self, filename, lineno)
320 self.inherit = (classes, filename, lineno)
321
322 def eval(self, data):
323 inherits = data.getVar('__BBDEFINHERITS', False) or []
324 inherits.append(self.inherit)
325 data.setVar('__BBDEFINHERITS', inherits)
326
276def handleInclude(statements, filename, lineno, m, force): 327def handleInclude(statements, filename, lineno, m, force):
277 statements.append(IncludeNode(filename, lineno, m.group(1), force)) 328 statements.append(IncludeNode(filename, lineno, m.group(1), force))
278 329
@@ -316,10 +367,17 @@ def handleDelTask(statements, filename, lineno, m):
316def handleBBHandlers(statements, filename, lineno, m): 367def handleBBHandlers(statements, filename, lineno, m):
317 statements.append(BBHandlerNode(filename, lineno, m.group(1))) 368 statements.append(BBHandlerNode(filename, lineno, m.group(1)))
318 369
370def handlePyLib(statements, filename, lineno, m):
371 statements.append(PyLibNode(filename, lineno, m.group(1), m.group(2)))
372
319def handleInherit(statements, filename, lineno, m): 373def handleInherit(statements, filename, lineno, m):
320 classes = m.group(1) 374 classes = m.group(1)
321 statements.append(InheritNode(filename, lineno, classes)) 375 statements.append(InheritNode(filename, lineno, classes))
322 376
377def handleInheritDeferred(statements, filename, lineno, m):
378 classes = m.group(1)
379 statements.append(InheritDeferredNode(filename, lineno, classes))
380
323def runAnonFuncs(d): 381def runAnonFuncs(d):
324 code = [] 382 code = []
325 for funcname in d.getVar("__BBANONFUNCS", False) or []: 383 for funcname in d.getVar("__BBANONFUNCS", False) or []:
@@ -329,6 +387,10 @@ def runAnonFuncs(d):
329def finalize(fn, d, variant = None): 387def finalize(fn, d, variant = None):
330 saved_handlers = bb.event.get_handlers().copy() 388 saved_handlers = bb.event.get_handlers().copy()
331 try: 389 try:
390 # Found renamed variables. Exit immediately
391 if d.getVar("_FAILPARSINGERRORHANDLED", False) == True:
392 raise bb.BBHandledException()
393
332 for var in d.getVar('__BBHANDLERS', False) or []: 394 for var in d.getVar('__BBHANDLERS', False) or []:
333 # try to add the handler 395 # try to add the handler
334 handlerfn = d.getVarFlag(var, "filename", False) 396 handlerfn = d.getVarFlag(var, "filename", False)
@@ -353,6 +415,9 @@ def finalize(fn, d, variant = None):
353 415
354 d.setVar('BBINCLUDED', bb.parse.get_file_depends(d)) 416 d.setVar('BBINCLUDED', bb.parse.get_file_depends(d))
355 417
418 if d.getVar('__BBAUTOREV_SEEN') and d.getVar('__BBSRCREV_SEEN') and not d.getVar("__BBAUTOREV_ACTED_UPON"):
419 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.")
420
356 bb.event.fire(bb.event.RecipeParsed(fn), d) 421 bb.event.fire(bb.event.RecipeParsed(fn), d)
357 finally: 422 finally:
358 bb.event.set_handlers(saved_handlers) 423 bb.event.set_handlers(saved_handlers)
@@ -379,6 +444,14 @@ def multi_finalize(fn, d):
379 logger.debug("Appending .bbappend file %s to %s", append, fn) 444 logger.debug("Appending .bbappend file %s to %s", append, fn)
380 bb.parse.BBHandler.handle(append, d, True) 445 bb.parse.BBHandler.handle(append, d, True)
381 446
447 while True:
448 inherits = d.getVar('__BBDEFINHERITS', False) or []
449 if not inherits:
450 break
451 inherit, filename, lineno = inherits.pop(0)
452 d.setVar('__BBDEFINHERITS', inherits)
453 bb.parse.BBHandler.inherit(inherit, filename, lineno, d, deferred=True)
454
382 onlyfinalise = d.getVar("__ONLYFINALISE", False) 455 onlyfinalise = d.getVar("__ONLYFINALISE", False)
383 456
384 safe_d = d 457 safe_d = d
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index f8988b8631..c13e4b9755 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -19,11 +19,9 @@ from . import ConfHandler
19from .. import resolve_file, ast, logger, ParseError 19from .. import resolve_file, ast, logger, ParseError
20from .ConfHandler import include, init 20from .ConfHandler import include, init
21 21
22# For compatibility 22__func_start_regexp__ = re.compile(r"(((?P<py>python(?=(\s|\()))|(?P<fr>fakeroot(?=\s)))\s*)*(?P<func>[\w\.\-\+\{\}\$:]+)?\s*\(\s*\)\s*{$" )
23bb.deprecate_import(__name__, "bb.parse", ["vars_from_file"])
24
25__func_start_regexp__ = re.compile(r"(((?P<py>python(?=(\s|\()))|(?P<fr>fakeroot(?=\s)))\s*)*(?P<func>[\w\.\-\+\{\}\$]+)?\s*\(\s*\)\s*{$" )
26__inherit_regexp__ = re.compile(r"inherit\s+(.+)" ) 23__inherit_regexp__ = re.compile(r"inherit\s+(.+)" )
24__inherit_def_regexp__ = re.compile(r"inherit_defer\s+(.+)" )
27__export_func_regexp__ = re.compile(r"EXPORT_FUNCTIONS\s+(.+)" ) 25__export_func_regexp__ = re.compile(r"EXPORT_FUNCTIONS\s+(.+)" )
28__addtask_regexp__ = re.compile(r"addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*") 26__addtask_regexp__ = re.compile(r"addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
29__deltask_regexp__ = re.compile(r"deltask\s+(.+)") 27__deltask_regexp__ = re.compile(r"deltask\s+(.+)")
@@ -36,6 +34,7 @@ __infunc__ = []
36__inpython__ = False 34__inpython__ = False
37__body__ = [] 35__body__ = []
38__classname__ = "" 36__classname__ = ""
37__residue__ = []
39 38
40cached_statements = {} 39cached_statements = {}
41 40
@@ -43,31 +42,46 @@ def supports(fn, d):
43 """Return True if fn has a supported extension""" 42 """Return True if fn has a supported extension"""
44 return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"] 43 return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
45 44
46def inherit(files, fn, lineno, d): 45def inherit(files, fn, lineno, d, deferred=False):
47 __inherit_cache = d.getVar('__inherit_cache', False) or [] 46 __inherit_cache = d.getVar('__inherit_cache', False) or []
47 #if "${" in files and not deferred:
48 # bb.warn("%s:%s has non deferred conditional inherit" % (fn, lineno))
48 files = d.expand(files).split() 49 files = d.expand(files).split()
49 for file in files: 50 for file in files:
50 if not os.path.isabs(file) and not file.endswith(".bbclass"): 51 classtype = d.getVar("__bbclasstype", False)
51 file = os.path.join('classes', '%s.bbclass' % file) 52 origfile = file
52 53 for t in ["classes-" + classtype, "classes"]:
53 if not os.path.isabs(file): 54 file = origfile
54 bbpath = d.getVar("BBPATH") 55 if not os.path.isabs(file) and not file.endswith(".bbclass"):
55 abs_fn, attempts = bb.utils.which(bbpath, file, history=True) 56 file = os.path.join(t, '%s.bbclass' % file)
56 for af in attempts: 57
57 if af != abs_fn: 58 if not os.path.isabs(file):
58 bb.parse.mark_dependency(d, af) 59 bbpath = d.getVar("BBPATH")
59 if abs_fn: 60 abs_fn, attempts = bb.utils.which(bbpath, file, history=True)
60 file = abs_fn 61 for af in attempts:
62 if af != abs_fn:
63 bb.parse.mark_dependency(d, af)
64 if abs_fn:
65 file = abs_fn
66
67 if os.path.exists(file):
68 break
69
70 if not os.path.exists(file):
71 raise ParseError("Could not inherit file %s" % (file), fn, lineno)
61 72
62 if not file in __inherit_cache: 73 if not file in __inherit_cache:
63 logger.debug("Inheriting %s (from %s:%d)" % (file, fn, lineno)) 74 logger.debug("Inheriting %s (from %s:%d)" % (file, fn, lineno))
64 __inherit_cache.append( file ) 75 __inherit_cache.append( file )
65 d.setVar('__inherit_cache', __inherit_cache) 76 d.setVar('__inherit_cache', __inherit_cache)
66 include(fn, file, lineno, d, "inherit") 77 try:
78 bb.parse.handle(file, d, True)
79 except (IOError, OSError) as exc:
80 raise ParseError("Could not inherit file %s: %s" % (fn, exc.strerror), fn, lineno)
67 __inherit_cache = d.getVar('__inherit_cache', False) or [] 81 __inherit_cache = d.getVar('__inherit_cache', False) or []
68 82
69def get_statements(filename, absolute_filename, base_name): 83def get_statements(filename, absolute_filename, base_name):
70 global cached_statements 84 global cached_statements, __residue__, __body__
71 85
72 try: 86 try:
73 return cached_statements[absolute_filename] 87 return cached_statements[absolute_filename]
@@ -87,12 +101,17 @@ def get_statements(filename, absolute_filename, base_name):
87 # add a blank line to close out any python definition 101 # add a blank line to close out any python definition
88 feeder(lineno, "", filename, base_name, statements, eof=True) 102 feeder(lineno, "", filename, base_name, statements, eof=True)
89 103
104 if __residue__:
105 raise ParseError("Unparsed lines %s: %s" % (filename, str(__residue__)), filename, lineno)
106 if __body__:
107 raise ParseError("Unparsed lines from unclosed function %s: %s" % (filename, str(__body__)), filename, lineno)
108
90 if filename.endswith(".bbclass") or filename.endswith(".inc"): 109 if filename.endswith(".bbclass") or filename.endswith(".inc"):
91 cached_statements[absolute_filename] = statements 110 cached_statements[absolute_filename] = statements
92 return statements 111 return statements
93 112
94def handle(fn, d, include): 113def handle(fn, d, include, baseconfig=False):
95 global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __residue__, __classname__ 114 global __infunc__, __body__, __residue__, __classname__
96 __body__ = [] 115 __body__ = []
97 __infunc__ = [] 116 __infunc__ = []
98 __classname__ = "" 117 __classname__ = ""
@@ -144,7 +163,7 @@ def handle(fn, d, include):
144 return d 163 return d
145 164
146def feeder(lineno, s, fn, root, statements, eof=False): 165def feeder(lineno, s, fn, root, statements, eof=False):
147 global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__, __infunc__, __body__, bb, __residue__, __classname__ 166 global __inpython__, __infunc__, __body__, __residue__, __classname__
148 167
149 # Check tabs in python functions: 168 # Check tabs in python functions:
150 # - def py_funcname(): covered by __inpython__ 169 # - def py_funcname(): covered by __inpython__
@@ -181,10 +200,10 @@ def feeder(lineno, s, fn, root, statements, eof=False):
181 200
182 if s and s[0] == '#': 201 if s and s[0] == '#':
183 if len(__residue__) != 0 and __residue__[0][0] != "#": 202 if len(__residue__) != 0 and __residue__[0][0] != "#":
184 bb.fatal("There is a comment on line %s of file %s (%s) which is in the middle of a multiline expression.\nBitbake used to ignore these but no longer does so, please fix your metadata as errors are likely as a result of this change." % (lineno, fn, s)) 203 bb.fatal("There is a comment on line %s of file %s:\n'''\n%s\n'''\nwhich is in the middle of a multiline expression. This syntax is invalid, please correct it." % (lineno, fn, s))
185 204
186 if len(__residue__) != 0 and __residue__[0][0] == "#" and (not s or s[0] != "#"): 205 if len(__residue__) != 0 and __residue__[0][0] == "#" and (not s or s[0] != "#"):
187 bb.fatal("There is a confusing multiline, partially commented expression on line %s of file %s (%s).\nPlease clarify whether this is all a comment or should be parsed." % (lineno, fn, s)) 206 bb.fatal("There is a confusing multiline partially commented expression on line %s of file %s:\n%s\nPlease clarify whether this is all a comment or should be parsed." % (lineno - len(__residue__), fn, "\n".join(__residue__)))
188 207
189 if s and s[-1] == '\\': 208 if s and s[-1] == '\\':
190 __residue__.append(s[:-1]) 209 __residue__.append(s[:-1])
@@ -255,7 +274,12 @@ def feeder(lineno, s, fn, root, statements, eof=False):
255 ast.handleInherit(statements, fn, lineno, m) 274 ast.handleInherit(statements, fn, lineno, m)
256 return 275 return
257 276
258 return ConfHandler.feeder(lineno, s, fn, statements) 277 m = __inherit_def_regexp__.match(s)
278 if m:
279 ast.handleInheritDeferred(statements, fn, lineno, m)
280 return
281
282 return ConfHandler.feeder(lineno, s, fn, statements, conffile=False)
259 283
260# Add us to the handlers list 284# Add us to the handlers list
261from .. import handlers 285from .. import handlers
diff --git a/bitbake/lib/bb/parse/parse_py/ConfHandler.py b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
index f171c5c932..7826dee7d3 100644
--- a/bitbake/lib/bb/parse/parse_py/ConfHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
@@ -20,8 +20,8 @@ from bb.parse import ParseError, resolve_file, ast, logger, handle
20__config_regexp__ = re.compile( r""" 20__config_regexp__ = re.compile( r"""
21 ^ 21 ^
22 (?P<exp>export\s+)? 22 (?P<exp>export\s+)?
23 (?P<var>[a-zA-Z0-9\-_+.${}/~]+?) 23 (?P<var>[a-zA-Z0-9\-_+.${}/~:]+?)
24 (\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])? 24 (\[(?P<flag>[a-zA-Z0-9\-_+.][a-zA-Z0-9\-_+.@]*)\])?
25 25
26 \s* ( 26 \s* (
27 (?P<colon>:=) | 27 (?P<colon>:=) |
@@ -45,13 +45,11 @@ __include_regexp__ = re.compile( r"include\s+(.+)" )
45__require_regexp__ = re.compile( r"require\s+(.+)" ) 45__require_regexp__ = re.compile( r"require\s+(.+)" )
46__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/~]+)$" ) 46__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
47__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)$" ) 47__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
48__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)\[([a-zA-Z0-9\-_+.]+)\]$" ) 48__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)\[([a-zA-Z0-9\-_+.][a-zA-Z0-9\-_+.@]+)\]$" )
49__addpylib_regexp__ = re.compile(r"addpylib\s+(.+)\s+(.+)" )
49 50
50def init(data): 51def init(data):
51 topdir = data.getVar('TOPDIR', False) 52 return
52 if not topdir:
53 data.setVar('TOPDIR', os.getcwd())
54
55 53
56def supports(fn, d): 54def supports(fn, d):
57 return fn[-5:] == ".conf" 55 return fn[-5:] == ".conf"
@@ -105,12 +103,12 @@ def include_single_file(parentfn, fn, lineno, data, error_out):
105# We have an issue where a UI might want to enforce particular settings such as 103# We have an issue where a UI might want to enforce particular settings such as
106# an empty DISTRO variable. If configuration files do something like assigning 104# an empty DISTRO variable. If configuration files do something like assigning
107# a weak default, it turns out to be very difficult to filter out these changes, 105# a weak default, it turns out to be very difficult to filter out these changes,
108# particularly when the weak default might appear half way though parsing a chain 106# particularly when the weak default might appear half way though parsing a chain
109# of configuration files. We therefore let the UIs hook into configuration file 107# of configuration files. We therefore let the UIs hook into configuration file
110# parsing. This turns out to be a hard problem to solve any other way. 108# parsing. This turns out to be a hard problem to solve any other way.
111confFilters = [] 109confFilters = []
112 110
113def handle(fn, data, include): 111def handle(fn, data, include, baseconfig=False):
114 init(data) 112 init(data)
115 113
116 if include == 0: 114 if include == 0:
@@ -128,21 +126,26 @@ def handle(fn, data, include):
128 s = f.readline() 126 s = f.readline()
129 if not s: 127 if not s:
130 break 128 break
129 origlineno = lineno
130 origline = s
131 w = s.strip() 131 w = s.strip()
132 # skip empty lines 132 # skip empty lines
133 if not w: 133 if not w:
134 continue 134 continue
135 s = s.rstrip() 135 s = s.rstrip()
136 while s[-1] == '\\': 136 while s[-1] == '\\':
137 s2 = f.readline().rstrip() 137 line = f.readline()
138 origline += line
139 s2 = line.rstrip()
138 lineno = lineno + 1 140 lineno = lineno + 1
139 if (not s2 or s2 and s2[0] != "#") and s[0] == "#" : 141 if (not s2 or s2 and s2[0] != "#") and s[0] == "#" :
140 bb.fatal("There is a confusing multiline, partially commented expression on line %s of file %s (%s).\nPlease clarify whether this is all a comment or should be parsed." % (lineno, fn, s)) 142 bb.fatal("There is a confusing multiline, partially commented expression starting on line %s of file %s:\n%s\nPlease clarify whether this is all a comment or should be parsed." % (origlineno, fn, origline))
143
141 s = s[:-1] + s2 144 s = s[:-1] + s2
142 # skip comments 145 # skip comments
143 if s[0] == '#': 146 if s[0] == '#':
144 continue 147 continue
145 feeder(lineno, s, abs_fn, statements) 148 feeder(lineno, s, abs_fn, statements, baseconfig=baseconfig)
146 149
147 # DONE WITH PARSING... time to evaluate 150 # DONE WITH PARSING... time to evaluate
148 data.setVar('FILE', abs_fn) 151 data.setVar('FILE', abs_fn)
@@ -150,14 +153,14 @@ def handle(fn, data, include):
150 if oldfile: 153 if oldfile:
151 data.setVar('FILE', oldfile) 154 data.setVar('FILE', oldfile)
152 155
153 f.close()
154
155 for f in confFilters: 156 for f in confFilters:
156 f(fn, data) 157 f(fn, data)
157 158
158 return data 159 return data
159 160
160def feeder(lineno, s, fn, statements): 161# baseconfig is set for the bblayers/layer.conf cookerdata config parsing
162# The function is also used by BBHandler, conffile would be False
163def feeder(lineno, s, fn, statements, baseconfig=False, conffile=True):
161 m = __config_regexp__.match(s) 164 m = __config_regexp__.match(s)
162 if m: 165 if m:
163 groupd = m.groupdict() 166 groupd = m.groupdict()
@@ -189,6 +192,11 @@ def feeder(lineno, s, fn, statements):
189 ast.handleUnsetFlag(statements, fn, lineno, m) 192 ast.handleUnsetFlag(statements, fn, lineno, m)
190 return 193 return
191 194
195 m = __addpylib_regexp__.match(s)
196 if baseconfig and conffile and m:
197 ast.handlePyLib(statements, fn, lineno, m)
198 return
199
192 raise ParseError("unparsed line: '%s'" % s, fn, lineno); 200 raise ParseError("unparsed line: '%s'" % s, fn, lineno);
193 201
194# Add us to the handlers list 202# Add us to the handlers list