1eb8dc403SDave Cobbley# 2eb8dc403SDave Cobbley# Copyright (C) 2003, 2004 Chris Larson 3eb8dc403SDave Cobbley# Copyright (C) 2003, 2004 Phil Blundell 4eb8dc403SDave Cobbley# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer 5eb8dc403SDave Cobbley# Copyright (C) 2005 Holger Hans Peter Freyther 6eb8dc403SDave Cobbley# Copyright (C) 2005 ROAD GmbH 7eb8dc403SDave Cobbley# Copyright (C) 2006 Richard Purdie 8eb8dc403SDave Cobbley# 9c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only 10eb8dc403SDave Cobbley# 11eb8dc403SDave Cobbley 12eb8dc403SDave Cobbleyimport logging 13eb8dc403SDave Cobbleyimport os 14eb8dc403SDave Cobbleyimport re 15eb8dc403SDave Cobbleyimport sys 1600e122a7SBrad Bishopimport hashlib 17eb8dc403SDave Cobbleyfrom functools import wraps 18eb8dc403SDave Cobbleyimport bb 19eb8dc403SDave Cobbleyfrom bb import data 20eb8dc403SDave Cobbleyimport bb.parse 21eb8dc403SDave Cobbley 22eb8dc403SDave Cobbleylogger = logging.getLogger("BitBake") 23eb8dc403SDave Cobbleyparselog = logging.getLogger("BitBake.Parsing") 24eb8dc403SDave Cobbley 25eb8dc403SDave Cobbleyclass ConfigParameters(object): 266ce62a20SAndrew Geissler def __init__(self, argv=None): 276ce62a20SAndrew Geissler self.options, targets = self.parseCommandLine(argv or sys.argv) 28eb8dc403SDave Cobbley self.environment = self.parseEnvironment() 29eb8dc403SDave Cobbley 30eb8dc403SDave Cobbley self.options.pkgs_to_build = targets or [] 31eb8dc403SDave Cobbley 32eb8dc403SDave Cobbley for key, val in self.options.__dict__.items(): 33eb8dc403SDave Cobbley setattr(self, key, val) 34eb8dc403SDave Cobbley 35eb8dc403SDave Cobbley def parseCommandLine(self, argv=sys.argv): 36eb8dc403SDave Cobbley raise Exception("Caller must implement commandline option parsing") 37eb8dc403SDave Cobbley 38eb8dc403SDave Cobbley def parseEnvironment(self): 39eb8dc403SDave Cobbley return os.environ.copy() 40eb8dc403SDave Cobbley 41eb8dc403SDave Cobbley def updateFromServer(self, server): 42eb8dc403SDave Cobbley if not self.options.cmd: 43eb8dc403SDave Cobbley defaulttask, error = server.runCommand(["getVariable", "BB_DEFAULT_TASK"]) 44eb8dc403SDave Cobbley if error: 45eb8dc403SDave Cobbley raise Exception("Unable to get the value of BB_DEFAULT_TASK from the server: %s" % error) 46eb8dc403SDave Cobbley self.options.cmd = defaulttask or "build" 47eb8dc403SDave Cobbley _, error = server.runCommand(["setConfig", "cmd", self.options.cmd]) 48eb8dc403SDave Cobbley if error: 49eb8dc403SDave Cobbley raise Exception("Unable to set configuration option 'cmd' on the server: %s" % error) 50eb8dc403SDave Cobbley 51eb8dc403SDave Cobbley if not self.options.pkgs_to_build: 52eb8dc403SDave Cobbley bbpkgs, error = server.runCommand(["getVariable", "BBTARGETS"]) 53eb8dc403SDave Cobbley if error: 54eb8dc403SDave Cobbley raise Exception("Unable to get the value of BBTARGETS from the server: %s" % error) 55eb8dc403SDave Cobbley if bbpkgs: 56eb8dc403SDave Cobbley self.options.pkgs_to_build.extend(bbpkgs.split()) 57eb8dc403SDave Cobbley 58eb8dc403SDave Cobbley def updateToServer(self, server, environment): 59eb8dc403SDave Cobbley options = {} 607e0e3c0cSAndrew Geissler for o in ["halt", "force", "invalidate_stamp", 61c9f7865aSAndrew Geissler "dry_run", "dump_signatures", 62c9f7865aSAndrew Geissler "extra_assume_provided", "profile", 63c9f7865aSAndrew Geissler "prefile", "postfile", "server_timeout", 64c9f7865aSAndrew Geissler "nosetscene", "setsceneonly", "skipsetscene", 65c9f7865aSAndrew Geissler "runall", "runonly", "writeeventlog"]: 66eb8dc403SDave Cobbley options[o] = getattr(self.options, o) 67eb8dc403SDave Cobbley 68c9f7865aSAndrew Geissler options['build_verbose_shell'] = self.options.verbose 69c9f7865aSAndrew Geissler options['build_verbose_stdout'] = self.options.verbose 70c9f7865aSAndrew Geissler options['default_loglevel'] = bb.msg.loggerDefaultLogLevel 71c9f7865aSAndrew Geissler options['debug_domains'] = bb.msg.loggerDefaultDomains 72c9f7865aSAndrew Geissler 73eb8dc403SDave Cobbley ret, error = server.runCommand(["updateConfig", options, environment, sys.argv]) 74eb8dc403SDave Cobbley if error: 75eb8dc403SDave Cobbley raise Exception("Unable to update the server configuration with local parameters: %s" % error) 76eb8dc403SDave Cobbley 77eb8dc403SDave Cobbley def parseActions(self): 78eb8dc403SDave Cobbley # Parse any commandline into actions 79eb8dc403SDave Cobbley action = {'action':None, 'msg':None} 80eb8dc403SDave Cobbley if self.options.show_environment: 81eb8dc403SDave Cobbley if 'world' in self.options.pkgs_to_build: 82eb8dc403SDave Cobbley action['msg'] = "'world' is not a valid target for --environment." 83eb8dc403SDave Cobbley elif 'universe' in self.options.pkgs_to_build: 84eb8dc403SDave Cobbley action['msg'] = "'universe' is not a valid target for --environment." 85eb8dc403SDave Cobbley elif len(self.options.pkgs_to_build) > 1: 86eb8dc403SDave Cobbley action['msg'] = "Only one target can be used with the --environment option." 87eb8dc403SDave Cobbley elif self.options.buildfile and len(self.options.pkgs_to_build) > 0: 88eb8dc403SDave Cobbley action['msg'] = "No target should be used with the --environment and --buildfile options." 89595f6308SAndrew Geissler elif self.options.pkgs_to_build: 90eb8dc403SDave Cobbley action['action'] = ["showEnvironmentTarget", self.options.pkgs_to_build] 91eb8dc403SDave Cobbley else: 92eb8dc403SDave Cobbley action['action'] = ["showEnvironment", self.options.buildfile] 93eb8dc403SDave Cobbley elif self.options.buildfile is not None: 94eb8dc403SDave Cobbley action['action'] = ["buildFile", self.options.buildfile, self.options.cmd] 95eb8dc403SDave Cobbley elif self.options.revisions_changed: 96eb8dc403SDave Cobbley action['action'] = ["compareRevisions"] 97eb8dc403SDave Cobbley elif self.options.show_versions: 98eb8dc403SDave Cobbley action['action'] = ["showVersions"] 99eb8dc403SDave Cobbley elif self.options.parse_only: 100eb8dc403SDave Cobbley action['action'] = ["parseFiles"] 101eb8dc403SDave Cobbley elif self.options.dot_graph: 102eb8dc403SDave Cobbley if self.options.pkgs_to_build: 103eb8dc403SDave Cobbley action['action'] = ["generateDotGraph", self.options.pkgs_to_build, self.options.cmd] 104eb8dc403SDave Cobbley else: 105eb8dc403SDave Cobbley action['msg'] = "Please specify a package name for dependency graph generation." 106eb8dc403SDave Cobbley else: 107eb8dc403SDave Cobbley if self.options.pkgs_to_build: 108eb8dc403SDave Cobbley action['action'] = ["buildTargets", self.options.pkgs_to_build, self.options.cmd] 109eb8dc403SDave Cobbley else: 110eb8dc403SDave Cobbley #action['msg'] = "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information." 111eb8dc403SDave Cobbley action = None 112eb8dc403SDave Cobbley self.options.initialaction = action 113eb8dc403SDave Cobbley return action 114eb8dc403SDave Cobbley 115eb8dc403SDave Cobbleyclass CookerConfiguration(object): 116eb8dc403SDave Cobbley """ 117eb8dc403SDave Cobbley Manages build options and configurations for one run 118eb8dc403SDave Cobbley """ 119eb8dc403SDave Cobbley 120eb8dc403SDave Cobbley def __init__(self): 121c9f7865aSAndrew Geissler self.debug_domains = bb.msg.loggerDefaultDomains 122c9f7865aSAndrew Geissler self.default_loglevel = bb.msg.loggerDefaultLogLevel 123eb8dc403SDave Cobbley self.extra_assume_provided = [] 124eb8dc403SDave Cobbley self.prefile = [] 125eb8dc403SDave Cobbley self.postfile = [] 126eb8dc403SDave Cobbley self.cmd = None 1277e0e3c0cSAndrew Geissler self.halt = True 128eb8dc403SDave Cobbley self.force = False 129eb8dc403SDave Cobbley self.profile = False 130eb8dc403SDave Cobbley self.nosetscene = False 131eb8dc403SDave Cobbley self.setsceneonly = False 13296ff1984SBrad Bishop self.skipsetscene = False 133eb8dc403SDave Cobbley self.invalidate_stamp = False 134eb8dc403SDave Cobbley self.dump_signatures = [] 135c9f7865aSAndrew Geissler self.build_verbose_shell = False 136c9f7865aSAndrew Geissler self.build_verbose_stdout = False 137eb8dc403SDave Cobbley self.dry_run = False 138eb8dc403SDave Cobbley self.tracking = False 139eb8dc403SDave Cobbley self.writeeventlog = False 140eb8dc403SDave Cobbley self.limited_deps = False 141eb8dc403SDave Cobbley self.runall = [] 142eb8dc403SDave Cobbley self.runonly = [] 143eb8dc403SDave Cobbley 144eb8dc403SDave Cobbley self.env = {} 145eb8dc403SDave Cobbley 146eb8dc403SDave Cobbley def __getstate__(self): 147eb8dc403SDave Cobbley state = {} 148eb8dc403SDave Cobbley for key in self.__dict__.keys(): 149eb8dc403SDave Cobbley state[key] = getattr(self, key) 150eb8dc403SDave Cobbley return state 151eb8dc403SDave Cobbley 152eb8dc403SDave Cobbley def __setstate__(self,state): 153eb8dc403SDave Cobbley for k in state: 154eb8dc403SDave Cobbley setattr(self, k, state[k]) 155eb8dc403SDave Cobbley 156eb8dc403SDave Cobbley 157eb8dc403SDave Cobbleydef catch_parse_error(func): 158eb8dc403SDave Cobbley """Exception handling bits for our parsing""" 159eb8dc403SDave Cobbley @wraps(func) 160eb8dc403SDave Cobbley def wrapped(fn, *args): 161eb8dc403SDave Cobbley try: 162eb8dc403SDave Cobbley return func(fn, *args) 1636aa7eec5SAndrew Geissler except Exception as exc: 164eb8dc403SDave Cobbley import traceback 165eb8dc403SDave Cobbley 166eb8dc403SDave Cobbley bbdir = os.path.dirname(__file__) + os.sep 167eb8dc403SDave Cobbley exc_class, exc, tb = sys.exc_info() 168eb8dc403SDave Cobbley for tb in iter(lambda: tb.tb_next, None): 169eb8dc403SDave Cobbley # Skip frames in bitbake itself, we only want the metadata 170eb8dc403SDave Cobbley fn, _, _, _ = traceback.extract_tb(tb, 1)[0] 171eb8dc403SDave Cobbley if not fn.startswith(bbdir): 172eb8dc403SDave Cobbley break 173eb8dc403SDave Cobbley parselog.critical("Unable to parse %s" % fn, exc_info=(exc_class, exc, tb)) 174c9f7865aSAndrew Geissler raise bb.BBHandledException() 175eb8dc403SDave Cobbley return wrapped 176eb8dc403SDave Cobbley 177eb8dc403SDave Cobbley@catch_parse_error 178eb8dc403SDave Cobbleydef parse_config_file(fn, data, include=True): 179517393d9SAndrew Geissler return bb.parse.handle(fn, data, include, baseconfig=True) 180eb8dc403SDave Cobbley 181eb8dc403SDave Cobbley@catch_parse_error 182eb8dc403SDave Cobbleydef _inherit(bbclass, data): 183eb8dc403SDave Cobbley bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data) 184eb8dc403SDave Cobbley return data 185eb8dc403SDave Cobbley 186eb8dc403SDave Cobbleydef findConfigFile(configfile, data): 187eb8dc403SDave Cobbley search = [] 188eb8dc403SDave Cobbley bbpath = data.getVar("BBPATH") 189eb8dc403SDave Cobbley if bbpath: 190eb8dc403SDave Cobbley for i in bbpath.split(":"): 191eb8dc403SDave Cobbley search.append(os.path.join(i, "conf", configfile)) 192eb8dc403SDave Cobbley path = os.getcwd() 193eb8dc403SDave Cobbley while path != "/": 194eb8dc403SDave Cobbley search.append(os.path.join(path, "conf", configfile)) 195eb8dc403SDave Cobbley path, _ = os.path.split(path) 196eb8dc403SDave Cobbley 197eb8dc403SDave Cobbley for i in search: 198eb8dc403SDave Cobbley if os.path.exists(i): 199eb8dc403SDave Cobbley return i 200eb8dc403SDave Cobbley 201eb8dc403SDave Cobbley return None 202eb8dc403SDave Cobbley 203eb8dc403SDave Cobbley# 204eb8dc403SDave Cobbley# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working 205595f6308SAndrew Geissler# up to /. If that fails, bitbake would fall back to cwd. 206eb8dc403SDave Cobbley# 207eb8dc403SDave Cobbley 208eb8dc403SDave Cobbleydef findTopdir(): 209eb8dc403SDave Cobbley d = bb.data.init() 210eb8dc403SDave Cobbley bbpath = None 211eb8dc403SDave Cobbley if 'BBPATH' in os.environ: 212eb8dc403SDave Cobbley bbpath = os.environ['BBPATH'] 213eb8dc403SDave Cobbley d.setVar('BBPATH', bbpath) 214eb8dc403SDave Cobbley 215eb8dc403SDave Cobbley layerconf = findConfigFile("bblayers.conf", d) 216eb8dc403SDave Cobbley if layerconf: 217eb8dc403SDave Cobbley return os.path.dirname(os.path.dirname(layerconf)) 218595f6308SAndrew Geissler 219595f6308SAndrew Geissler return os.path.abspath(os.getcwd()) 220eb8dc403SDave Cobbley 221eb8dc403SDave Cobbleyclass CookerDataBuilder(object): 222eb8dc403SDave Cobbley 223eb8dc403SDave Cobbley def __init__(self, cookercfg, worker = False): 224eb8dc403SDave Cobbley 225eb8dc403SDave Cobbley self.prefiles = cookercfg.prefile 226eb8dc403SDave Cobbley self.postfiles = cookercfg.postfile 227eb8dc403SDave Cobbley self.tracking = cookercfg.tracking 228eb8dc403SDave Cobbley 229eb8dc403SDave Cobbley bb.utils.set_context(bb.utils.clean_context()) 230eb8dc403SDave Cobbley bb.event.set_class_handlers(bb.event.clean_class_handlers()) 231eb8dc403SDave Cobbley self.basedata = bb.data.init() 232eb8dc403SDave Cobbley if self.tracking: 233eb8dc403SDave Cobbley self.basedata.enableTracking() 234eb8dc403SDave Cobbley 235eb8dc403SDave Cobbley # Keep a datastore of the initial environment variables and their 236eb8dc403SDave Cobbley # values from when BitBake was launched to enable child processes 237eb8dc403SDave Cobbley # to use environment variables which have been cleaned from the 238eb8dc403SDave Cobbley # BitBake processes env 239eb8dc403SDave Cobbley self.savedenv = bb.data.init() 240eb8dc403SDave Cobbley for k in cookercfg.env: 241eb8dc403SDave Cobbley self.savedenv.setVar(k, cookercfg.env[k]) 2427e0e3c0cSAndrew Geissler if k in bb.data_smart.bitbake_renamed_vars: 243d583833aSAndrew Geissler bb.error('Shell environment variable %s has been renamed to %s' % (k, bb.data_smart.bitbake_renamed_vars[k])) 2447e0e3c0cSAndrew Geissler bb.fatal("Exiting to allow enviroment variables to be corrected") 245eb8dc403SDave Cobbley 246eb8dc403SDave Cobbley filtered_keys = bb.utils.approved_variables() 247eb8dc403SDave Cobbley bb.data.inheritFromOS(self.basedata, self.savedenv, filtered_keys) 248eb8dc403SDave Cobbley self.basedata.setVar("BB_ORIGENV", self.savedenv) 24992b42cb3SPatrick Williams self.basedata.setVar("__bbclasstype", "global") 250eb8dc403SDave Cobbley 251eb8dc403SDave Cobbley if worker: 252eb8dc403SDave Cobbley self.basedata.setVar("BB_WORKERCONTEXT", "1") 253eb8dc403SDave Cobbley 254eb8dc403SDave Cobbley self.data = self.basedata 255eb8dc403SDave Cobbley self.mcdata = {} 256eb8dc403SDave Cobbley 2577e0e3c0cSAndrew Geissler def parseBaseConfiguration(self, worker=False): 258517393d9SAndrew Geissler mcdata = {} 25900e122a7SBrad Bishop data_hash = hashlib.sha256() 260eb8dc403SDave Cobbley try: 261eb8dc403SDave Cobbley self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles) 262eb8dc403SDave Cobbley 2637e0e3c0cSAndrew Geissler if self.data.getVar("BB_WORKERCONTEXT", False) is None and not worker: 264eb8dc403SDave Cobbley bb.fetch.fetcher_init(self.data) 265c68388fcSBrad Bishop bb.parse.init_parser(self.data) 266eb8dc403SDave Cobbley 267eb8dc403SDave Cobbley bb.event.fire(bb.event.ConfigParsed(), self.data) 268eb8dc403SDave Cobbley 269eb8dc403SDave Cobbley reparse_cnt = 0 270eb8dc403SDave Cobbley while self.data.getVar("BB_INVALIDCONF", False) is True: 271eb8dc403SDave Cobbley if reparse_cnt > 20: 272eb8dc403SDave Cobbley logger.error("Configuration has been re-parsed over 20 times, " 273eb8dc403SDave Cobbley "breaking out of the loop...") 274eb8dc403SDave Cobbley raise Exception("Too deep config re-parse loop. Check locations where " 275eb8dc403SDave Cobbley "BB_INVALIDCONF is being set (ConfigParsed event handlers)") 276eb8dc403SDave Cobbley self.data.setVar("BB_INVALIDCONF", False) 277eb8dc403SDave Cobbley self.data = self.parseConfigurationFiles(self.prefiles, self.postfiles) 278eb8dc403SDave Cobbley reparse_cnt += 1 279eb8dc403SDave Cobbley bb.event.fire(bb.event.ConfigParsed(), self.data) 280eb8dc403SDave Cobbley 281eb8dc403SDave Cobbley bb.parse.init_parser(self.data) 28200e122a7SBrad Bishop data_hash.update(self.data.get_hash().encode('utf-8')) 283517393d9SAndrew Geissler mcdata[''] = self.data 284eb8dc403SDave Cobbley 285eb8dc403SDave Cobbley multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split() 286eb8dc403SDave Cobbley for config in multiconfig: 2875199d831SAndrew Geissler if config[0].isdigit(): 2885199d831SAndrew Geissler bb.fatal("Multiconfig name '%s' is invalid as multiconfigs cannot start with a digit" % config) 289517393d9SAndrew Geissler parsed_mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config) 290517393d9SAndrew Geissler bb.event.fire(bb.event.ConfigParsed(), parsed_mcdata) 291517393d9SAndrew Geissler mcdata[config] = parsed_mcdata 292517393d9SAndrew Geissler data_hash.update(parsed_mcdata.get_hash().encode('utf-8')) 293eb8dc403SDave Cobbley if multiconfig: 294517393d9SAndrew Geissler bb.event.fire(bb.event.MultiConfigParsed(mcdata), self.data) 295eb8dc403SDave Cobbley 29600e122a7SBrad Bishop self.data_hash = data_hash.hexdigest() 297eb8dc403SDave Cobbley except bb.data_smart.ExpansionError as e: 298eb8dc403SDave Cobbley logger.error(str(e)) 299c9f7865aSAndrew Geissler raise bb.BBHandledException() 300eb8dc403SDave Cobbley 301517393d9SAndrew Geissler bb.codeparser.update_module_dependencies(self.data) 3027e0e3c0cSAndrew Geissler 3037e0e3c0cSAndrew Geissler # Handle obsolete variable names 3047e0e3c0cSAndrew Geissler d = self.data 3057e0e3c0cSAndrew Geissler renamedvars = d.getVarFlags('BB_RENAMED_VARIABLES') or {} 3067e0e3c0cSAndrew Geissler renamedvars.update(bb.data_smart.bitbake_renamed_vars) 3077e0e3c0cSAndrew Geissler issues = False 3087e0e3c0cSAndrew Geissler for v in renamedvars: 3097e0e3c0cSAndrew Geissler if d.getVar(v) != None or d.hasOverrides(v): 3107e0e3c0cSAndrew Geissler issues = True 3117e0e3c0cSAndrew Geissler loginfo = {} 3127e0e3c0cSAndrew Geissler history = d.varhistory.get_variable_refs(v) 3137e0e3c0cSAndrew Geissler for h in history: 3147e0e3c0cSAndrew Geissler for line in history[h]: 3157e0e3c0cSAndrew Geissler loginfo = {'file' : h, 'line' : line} 3167e0e3c0cSAndrew Geissler bb.data.data_smart._print_rename_error(v, loginfo, renamedvars) 3177e0e3c0cSAndrew Geissler if not history: 3187e0e3c0cSAndrew Geissler bb.data.data_smart._print_rename_error(v, loginfo, renamedvars) 3197e0e3c0cSAndrew Geissler if issues: 3207e0e3c0cSAndrew Geissler raise bb.BBHandledException() 3217e0e3c0cSAndrew Geissler 322517393d9SAndrew Geissler for mc in mcdata: 323517393d9SAndrew Geissler mcdata[mc].renameVar("__depends", "__base_depends") 324517393d9SAndrew Geissler mcdata[mc].setVar("__bbclasstype", "recipe") 325517393d9SAndrew Geissler 326eb8dc403SDave Cobbley # Create a copy so we can reset at a later date when UIs disconnect 327517393d9SAndrew Geissler self.mcorigdata = mcdata 328517393d9SAndrew Geissler for mc in mcdata: 329517393d9SAndrew Geissler self.mcdata[mc] = bb.data.createCopy(mcdata[mc]) 330517393d9SAndrew Geissler self.data = self.mcdata[''] 331eb8dc403SDave Cobbley 332eb8dc403SDave Cobbley def reset(self): 333eb8dc403SDave Cobbley # We may not have run parseBaseConfiguration() yet 334517393d9SAndrew Geissler if not hasattr(self, 'mcorigdata'): 335eb8dc403SDave Cobbley return 336517393d9SAndrew Geissler for mc in self.mcorigdata: 337517393d9SAndrew Geissler self.mcdata[mc] = bb.data.createCopy(self.mcorigdata[mc]) 338517393d9SAndrew Geissler self.data = self.mcdata[''] 339eb8dc403SDave Cobbley 340eb8dc403SDave Cobbley def _findLayerConf(self, data): 341eb8dc403SDave Cobbley return findConfigFile("bblayers.conf", data) 342eb8dc403SDave Cobbley 343eb8dc403SDave Cobbley def parseConfigurationFiles(self, prefiles, postfiles, mc = "default"): 344eb8dc403SDave Cobbley data = bb.data.createCopy(self.basedata) 345eb8dc403SDave Cobbley data.setVar("BB_CURRENT_MC", mc) 346eb8dc403SDave Cobbley 347eb8dc403SDave Cobbley # Parse files for loading *before* bitbake.conf and any includes 348eb8dc403SDave Cobbley for f in prefiles: 349eb8dc403SDave Cobbley data = parse_config_file(f, data) 350eb8dc403SDave Cobbley 351eb8dc403SDave Cobbley layerconf = self._findLayerConf(data) 352eb8dc403SDave Cobbley if layerconf: 35387f5cff0SAndrew Geissler parselog.debug2("Found bblayers.conf (%s)", layerconf) 354eb8dc403SDave Cobbley # By definition bblayers.conf is in conf/ of TOPDIR. 355eb8dc403SDave Cobbley # We may have been called with cwd somewhere else so reset TOPDIR 356eb8dc403SDave Cobbley data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf))) 357eb8dc403SDave Cobbley data = parse_config_file(layerconf, data) 358eb8dc403SDave Cobbley 359c5535c91SAndrew Geissler if not data.getVar("BB_CACHEDIR"): 360c5535c91SAndrew Geissler data.setVar("BB_CACHEDIR", "${TOPDIR}/cache") 361c5535c91SAndrew Geissler 362c5535c91SAndrew Geissler bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR")) 363c5535c91SAndrew Geissler 364eb8dc403SDave Cobbley layers = (data.getVar('BBLAYERS') or "").split() 36515ae2509SBrad Bishop broken_layers = [] 366eb8dc403SDave Cobbley 3675199d831SAndrew Geissler if not layers: 3685199d831SAndrew Geissler bb.fatal("The bblayers.conf file doesn't contain any BBLAYERS definition") 3695199d831SAndrew Geissler 370eb8dc403SDave Cobbley data = bb.data.createCopy(data) 371eb8dc403SDave Cobbley approved = bb.utils.approved_variables() 37215ae2509SBrad Bishop 37315ae2509SBrad Bishop # Check whether present layer directories exist 374eb8dc403SDave Cobbley for layer in layers: 375eb8dc403SDave Cobbley if not os.path.isdir(layer): 37615ae2509SBrad Bishop broken_layers.append(layer) 37715ae2509SBrad Bishop 37815ae2509SBrad Bishop if broken_layers: 37915ae2509SBrad Bishop parselog.critical("The following layer directories do not exist:") 38015ae2509SBrad Bishop for layer in broken_layers: 38115ae2509SBrad Bishop parselog.critical(" %s", layer) 38215ae2509SBrad Bishop parselog.critical("Please check BBLAYERS in %s" % (layerconf)) 383c9f7865aSAndrew Geissler raise bb.BBHandledException() 38415ae2509SBrad Bishop 385517393d9SAndrew Geissler layerseries = None 386517393d9SAndrew Geissler compat_entries = {} 38715ae2509SBrad Bishop for layer in layers: 38887f5cff0SAndrew Geissler parselog.debug2("Adding layer %s", layer) 389eb8dc403SDave Cobbley if 'HOME' in approved and '~' in layer: 390eb8dc403SDave Cobbley layer = os.path.expanduser(layer) 391eb8dc403SDave Cobbley if layer.endswith('/'): 392eb8dc403SDave Cobbley layer = layer.rstrip('/') 393eb8dc403SDave Cobbley data.setVar('LAYERDIR', layer) 394eb8dc403SDave Cobbley data.setVar('LAYERDIR_RE', re.escape(layer)) 395eb8dc403SDave Cobbley data = parse_config_file(os.path.join(layer, "conf", "layer.conf"), data) 396eb8dc403SDave Cobbley data.expandVarref('LAYERDIR') 397eb8dc403SDave Cobbley data.expandVarref('LAYERDIR_RE') 398eb8dc403SDave Cobbley 399517393d9SAndrew Geissler # Sadly we can't have nice things. 400517393d9SAndrew Geissler # Some layers think they're going to be 'clever' and copy the values from 401517393d9SAndrew Geissler # another layer, e.g. using ${LAYERSERIES_COMPAT_core}. The whole point of 402517393d9SAndrew Geissler # this mechanism is to make it clear which releases a layer supports and 403517393d9SAndrew Geissler # show when a layer master branch is bitrotting and is unmaintained. 404517393d9SAndrew Geissler # We therefore avoid people doing this here. 405517393d9SAndrew Geissler collections = (data.getVar('BBFILE_COLLECTIONS') or "").split() 406517393d9SAndrew Geissler for c in collections: 407517393d9SAndrew Geissler compat_entry = data.getVar("LAYERSERIES_COMPAT_%s" % c) 408517393d9SAndrew Geissler if compat_entry: 409517393d9SAndrew Geissler compat_entries[c] = set(compat_entry.split()) 410517393d9SAndrew Geissler data.delVar("LAYERSERIES_COMPAT_%s" % c) 411517393d9SAndrew Geissler if not layerseries: 412517393d9SAndrew Geissler layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split()) 413517393d9SAndrew Geissler if layerseries: 414517393d9SAndrew Geissler data.delVar("LAYERSERIES_CORENAMES") 415517393d9SAndrew Geissler 416eb8dc403SDave Cobbley data.delVar('LAYERDIR_RE') 417eb8dc403SDave Cobbley data.delVar('LAYERDIR') 418517393d9SAndrew Geissler for c in compat_entries: 419517393d9SAndrew Geissler data.setVar("LAYERSERIES_COMPAT_%s" % c, " ".join(sorted(compat_entries[c]))) 420eb8dc403SDave Cobbley 421eb8dc403SDave Cobbley bbfiles_dynamic = (data.getVar('BBFILES_DYNAMIC') or "").split() 422eb8dc403SDave Cobbley collections = (data.getVar('BBFILE_COLLECTIONS') or "").split() 423eb8dc403SDave Cobbley invalid = [] 424eb8dc403SDave Cobbley for entry in bbfiles_dynamic: 425eb8dc403SDave Cobbley parts = entry.split(":", 1) 426eb8dc403SDave Cobbley if len(parts) != 2: 427eb8dc403SDave Cobbley invalid.append(entry) 428eb8dc403SDave Cobbley continue 429eb8dc403SDave Cobbley l, f = parts 430d25ed324SAndrew Geissler invert = l[0] == "!" 431d25ed324SAndrew Geissler if invert: 432d25ed324SAndrew Geissler l = l[1:] 433d25ed324SAndrew Geissler if (l in collections and not invert) or (l not in collections and invert): 434eb8dc403SDave Cobbley data.appendVar("BBFILES", " " + f) 435eb8dc403SDave Cobbley if invalid: 436d25ed324SAndrew Geissler bb.fatal("BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:\n %s" % "\n ".join(invalid)) 437eb8dc403SDave Cobbley 43819323693SBrad Bishop collections_tmp = collections[:] 439eb8dc403SDave Cobbley for c in collections: 44019323693SBrad Bishop collections_tmp.remove(c) 44119323693SBrad Bishop if c in collections_tmp: 44219323693SBrad Bishop bb.fatal("Found duplicated BBFILE_COLLECTIONS '%s', check bblayers.conf or layer.conf to fix it." % c) 443517393d9SAndrew Geissler 444517393d9SAndrew Geissler compat = set() 445517393d9SAndrew Geissler if c in compat_entries: 446517393d9SAndrew Geissler compat = compat_entries[c] 4475199d831SAndrew Geissler if compat and not layerseries: 4485199d831SAndrew Geissler bb.fatal("No core layer found to work with layer '%s'. Missing entry in bblayers.conf?" % c) 449eb8dc403SDave Cobbley if compat and not (compat & layerseries): 450eb8dc403SDave Cobbley bb.fatal("Layer %s is not compatible with the core layer which only supports these series: %s (layer is compatible with %s)" 451eb8dc403SDave Cobbley % (c, " ".join(layerseries), " ".join(compat))) 452eb8dc403SDave Cobbley elif not compat and not data.getVar("BB_WORKERCONTEXT"): 453eb8dc403SDave Cobbley 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)) 454eb8dc403SDave Cobbley 455517393d9SAndrew Geissler data.setVar("LAYERSERIES_CORENAMES", " ".join(sorted(layerseries))) 456517393d9SAndrew Geissler 457eb8dc403SDave Cobbley if not data.getVar("BBPATH"): 458eb8dc403SDave Cobbley msg = "The BBPATH variable is not set" 459eb8dc403SDave Cobbley if not layerconf: 460eb8dc403SDave Cobbley msg += (" and bitbake did not find a conf/bblayers.conf file in" 461eb8dc403SDave Cobbley " the expected location.\nMaybe you accidentally" 462eb8dc403SDave Cobbley " invoked bitbake from the wrong directory?") 4636aa7eec5SAndrew Geissler bb.fatal(msg) 464eb8dc403SDave Cobbley 465595f6308SAndrew Geissler if not data.getVar("TOPDIR"): 466595f6308SAndrew Geissler data.setVar("TOPDIR", os.path.abspath(os.getcwd())) 467c5535c91SAndrew Geissler if not data.getVar("BB_CACHEDIR"): 468c5535c91SAndrew Geissler data.setVar("BB_CACHEDIR", "${TOPDIR}/cache") 469c5535c91SAndrew Geissler bb.codeparser.parser_cache_init(data.getVar("BB_CACHEDIR")) 470595f6308SAndrew Geissler 471eb8dc403SDave Cobbley data = parse_config_file(os.path.join("conf", "bitbake.conf"), data) 472eb8dc403SDave Cobbley 473eb8dc403SDave Cobbley # Parse files for loading *after* bitbake.conf and any includes 474eb8dc403SDave Cobbley for p in postfiles: 475eb8dc403SDave Cobbley data = parse_config_file(p, data) 476eb8dc403SDave Cobbley 477eb8dc403SDave Cobbley # Handle any INHERITs and inherit the base class 478eb8dc403SDave Cobbley bbclasses = ["base"] + (data.getVar('INHERIT') or "").split() 479eb8dc403SDave Cobbley for bbclass in bbclasses: 480eb8dc403SDave Cobbley data = _inherit(bbclass, data) 481eb8dc403SDave Cobbley 4827e0e3c0cSAndrew Geissler # Normally we only register event handlers at the end of parsing .bb files 483eb8dc403SDave Cobbley # We register any handlers we've found so far here... 484eb8dc403SDave Cobbley for var in data.getVar('__BBHANDLERS', False) or []: 485eb8dc403SDave Cobbley handlerfn = data.getVarFlag(var, "filename", False) 486eb8dc403SDave Cobbley if not handlerfn: 487eb8dc403SDave Cobbley parselog.critical("Undefined event handler function '%s'" % var) 488c9f7865aSAndrew Geissler raise bb.BBHandledException() 489eb8dc403SDave Cobbley handlerln = int(data.getVarFlag(var, "lineno", False)) 4909b4d8b0eSAndrew Geissler bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data) 491eb8dc403SDave Cobbley 492eb8dc403SDave Cobbley data.setVar('BBINCLUDED',bb.parse.get_file_depends(data)) 493eb8dc403SDave Cobbley 494eb8dc403SDave Cobbley return data 495eb8dc403SDave Cobbley 496517393d9SAndrew Geissler @staticmethod 497e760df85SPatrick Williams def _parse_recipe(bb_data, bbfile, appends, mc, layername): 498517393d9SAndrew Geissler bb_data.setVar("__BBMULTICONFIG", mc) 499e760df85SPatrick Williams bb_data.setVar("FILE_LAYERNAME", layername) 500517393d9SAndrew Geissler 501517393d9SAndrew Geissler bbfile_loc = os.path.abspath(os.path.dirname(bbfile)) 502517393d9SAndrew Geissler bb.parse.cached_mtime_noerror(bbfile_loc) 503517393d9SAndrew Geissler 504517393d9SAndrew Geissler if appends: 505517393d9SAndrew Geissler bb_data.setVar('__BBAPPEND', " ".join(appends)) 506*ac13d5f3SPatrick Williams 507*ac13d5f3SPatrick Williams return bb.parse.handle(bbfile, bb_data) 508517393d9SAndrew Geissler 509e760df85SPatrick Williams def parseRecipeVariants(self, bbfile, appends, virtonly=False, mc=None, layername=None): 510517393d9SAndrew Geissler """ 511517393d9SAndrew Geissler Load and parse one .bb build file 512517393d9SAndrew Geissler Return the data and whether parsing resulted in the file being skipped 513517393d9SAndrew Geissler """ 514517393d9SAndrew Geissler 515517393d9SAndrew Geissler if virtonly: 516517393d9SAndrew Geissler (bbfile, virtual, mc) = bb.cache.virtualfn2realfn(bbfile) 517517393d9SAndrew Geissler bb_data = self.mcdata[mc].createCopy() 518517393d9SAndrew Geissler bb_data.setVar("__ONLYFINALISE", virtual or "default") 519*ac13d5f3SPatrick Williams return self._parse_recipe(bb_data, bbfile, appends, mc, layername) 520517393d9SAndrew Geissler 521517393d9SAndrew Geissler if mc is not None: 522517393d9SAndrew Geissler bb_data = self.mcdata[mc].createCopy() 523e760df85SPatrick Williams return self._parse_recipe(bb_data, bbfile, appends, mc, layername) 524517393d9SAndrew Geissler 525517393d9SAndrew Geissler bb_data = self.data.createCopy() 526e760df85SPatrick Williams datastores = self._parse_recipe(bb_data, bbfile, appends, '', layername) 527517393d9SAndrew Geissler 528517393d9SAndrew Geissler for mc in self.mcdata: 529517393d9SAndrew Geissler if not mc: 530517393d9SAndrew Geissler continue 531517393d9SAndrew Geissler bb_data = self.mcdata[mc].createCopy() 532e760df85SPatrick Williams newstores = self._parse_recipe(bb_data, bbfile, appends, mc, layername) 533517393d9SAndrew Geissler for ns in newstores: 534517393d9SAndrew Geissler datastores["mc:%s:%s" % (mc, ns)] = newstores[ns] 535517393d9SAndrew Geissler 536517393d9SAndrew Geissler return datastores 537517393d9SAndrew Geissler 538e760df85SPatrick Williams def parseRecipe(self, virtualfn, appends, layername): 539517393d9SAndrew Geissler """ 540517393d9SAndrew Geissler Return a complete set of data for fn. 541517393d9SAndrew Geissler To do this, we need to parse the file. 542517393d9SAndrew Geissler """ 543517393d9SAndrew Geissler logger.debug("Parsing %s (full)" % virtualfn) 544517393d9SAndrew Geissler (fn, virtual, mc) = bb.cache.virtualfn2realfn(virtualfn) 545*ac13d5f3SPatrick Williams datastores = self.parseRecipeVariants(virtualfn, appends, virtonly=True, layername=layername) 546*ac13d5f3SPatrick Williams return datastores[virtual] 547