summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/cookerdata.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/cookerdata.py')
-rw-r--r--bitbake/lib/bb/cookerdata.py197
1 files changed, 153 insertions, 44 deletions
diff --git a/bitbake/lib/bb/cookerdata.py b/bitbake/lib/bb/cookerdata.py
index 1c1e008c6b..0649e40995 100644
--- a/bitbake/lib/bb/cookerdata.py
+++ b/bitbake/lib/bb/cookerdata.py
@@ -57,7 +57,7 @@ class ConfigParameters(object):
57 57
58 def updateToServer(self, server, environment): 58 def updateToServer(self, server, environment):
59 options = {} 59 options = {}
60 for o in ["abort", "force", "invalidate_stamp", 60 for o in ["halt", "force", "invalidate_stamp",
61 "dry_run", "dump_signatures", 61 "dry_run", "dump_signatures",
62 "extra_assume_provided", "profile", 62 "extra_assume_provided", "profile",
63 "prefile", "postfile", "server_timeout", 63 "prefile", "postfile", "server_timeout",
@@ -86,7 +86,7 @@ class ConfigParameters(object):
86 action['msg'] = "Only one target can be used with the --environment option." 86 action['msg'] = "Only one target can be used with the --environment option."
87 elif self.options.buildfile and len(self.options.pkgs_to_build) > 0: 87 elif self.options.buildfile and len(self.options.pkgs_to_build) > 0:
88 action['msg'] = "No target should be used with the --environment and --buildfile options." 88 action['msg'] = "No target should be used with the --environment and --buildfile options."
89 elif len(self.options.pkgs_to_build) > 0: 89 elif self.options.pkgs_to_build:
90 action['action'] = ["showEnvironmentTarget", self.options.pkgs_to_build] 90 action['action'] = ["showEnvironmentTarget", self.options.pkgs_to_build]
91 else: 91 else:
92 action['action'] = ["showEnvironment", self.options.buildfile] 92 action['action'] = ["showEnvironment", self.options.buildfile]
@@ -124,7 +124,7 @@ class CookerConfiguration(object):
124 self.prefile = [] 124 self.prefile = []
125 self.postfile = [] 125 self.postfile = []
126 self.cmd = None 126 self.cmd = None
127 self.abort = True 127 self.halt = True
128 self.force = False 128 self.force = False
129 self.profile = False 129 self.profile = False
130 self.nosetscene = False 130 self.nosetscene = False
@@ -160,12 +160,7 @@ def catch_parse_error(func):
160 def wrapped(fn, *args): 160 def wrapped(fn, *args):
161 try: 161 try:
162 return func(fn, *args) 162 return func(fn, *args)
163 except IOError as exc: 163 except Exception as exc:
164 import traceback
165 parselog.critical(traceback.format_exc())
166 parselog.critical("Unable to parse %s: %s" % (fn, exc))
167 raise bb.BBHandledException()
168 except bb.data_smart.ExpansionError as exc:
169 import traceback 164 import traceback
170 165
171 bbdir = os.path.dirname(__file__) + os.sep 166 bbdir = os.path.dirname(__file__) + os.sep
@@ -177,14 +172,11 @@ def catch_parse_error(func):
177 break 172 break
178 parselog.critical("Unable to parse %s" % fn, exc_info=(exc_class, exc, tb)) 173 parselog.critical("Unable to parse %s" % fn, exc_info=(exc_class, exc, tb))
179 raise bb.BBHandledException() 174 raise bb.BBHandledException()
180 except bb.parse.ParseError as exc:
181 parselog.critical(str(exc))
182 raise bb.BBHandledException()
183 return wrapped 175 return wrapped
184 176
185@catch_parse_error 177@catch_parse_error
186def parse_config_file(fn, data, include=True): 178def parse_config_file(fn, data, include=True):
187 return bb.parse.handle(fn, data, include) 179 return bb.parse.handle(fn, data, include, baseconfig=True)
188 180
189@catch_parse_error 181@catch_parse_error
190def _inherit(bbclass, data): 182def _inherit(bbclass, data):
@@ -210,7 +202,7 @@ def findConfigFile(configfile, data):
210 202
211# 203#
212# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working 204# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working
213# up to /. If that fails, we search for a conf/bitbake.conf in BBPATH. 205# up to /. If that fails, bitbake would fall back to cwd.
214# 206#
215 207
216def findTopdir(): 208def findTopdir():
@@ -223,11 +215,8 @@ def findTopdir():
223 layerconf = findConfigFile("bblayers.conf", d) 215 layerconf = findConfigFile("bblayers.conf", d)
224 if layerconf: 216 if layerconf:
225 return os.path.dirname(os.path.dirname(layerconf)) 217 return os.path.dirname(os.path.dirname(layerconf))
226 if bbpath: 218
227 bitbakeconf = bb.utils.which(bbpath, "conf/bitbake.conf") 219 return os.path.abspath(os.getcwd())
228 if bitbakeconf:
229 return os.path.dirname(os.path.dirname(bitbakeconf))
230 return None
231 220
232class CookerDataBuilder(object): 221class CookerDataBuilder(object):
233 222
@@ -250,10 +239,14 @@ class CookerDataBuilder(object):
250 self.savedenv = bb.data.init() 239 self.savedenv = bb.data.init()
251 for k in cookercfg.env: 240 for k in cookercfg.env:
252 self.savedenv.setVar(k, cookercfg.env[k]) 241 self.savedenv.setVar(k, cookercfg.env[k])
242 if k in bb.data_smart.bitbake_renamed_vars:
243 bb.error('Shell environment variable %s has been renamed to %s' % (k, bb.data_smart.bitbake_renamed_vars[k]))
244 bb.fatal("Exiting to allow enviroment variables to be corrected")
253 245
254 filtered_keys = bb.utils.approved_variables() 246 filtered_keys = bb.utils.approved_variables()
255 bb.data.inheritFromOS(self.basedata, self.savedenv, filtered_keys) 247 bb.data.inheritFromOS(self.basedata, self.savedenv, filtered_keys)
256 self.basedata.setVar("BB_ORIGENV", self.savedenv) 248 self.basedata.setVar("BB_ORIGENV", self.savedenv)
249 self.basedata.setVar("__bbclasstype", "global")
257 250
258 if worker: 251 if worker:
259 self.basedata.setVar("BB_WORKERCONTEXT", "1") 252 self.basedata.setVar("BB_WORKERCONTEXT", "1")
@@ -261,15 +254,15 @@ class CookerDataBuilder(object):
261 self.data = self.basedata 254 self.data = self.basedata
262 self.mcdata = {} 255 self.mcdata = {}
263 256
264 def parseBaseConfiguration(self): 257 def parseBaseConfiguration(self, worker=False):
258 mcdata = {}
265 data_hash = hashlib.sha256() 259 data_hash = hashlib.sha256()
266 try: 260 try:
267 self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles) 261 self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles)
268 262
269 if self.data.getVar("BB_WORKERCONTEXT", False) is None: 263 if self.data.getVar("BB_WORKERCONTEXT", False) is None and not worker:
270 bb.fetch.fetcher_init(self.data) 264 bb.fetch.fetcher_init(self.data)
271 bb.parse.init_parser(self.data) 265 bb.parse.init_parser(self.data)
272 bb.codeparser.parser_cache_init(self.data)
273 266
274 bb.event.fire(bb.event.ConfigParsed(), self.data) 267 bb.event.fire(bb.event.ConfigParsed(), self.data)
275 268
@@ -287,38 +280,62 @@ class CookerDataBuilder(object):
287 280
288 bb.parse.init_parser(self.data) 281 bb.parse.init_parser(self.data)
289 data_hash.update(self.data.get_hash().encode('utf-8')) 282 data_hash.update(self.data.get_hash().encode('utf-8'))
290 self.mcdata[''] = self.data 283 mcdata[''] = self.data
291 284
292 multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split() 285 multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split()
293 for config in multiconfig: 286 for config in multiconfig:
294 mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config) 287 if config[0].isdigit():
295 bb.event.fire(bb.event.ConfigParsed(), mcdata) 288 bb.fatal("Multiconfig name '%s' is invalid as multiconfigs cannot start with a digit" % config)
296 self.mcdata[config] = mcdata 289 parsed_mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config)
297 data_hash.update(mcdata.get_hash().encode('utf-8')) 290 bb.event.fire(bb.event.ConfigParsed(), parsed_mcdata)
291 mcdata[config] = parsed_mcdata
292 data_hash.update(parsed_mcdata.get_hash().encode('utf-8'))
298 if multiconfig: 293 if multiconfig:
299 bb.event.fire(bb.event.MultiConfigParsed(self.mcdata), self.data) 294 bb.event.fire(bb.event.MultiConfigParsed(mcdata), self.data)
300 295
301 self.data_hash = data_hash.hexdigest() 296 self.data_hash = data_hash.hexdigest()
302 except (SyntaxError, bb.BBHandledException):
303 raise bb.BBHandledException()
304 except bb.data_smart.ExpansionError as e: 297 except bb.data_smart.ExpansionError as e:
305 logger.error(str(e)) 298 logger.error(str(e))
306 raise bb.BBHandledException() 299 raise bb.BBHandledException()
307 except Exception: 300
308 logger.exception("Error parsing configuration files") 301 bb.codeparser.update_module_dependencies(self.data)
302
303 # Handle obsolete variable names
304 d = self.data
305 renamedvars = d.getVarFlags('BB_RENAMED_VARIABLES') or {}
306 renamedvars.update(bb.data_smart.bitbake_renamed_vars)
307 issues = False
308 for v in renamedvars:
309 if d.getVar(v) != None or d.hasOverrides(v):
310 issues = True
311 loginfo = {}
312 history = d.varhistory.get_variable_refs(v)
313 for h in history:
314 for line in history[h]:
315 loginfo = {'file' : h, 'line' : line}
316 bb.data.data_smart._print_rename_error(v, loginfo, renamedvars)
317 if not history:
318 bb.data.data_smart._print_rename_error(v, loginfo, renamedvars)
319 if issues:
309 raise bb.BBHandledException() 320 raise bb.BBHandledException()
310 321
322 for mc in mcdata:
323 mcdata[mc].renameVar("__depends", "__base_depends")
324 mcdata[mc].setVar("__bbclasstype", "recipe")
325
311 # Create a copy so we can reset at a later date when UIs disconnect 326 # Create a copy so we can reset at a later date when UIs disconnect
312 self.origdata = self.data 327 self.mcorigdata = mcdata
313 self.data = bb.data.createCopy(self.origdata) 328 for mc in mcdata:
314 self.mcdata[''] = self.data 329 self.mcdata[mc] = bb.data.createCopy(mcdata[mc])
330 self.data = self.mcdata['']
315 331
316 def reset(self): 332 def reset(self):
317 # We may not have run parseBaseConfiguration() yet 333 # We may not have run parseBaseConfiguration() yet
318 if not hasattr(self, 'origdata'): 334 if not hasattr(self, 'mcorigdata'):
319 return 335 return
320 self.data = bb.data.createCopy(self.origdata) 336 for mc in self.mcorigdata:
321 self.mcdata[''] = self.data 337 self.mcdata[mc] = bb.data.createCopy(self.mcorigdata[mc])
338 self.data = self.mcdata['']
322 339
323 def _findLayerConf(self, data): 340 def _findLayerConf(self, data):
324 return findConfigFile("bblayers.conf", data) 341 return findConfigFile("bblayers.conf", data)
@@ -333,15 +350,23 @@ class CookerDataBuilder(object):
333 350
334 layerconf = self._findLayerConf(data) 351 layerconf = self._findLayerConf(data)
335 if layerconf: 352 if layerconf:
336 parselog.debug(2, "Found bblayers.conf (%s)", layerconf) 353 parselog.debug2("Found bblayers.conf (%s)", layerconf)
337 # By definition bblayers.conf is in conf/ of TOPDIR. 354 # By definition bblayers.conf is in conf/ of TOPDIR.
338 # We may have been called with cwd somewhere else so reset TOPDIR 355 # We may have been called with cwd somewhere else so reset TOPDIR
339 data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf))) 356 data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf)))
340 data = parse_config_file(layerconf, data) 357 data = parse_config_file(layerconf, data)
341 358
359 if not data.getVar("BB_CACHEDIR"):
360 data.setVar("BB_CACHEDIR", "${TOPDIR}/cache")
361
362 bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR"))
363
342 layers = (data.getVar('BBLAYERS') or "").split() 364 layers = (data.getVar('BBLAYERS') or "").split()
343 broken_layers = [] 365 broken_layers = []
344 366
367 if not layers:
368 bb.fatal("The bblayers.conf file doesn't contain any BBLAYERS definition")
369
345 data = bb.data.createCopy(data) 370 data = bb.data.createCopy(data)
346 approved = bb.utils.approved_variables() 371 approved = bb.utils.approved_variables()
347 372
@@ -357,8 +382,10 @@ class CookerDataBuilder(object):
357 parselog.critical("Please check BBLAYERS in %s" % (layerconf)) 382 parselog.critical("Please check BBLAYERS in %s" % (layerconf))
358 raise bb.BBHandledException() 383 raise bb.BBHandledException()
359 384
385 layerseries = None
386 compat_entries = {}
360 for layer in layers: 387 for layer in layers:
361 parselog.debug(2, "Adding layer %s", layer) 388 parselog.debug2("Adding layer %s", layer)
362 if 'HOME' in approved and '~' in layer: 389 if 'HOME' in approved and '~' in layer:
363 layer = os.path.expanduser(layer) 390 layer = os.path.expanduser(layer)
364 if layer.endswith('/'): 391 if layer.endswith('/'):
@@ -369,8 +396,27 @@ class CookerDataBuilder(object):
369 data.expandVarref('LAYERDIR') 396 data.expandVarref('LAYERDIR')
370 data.expandVarref('LAYERDIR_RE') 397 data.expandVarref('LAYERDIR_RE')
371 398
399 # Sadly we can't have nice things.
400 # Some layers think they're going to be 'clever' and copy the values from
401 # another layer, e.g. using ${LAYERSERIES_COMPAT_core}. The whole point of
402 # this mechanism is to make it clear which releases a layer supports and
403 # show when a layer master branch is bitrotting and is unmaintained.
404 # We therefore avoid people doing this here.
405 collections = (data.getVar('BBFILE_COLLECTIONS') or "").split()
406 for c in collections:
407 compat_entry = data.getVar("LAYERSERIES_COMPAT_%s" % c)
408 if compat_entry:
409 compat_entries[c] = set(compat_entry.split())
410 data.delVar("LAYERSERIES_COMPAT_%s" % c)
411 if not layerseries:
412 layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split())
413 if layerseries:
414 data.delVar("LAYERSERIES_CORENAMES")
415
372 data.delVar('LAYERDIR_RE') 416 data.delVar('LAYERDIR_RE')
373 data.delVar('LAYERDIR') 417 data.delVar('LAYERDIR')
418 for c in compat_entries:
419 data.setVar("LAYERSERIES_COMPAT_%s" % c, " ".join(sorted(compat_entries[c])))
374 420
375 bbfiles_dynamic = (data.getVar('BBFILES_DYNAMIC') or "").split() 421 bbfiles_dynamic = (data.getVar('BBFILES_DYNAMIC') or "").split()
376 collections = (data.getVar('BBFILE_COLLECTIONS') or "").split() 422 collections = (data.getVar('BBFILE_COLLECTIONS') or "").split()
@@ -389,26 +435,38 @@ class CookerDataBuilder(object):
389 if invalid: 435 if invalid:
390 bb.fatal("BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:\n %s" % "\n ".join(invalid)) 436 bb.fatal("BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:\n %s" % "\n ".join(invalid))
391 437
392 layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split())
393 collections_tmp = collections[:] 438 collections_tmp = collections[:]
394 for c in collections: 439 for c in collections:
395 collections_tmp.remove(c) 440 collections_tmp.remove(c)
396 if c in collections_tmp: 441 if c in collections_tmp:
397 bb.fatal("Found duplicated BBFILE_COLLECTIONS '%s', check bblayers.conf or layer.conf to fix it." % c) 442 bb.fatal("Found duplicated BBFILE_COLLECTIONS '%s', check bblayers.conf or layer.conf to fix it." % c)
398 compat = set((data.getVar("LAYERSERIES_COMPAT_%s" % c) or "").split()) 443
444 compat = set()
445 if c in compat_entries:
446 compat = compat_entries[c]
447 if compat and not layerseries:
448 bb.fatal("No core layer found to work with layer '%s'. Missing entry in bblayers.conf?" % c)
399 if compat and not (compat & layerseries): 449 if compat and not (compat & layerseries):
400 bb.fatal("Layer %s is not compatible with the core layer which only supports these series: %s (layer is compatible with %s)" 450 bb.fatal("Layer %s is not compatible with the core layer which only supports these series: %s (layer is compatible with %s)"
401 % (c, " ".join(layerseries), " ".join(compat))) 451 % (c, " ".join(layerseries), " ".join(compat)))
402 elif not compat and not data.getVar("BB_WORKERCONTEXT"): 452 elif not compat and not data.getVar("BB_WORKERCONTEXT"):
403 bb.warn("Layer %s should set LAYERSERIES_COMPAT_%s in its conf/layer.conf file to list the core layer names it is compatible with." % (c, c)) 453 bb.warn("Layer %s should set LAYERSERIES_COMPAT_%s in its conf/layer.conf file to list the core layer names it is compatible with." % (c, c))
404 454
455 data.setVar("LAYERSERIES_CORENAMES", " ".join(sorted(layerseries)))
456
405 if not data.getVar("BBPATH"): 457 if not data.getVar("BBPATH"):
406 msg = "The BBPATH variable is not set" 458 msg = "The BBPATH variable is not set"
407 if not layerconf: 459 if not layerconf:
408 msg += (" and bitbake did not find a conf/bblayers.conf file in" 460 msg += (" and bitbake did not find a conf/bblayers.conf file in"
409 " the expected location.\nMaybe you accidentally" 461 " the expected location.\nMaybe you accidentally"
410 " invoked bitbake from the wrong directory?") 462 " invoked bitbake from the wrong directory?")
411 raise SystemExit(msg) 463 bb.fatal(msg)
464
465 if not data.getVar("TOPDIR"):
466 data.setVar("TOPDIR", os.path.abspath(os.getcwd()))
467 if not data.getVar("BB_CACHEDIR"):
468 data.setVar("BB_CACHEDIR", "${TOPDIR}/cache")
469 bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR"))
412 470
413 data = parse_config_file(os.path.join("conf", "bitbake.conf"), data) 471 data = parse_config_file(os.path.join("conf", "bitbake.conf"), data)
414 472
@@ -421,7 +479,7 @@ class CookerDataBuilder(object):
421 for bbclass in bbclasses: 479 for bbclass in bbclasses:
422 data = _inherit(bbclass, data) 480 data = _inherit(bbclass, data)
423 481
424 # Nomally we only register event handlers at the end of parsing .bb files 482 # Normally we only register event handlers at the end of parsing .bb files
425 # We register any handlers we've found so far here... 483 # We register any handlers we've found so far here...
426 for var in data.getVar('__BBHANDLERS', False) or []: 484 for var in data.getVar('__BBHANDLERS', False) or []:
427 handlerfn = data.getVarFlag(var, "filename", False) 485 handlerfn = data.getVarFlag(var, "filename", False)
@@ -435,3 +493,54 @@ class CookerDataBuilder(object):
435 493
436 return data 494 return data
437 495
496 @staticmethod
497 def _parse_recipe(bb_data, bbfile, appends, mc, layername):
498 bb_data.setVar("__BBMULTICONFIG", mc)
499 bb_data.setVar("FILE_LAYERNAME", layername)
500
501 bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
502 bb.parse.cached_mtime_noerror(bbfile_loc)
503
504 if appends:
505 bb_data.setVar('__BBAPPEND', " ".join(appends))
506
507 return bb.parse.handle(bbfile, bb_data)
508
509 def parseRecipeVariants(self, bbfile, appends, virtonly=False, mc=None, layername=None):
510 """
511 Load and parse one .bb build file
512 Return the data and whether parsing resulted in the file being skipped
513 """
514
515 if virtonly:
516 (bbfile, virtual, mc) = bb.cache.virtualfn2realfn(bbfile)
517 bb_data = self.mcdata[mc].createCopy()
518 bb_data.setVar("__ONLYFINALISE", virtual or "default")
519 return self._parse_recipe(bb_data, bbfile, appends, mc, layername)
520
521 if mc is not None:
522 bb_data = self.mcdata[mc].createCopy()
523 return self._parse_recipe(bb_data, bbfile, appends, mc, layername)
524
525 bb_data = self.data.createCopy()
526 datastores = self._parse_recipe(bb_data, bbfile, appends, '', layername)
527
528 for mc in self.mcdata:
529 if not mc:
530 continue
531 bb_data = self.mcdata[mc].createCopy()
532 newstores = self._parse_recipe(bb_data, bbfile, appends, mc, layername)
533 for ns in newstores:
534 datastores["mc:%s:%s" % (mc, ns)] = newstores[ns]
535
536 return datastores
537
538 def parseRecipe(self, virtualfn, appends, layername):
539 """
540 Return a complete set of data for fn.
541 To do this, we need to parse the file.
542 """
543 logger.debug("Parsing %s (full)" % virtualfn)
544 (fn, virtual, mc) = bb.cache.virtualfn2realfn(virtualfn)
545 datastores = self.parseRecipeVariants(virtualfn, appends, virtonly=True, layername=layername)
546 return datastores[virtual]