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 os 13eb8dc403SDave Cobbleyimport sys 14eb8dc403SDave Cobbleyimport logging 15517393d9SAndrew Geisslerimport argparse 16eb8dc403SDave Cobbleyimport warnings 17eb8dc403SDave Cobbleyimport fcntl 18eb8dc403SDave Cobbleyimport time 19eb8dc403SDave Cobbleyimport traceback 20517393d9SAndrew Geisslerimport datetime 21eb8dc403SDave Cobbley 22eb8dc403SDave Cobbleyimport bb 23eb8dc403SDave Cobbleyfrom bb import event 24eb8dc403SDave Cobbleyimport bb.msg 25eb8dc403SDave Cobbleyfrom bb import cooker 26eb8dc403SDave Cobbleyfrom bb import ui 27eb8dc403SDave Cobbleyfrom bb import server 28eb8dc403SDave Cobbleyfrom bb import cookerdata 29eb8dc403SDave Cobbley 30eb8dc403SDave Cobbleyimport bb.server.process 31eb8dc403SDave Cobbleyimport bb.server.xmlrpcclient 32eb8dc403SDave Cobbley 33eb8dc403SDave Cobbleylogger = logging.getLogger("BitBake") 34eb8dc403SDave Cobbley 35eb8dc403SDave Cobbleyclass BBMainException(Exception): 36eb8dc403SDave Cobbley pass 37eb8dc403SDave Cobbley 38eb8dc403SDave Cobbleyclass BBMainFatal(bb.BBHandledException): 39eb8dc403SDave Cobbley pass 40eb8dc403SDave Cobbley 41eb8dc403SDave Cobbleydef present_options(optionlist): 42eb8dc403SDave Cobbley if len(optionlist) > 1: 43eb8dc403SDave Cobbley return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]]) 44eb8dc403SDave Cobbley else: 45eb8dc403SDave Cobbley return optionlist[0] 46eb8dc403SDave Cobbley 47517393d9SAndrew Geisslerclass BitbakeHelpFormatter(argparse.HelpFormatter): 48517393d9SAndrew Geissler def _get_help_string(self, action): 49eb8dc403SDave Cobbley # We need to do this here rather than in the text we supply to 50eb8dc403SDave Cobbley # add_option() because we don't want to call list_extension_modules() 51eb8dc403SDave Cobbley # on every execution (since it imports all of the modules) 52eb8dc403SDave Cobbley # Note also that we modify option.help rather than the returned text 53eb8dc403SDave Cobbley # - this is so that we don't have to re-format the text ourselves 54517393d9SAndrew Geissler if action.dest == 'ui': 55eb8dc403SDave Cobbley valid_uis = list_extension_modules(bb.ui, 'main') 56517393d9SAndrew Geissler return action.help.replace('@CHOICES@', present_options(valid_uis)) 57eb8dc403SDave Cobbley 58517393d9SAndrew Geissler return action.help 59eb8dc403SDave Cobbley 60eb8dc403SDave Cobbleydef list_extension_modules(pkg, checkattr): 61eb8dc403SDave Cobbley """ 62eb8dc403SDave Cobbley Lists extension modules in a specific Python package 63eb8dc403SDave Cobbley (e.g. UIs, servers). NOTE: Calling this function will import all of the 64eb8dc403SDave Cobbley submodules of the specified module in order to check for the specified 65eb8dc403SDave Cobbley attribute; this can have unusual side-effects. As a result, this should 66eb8dc403SDave Cobbley only be called when displaying help text or error messages. 67eb8dc403SDave Cobbley Parameters: 68eb8dc403SDave Cobbley pkg: previously imported Python package to list 69eb8dc403SDave Cobbley checkattr: attribute to look for in module to determine if it's valid 70eb8dc403SDave Cobbley as the type of extension you are looking for 71eb8dc403SDave Cobbley """ 72eb8dc403SDave Cobbley import pkgutil 73eb8dc403SDave Cobbley pkgdir = os.path.dirname(pkg.__file__) 74eb8dc403SDave Cobbley 75eb8dc403SDave Cobbley modules = [] 76eb8dc403SDave Cobbley for _, modulename, _ in pkgutil.iter_modules([pkgdir]): 77eb8dc403SDave Cobbley if os.path.isdir(os.path.join(pkgdir, modulename)): 78eb8dc403SDave Cobbley # ignore directories 79eb8dc403SDave Cobbley continue 80eb8dc403SDave Cobbley try: 81eb8dc403SDave Cobbley module = __import__(pkg.__name__, fromlist=[modulename]) 82eb8dc403SDave Cobbley except: 83eb8dc403SDave Cobbley # If we can't import it, it's not valid 84eb8dc403SDave Cobbley continue 85eb8dc403SDave Cobbley module_if = getattr(module, modulename) 86eb8dc403SDave Cobbley if getattr(module_if, 'hidden_extension', False): 87eb8dc403SDave Cobbley continue 88eb8dc403SDave Cobbley if not checkattr or hasattr(module_if, checkattr): 89eb8dc403SDave Cobbley modules.append(modulename) 90eb8dc403SDave Cobbley return modules 91eb8dc403SDave Cobbley 92eb8dc403SDave Cobbleydef import_extension_module(pkg, modulename, checkattr): 93eb8dc403SDave Cobbley try: 94eb8dc403SDave Cobbley # Dynamically load the UI based on the ui name. Although we 95eb8dc403SDave Cobbley # suggest a fixed set this allows you to have flexibility in which 96eb8dc403SDave Cobbley # ones are available. 97eb8dc403SDave Cobbley module = __import__(pkg.__name__, fromlist=[modulename]) 98eb8dc403SDave Cobbley return getattr(module, modulename) 99eb8dc403SDave Cobbley except AttributeError: 100eb8dc403SDave Cobbley modules = present_options(list_extension_modules(pkg, checkattr)) 101eb8dc403SDave Cobbley raise BBMainException('FATAL: Unable to import extension module "%s" from %s. ' 102eb8dc403SDave Cobbley 'Valid extension modules: %s' % (modulename, pkg.__name__, modules)) 103eb8dc403SDave Cobbley 104eb8dc403SDave Cobbley# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others""" 105eb8dc403SDave Cobbleywarnlog = logging.getLogger("BitBake.Warnings") 106eb8dc403SDave Cobbley_warnings_showwarning = warnings.showwarning 107eb8dc403SDave Cobbleydef _showwarning(message, category, filename, lineno, file=None, line=None): 108eb8dc403SDave Cobbley if file is not None: 109eb8dc403SDave Cobbley if _warnings_showwarning is not None: 110eb8dc403SDave Cobbley _warnings_showwarning(message, category, filename, lineno, file, line) 111eb8dc403SDave Cobbley else: 112eb8dc403SDave Cobbley s = warnings.formatwarning(message, category, filename, lineno) 113eb8dc403SDave Cobbley warnlog.warning(s) 114eb8dc403SDave Cobbley 115eb8dc403SDave Cobbleywarnings.showwarning = _showwarning 116eb8dc403SDave Cobbley 1176ce62a20SAndrew Geisslerdef create_bitbake_parser(): 118517393d9SAndrew Geissler parser = argparse.ArgumentParser( 119517393d9SAndrew Geissler description="""\ 120eb8dc403SDave Cobbley It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which 121517393d9SAndrew Geissler will provide the layer, BBFILES and other configuration information. 122517393d9SAndrew Geissler """, 123517393d9SAndrew Geissler formatter_class=BitbakeHelpFormatter, 124517393d9SAndrew Geissler allow_abbrev=False, 125517393d9SAndrew Geissler add_help=False, # help is manually added below in a specific argument group 126517393d9SAndrew Geissler ) 127eb8dc403SDave Cobbley 128517393d9SAndrew Geissler general_group = parser.add_argument_group('General options') 129517393d9SAndrew Geissler task_group = parser.add_argument_group('Task control options') 130517393d9SAndrew Geissler exec_group = parser.add_argument_group('Execution control options') 131517393d9SAndrew Geissler logging_group = parser.add_argument_group('Logging/output control options') 132517393d9SAndrew Geissler server_group = parser.add_argument_group('Server options') 133517393d9SAndrew Geissler config_group = parser.add_argument_group('Configuration options') 134eb8dc403SDave Cobbley 135517393d9SAndrew Geissler general_group.add_argument("targets", nargs="*", metavar="recipename/target", 136517393d9SAndrew Geissler help="Execute the specified task (default is 'build') for these target " 137517393d9SAndrew Geissler "recipes (.bb files).") 138eb8dc403SDave Cobbley 139517393d9SAndrew Geissler general_group.add_argument("-s", "--show-versions", action="store_true", 140517393d9SAndrew Geissler help="Show current and preferred versions of all recipes.") 141517393d9SAndrew Geissler 142517393d9SAndrew Geissler general_group.add_argument("-e", "--environment", action="store_true", 143517393d9SAndrew Geissler dest="show_environment", 144517393d9SAndrew Geissler help="Show the global or per-recipe environment complete with information" 145517393d9SAndrew Geissler " about where variables were set/changed.") 146517393d9SAndrew Geissler 147517393d9SAndrew Geissler general_group.add_argument("-g", "--graphviz", action="store_true", dest="dot_graph", 148517393d9SAndrew Geissler help="Save dependency tree information for the specified " 149517393d9SAndrew Geissler "targets in the dot syntax.") 150517393d9SAndrew Geissler 151517393d9SAndrew Geissler # @CHOICES@ is substituted out by BitbakeHelpFormatter above 152517393d9SAndrew Geissler general_group.add_argument("-u", "--ui", 153517393d9SAndrew Geissler default=os.environ.get('BITBAKE_UI', 'knotty'), 154517393d9SAndrew Geissler help="The user interface to use (@CHOICES@ - default %(default)s).") 155517393d9SAndrew Geissler 156517393d9SAndrew Geissler general_group.add_argument("--version", action="store_true", 157517393d9SAndrew Geissler help="Show programs version and exit.") 158517393d9SAndrew Geissler 159517393d9SAndrew Geissler general_group.add_argument('-h', '--help', action='help', 160517393d9SAndrew Geissler help='Show this help message and exit.') 161517393d9SAndrew Geissler 162517393d9SAndrew Geissler 163517393d9SAndrew Geissler task_group.add_argument("-f", "--force", action="store_true", 164eb8dc403SDave Cobbley help="Force the specified targets/task to run (invalidating any " 165eb8dc403SDave Cobbley "existing stamp file).") 166eb8dc403SDave Cobbley 167517393d9SAndrew Geissler task_group.add_argument("-c", "--cmd", 168eb8dc403SDave Cobbley help="Specify the task to execute. The exact options available " 169eb8dc403SDave Cobbley "depend on the metadata. Some examples might be 'compile'" 170eb8dc403SDave Cobbley " or 'populate_sysroot' or 'listtasks' may give a list of " 171eb8dc403SDave Cobbley "the tasks available.") 172eb8dc403SDave Cobbley 173517393d9SAndrew Geissler task_group.add_argument("-C", "--clear-stamp", dest="invalidate_stamp", 174eb8dc403SDave Cobbley help="Invalidate the stamp for the specified task such as 'compile' " 175eb8dc403SDave Cobbley "and then run the default task for the specified target(s).") 176eb8dc403SDave Cobbley 177517393d9SAndrew Geissler task_group.add_argument("--runall", action="append", default=[], 178517393d9SAndrew Geissler help="Run the specified task for any recipe in the taskgraph of the " 179517393d9SAndrew Geissler "specified target (even if it wouldn't otherwise have run).") 180eb8dc403SDave Cobbley 181517393d9SAndrew Geissler task_group.add_argument("--runonly", action="append", 182517393d9SAndrew Geissler help="Run only the specified task within the taskgraph of the " 183517393d9SAndrew Geissler "specified targets (and any task dependencies those tasks may have).") 184eb8dc403SDave Cobbley 185517393d9SAndrew Geissler task_group.add_argument("--no-setscene", action="store_true", 186517393d9SAndrew Geissler dest="nosetscene", 187517393d9SAndrew Geissler help="Do not run any setscene tasks. sstate will be ignored and " 188517393d9SAndrew Geissler "everything needed, built.") 189eb8dc403SDave Cobbley 190517393d9SAndrew Geissler task_group.add_argument("--skip-setscene", action="store_true", 191517393d9SAndrew Geissler dest="skipsetscene", 192517393d9SAndrew Geissler help="Skip setscene tasks if they would be executed. Tasks previously " 193517393d9SAndrew Geissler "restored from sstate will be kept, unlike --no-setscene.") 194517393d9SAndrew Geissler 195517393d9SAndrew Geissler task_group.add_argument("--setscene-only", action="store_true", 196517393d9SAndrew Geissler dest="setsceneonly", 197517393d9SAndrew Geissler help="Only run setscene tasks, don't run any real tasks.") 198517393d9SAndrew Geissler 199517393d9SAndrew Geissler 200517393d9SAndrew Geissler exec_group.add_argument("-n", "--dry-run", action="store_true", 201517393d9SAndrew Geissler help="Don't execute, just go through the motions.") 202517393d9SAndrew Geissler 203517393d9SAndrew Geissler exec_group.add_argument("-p", "--parse-only", action="store_true", 204517393d9SAndrew Geissler help="Quit after parsing the BB recipes.") 205517393d9SAndrew Geissler 206517393d9SAndrew Geissler exec_group.add_argument("-k", "--continue", action="store_false", dest="halt", 207517393d9SAndrew Geissler help="Continue as much as possible after an error. While the target that " 208517393d9SAndrew Geissler "failed and anything depending on it cannot be built, as much as " 209517393d9SAndrew Geissler "possible will be built before stopping.") 210517393d9SAndrew Geissler 211517393d9SAndrew Geissler exec_group.add_argument("-P", "--profile", action="store_true", 212517393d9SAndrew Geissler help="Profile the command and save reports.") 213517393d9SAndrew Geissler 214517393d9SAndrew Geissler exec_group.add_argument("-S", "--dump-signatures", action="append", 215517393d9SAndrew Geissler default=[], metavar="SIGNATURE_HANDLER", 216517393d9SAndrew Geissler help="Dump out the signature construction information, with no task " 217517393d9SAndrew Geissler "execution. The SIGNATURE_HANDLER parameter is passed to the " 218517393d9SAndrew Geissler "handler. Two common values are none and printdiff but the handler " 219517393d9SAndrew Geissler "may define more/less. none means only dump the signature, printdiff" 220*03514f19SPatrick Williams " means recursively compare the dumped signature with the most recent" 221*03514f19SPatrick Williams " one in a local build or sstate cache (can be used to find out why tasks re-run" 222*03514f19SPatrick Williams " when that is not expected)") 223517393d9SAndrew Geissler 224517393d9SAndrew Geissler exec_group.add_argument("--revisions-changed", action="store_true", 225517393d9SAndrew Geissler help="Set the exit code depending on whether upstream floating " 226517393d9SAndrew Geissler "revisions have changed or not.") 227517393d9SAndrew Geissler 228517393d9SAndrew Geissler exec_group.add_argument("-b", "--buildfile", 229517393d9SAndrew Geissler help="Execute tasks from a specific .bb recipe directly. WARNING: Does " 230517393d9SAndrew Geissler "not handle any dependencies from other recipes.") 231517393d9SAndrew Geissler 232517393d9SAndrew Geissler logging_group.add_argument("-D", "--debug", action="count", default=0, 233eb8dc403SDave Cobbley help="Increase the debug level. You can specify this " 234eb8dc403SDave Cobbley "more than once. -D sets the debug level to 1, " 235eb8dc403SDave Cobbley "where only bb.debug(1, ...) messages are printed " 236eb8dc403SDave Cobbley "to stdout; -DD sets the debug level to 2, where " 237eb8dc403SDave Cobbley "both bb.debug(1, ...) and bb.debug(2, ...) " 238eb8dc403SDave Cobbley "messages are printed; etc. Without -D, no debug " 239eb8dc403SDave Cobbley "messages are printed. Note that -D only affects " 240eb8dc403SDave Cobbley "output to stdout. All debug messages are written " 241eb8dc403SDave Cobbley "to ${T}/log.do_taskname, regardless of the debug " 242eb8dc403SDave Cobbley "level.") 243eb8dc403SDave Cobbley 244517393d9SAndrew Geissler logging_group.add_argument("-l", "--log-domains", action="append", dest="debug_domains", 245517393d9SAndrew Geissler default=[], 246517393d9SAndrew Geissler help="Show debug logging for the specified logging domains.") 247eb8dc403SDave Cobbley 248517393d9SAndrew Geissler logging_group.add_argument("-v", "--verbose", action="store_true", 249517393d9SAndrew Geissler help="Enable tracing of shell tasks (with 'set -x'). " 250517393d9SAndrew Geissler "Also print bb.note(...) messages to stdout (in " 251517393d9SAndrew Geissler "addition to writing them to ${T}/log.do_<task>).") 252eb8dc403SDave Cobbley 253517393d9SAndrew Geissler logging_group.add_argument("-q", "--quiet", action="count", default=0, 254517393d9SAndrew Geissler help="Output less log message data to the terminal. You can specify this " 255517393d9SAndrew Geissler "more than once.") 256eb8dc403SDave Cobbley 257517393d9SAndrew Geissler logging_group.add_argument("-w", "--write-log", dest="writeeventlog", 258517393d9SAndrew Geissler default=os.environ.get("BBEVENTLOG"), 259517393d9SAndrew Geissler help="Writes the event log of the build to a bitbake event json file. " 260517393d9SAndrew Geissler "Use '' (empty string) to assign the name automatically.") 261eb8dc403SDave Cobbley 262eb8dc403SDave Cobbley 263517393d9SAndrew Geissler server_group.add_argument("-B", "--bind", default=False, 264eb8dc403SDave Cobbley help="The name/address for the bitbake xmlrpc server to bind to.") 265eb8dc403SDave Cobbley 266517393d9SAndrew Geissler server_group.add_argument("-T", "--idle-timeout", type=float, dest="server_timeout", 267eb8dc403SDave Cobbley default=os.getenv("BB_SERVER_TIMEOUT"), 268eb8dc403SDave Cobbley help="Set timeout to unload bitbake server due to inactivity, " 269eb8dc403SDave Cobbley "set to -1 means no unload, " 270eb8dc403SDave Cobbley "default: Environment variable BB_SERVER_TIMEOUT.") 271eb8dc403SDave Cobbley 272517393d9SAndrew Geissler server_group.add_argument("--remote-server", 273eb8dc403SDave Cobbley default=os.environ.get("BBSERVER"), 274eb8dc403SDave Cobbley help="Connect to the specified server.") 275eb8dc403SDave Cobbley 276517393d9SAndrew Geissler server_group.add_argument("-m", "--kill-server", action="store_true", 277eb8dc403SDave Cobbley help="Terminate any running bitbake server.") 278eb8dc403SDave Cobbley 279517393d9SAndrew Geissler server_group.add_argument("--token", dest="xmlrpctoken", 280517393d9SAndrew Geissler default=os.environ.get("BBTOKEN"), 281517393d9SAndrew Geissler help="Specify the connection token to be used when connecting " 282517393d9SAndrew Geissler "to a remote server.") 283517393d9SAndrew Geissler 284517393d9SAndrew Geissler server_group.add_argument("--observe-only", action="store_true", 285eb8dc403SDave Cobbley help="Connect to a server as an observing-only client.") 286eb8dc403SDave Cobbley 287517393d9SAndrew Geissler server_group.add_argument("--status-only", action="store_true", 288eb8dc403SDave Cobbley help="Check the status of the remote bitbake server.") 289eb8dc403SDave Cobbley 290517393d9SAndrew Geissler server_group.add_argument("--server-only", action="store_true", 291517393d9SAndrew Geissler help="Run bitbake without a UI, only starting a server " 292517393d9SAndrew Geissler "(cooker) process.") 293eb8dc403SDave Cobbley 294eb8dc403SDave Cobbley 295517393d9SAndrew Geissler config_group.add_argument("-r", "--read", action="append", dest="prefile", default=[], 296517393d9SAndrew Geissler help="Read the specified file before bitbake.conf.") 297517393d9SAndrew Geissler 298517393d9SAndrew Geissler config_group.add_argument("-R", "--postread", action="append", dest="postfile", default=[], 299517393d9SAndrew Geissler help="Read the specified file after bitbake.conf.") 300517393d9SAndrew Geissler 301517393d9SAndrew Geissler 302517393d9SAndrew Geissler config_group.add_argument("-I", "--ignore-deps", action="append", 303517393d9SAndrew Geissler dest="extra_assume_provided", default=[], 304517393d9SAndrew Geissler help="Assume these dependencies don't exist and are already provided " 305517393d9SAndrew Geissler "(equivalent to ASSUME_PROVIDED). Useful to make dependency " 306517393d9SAndrew Geissler "graphs more appealing.") 307517393d9SAndrew Geissler 3086ce62a20SAndrew Geissler return parser 309eb8dc403SDave Cobbley 310eb8dc403SDave Cobbley 3116ce62a20SAndrew Geisslerclass BitBakeConfigParameters(cookerdata.ConfigParameters): 3126ce62a20SAndrew Geissler def parseCommandLine(self, argv=sys.argv): 3136ce62a20SAndrew Geissler parser = create_bitbake_parser() 314517393d9SAndrew Geissler options = parser.parse_intermixed_args(argv[1:]) 315517393d9SAndrew Geissler 316517393d9SAndrew Geissler if options.version: 317517393d9SAndrew Geissler print("BitBake Build Tool Core version %s" % bb.__version__) 318517393d9SAndrew Geissler sys.exit(0) 319eb8dc403SDave Cobbley 320eb8dc403SDave Cobbley if options.quiet and options.verbose: 321eb8dc403SDave Cobbley parser.error("options --quiet and --verbose are mutually exclusive") 322eb8dc403SDave Cobbley 323eb8dc403SDave Cobbley if options.quiet and options.debug: 324eb8dc403SDave Cobbley parser.error("options --quiet and --debug are mutually exclusive") 325eb8dc403SDave Cobbley 326eb8dc403SDave Cobbley # use configuration files from environment variables 327eb8dc403SDave Cobbley if "BBPRECONF" in os.environ: 328eb8dc403SDave Cobbley options.prefile.append(os.environ["BBPRECONF"]) 329eb8dc403SDave Cobbley 330eb8dc403SDave Cobbley if "BBPOSTCONF" in os.environ: 331eb8dc403SDave Cobbley options.postfile.append(os.environ["BBPOSTCONF"]) 332eb8dc403SDave Cobbley 333eb8dc403SDave Cobbley # fill in proper log name if not supplied 334eb8dc403SDave Cobbley if options.writeeventlog is not None and len(options.writeeventlog) == 0: 335eb8dc403SDave Cobbley from datetime import datetime 336eb8dc403SDave Cobbley eventlog = "bitbake_eventlog_%s.json" % datetime.now().strftime("%Y%m%d%H%M%S") 337eb8dc403SDave Cobbley options.writeeventlog = eventlog 338eb8dc403SDave Cobbley 339eb8dc403SDave Cobbley if options.bind: 340eb8dc403SDave Cobbley try: 341eb8dc403SDave Cobbley #Checking that the port is a number and is a ':' delimited value 342eb8dc403SDave Cobbley (host, port) = options.bind.split(':') 343eb8dc403SDave Cobbley port = int(port) 344eb8dc403SDave Cobbley except (ValueError,IndexError): 345eb8dc403SDave Cobbley raise BBMainException("FATAL: Malformed host:port bind parameter") 346eb8dc403SDave Cobbley options.xmlrpcinterface = (host, port) 347eb8dc403SDave Cobbley else: 348eb8dc403SDave Cobbley options.xmlrpcinterface = (None, 0) 349eb8dc403SDave Cobbley 350517393d9SAndrew Geissler return options, options.targets 351eb8dc403SDave Cobbley 352eb8dc403SDave Cobbley 353eb8dc403SDave Cobbleydef bitbake_main(configParams, configuration): 354eb8dc403SDave Cobbley 355eb8dc403SDave Cobbley # Python multiprocessing requires /dev/shm on Linux 356eb8dc403SDave Cobbley if sys.platform.startswith('linux') and not os.access('/dev/shm', os.W_OK | os.X_OK): 357eb8dc403SDave Cobbley raise BBMainException("FATAL: /dev/shm does not exist or is not writable") 358eb8dc403SDave Cobbley 359eb8dc403SDave Cobbley # Unbuffer stdout to avoid log truncation in the event 360eb8dc403SDave Cobbley # of an unorderly exit as well as to provide timely 361eb8dc403SDave Cobbley # updates to log files for use with tail 362eb8dc403SDave Cobbley try: 363eb8dc403SDave Cobbley if sys.stdout.name == '<stdout>': 364eb8dc403SDave Cobbley # Reopen with O_SYNC (unbuffered) 365eb8dc403SDave Cobbley fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL) 366eb8dc403SDave Cobbley fl |= os.O_SYNC 367eb8dc403SDave Cobbley fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl) 368eb8dc403SDave Cobbley except: 369eb8dc403SDave Cobbley pass 370eb8dc403SDave Cobbley 371eb8dc403SDave Cobbley if configParams.server_only and configParams.remote_server: 372eb8dc403SDave Cobbley raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" % 373eb8dc403SDave Cobbley ("the BBSERVER environment variable" if "BBSERVER" in os.environ \ 374eb8dc403SDave Cobbley else "the '--remote-server' option")) 375eb8dc403SDave Cobbley 376eb8dc403SDave Cobbley if configParams.observe_only and not (configParams.remote_server or configParams.bind): 377eb8dc403SDave Cobbley raise BBMainException("FATAL: '--observe-only' can only be used by UI clients " 378eb8dc403SDave Cobbley "connecting to a server.\n") 379eb8dc403SDave Cobbley 380eb8dc403SDave Cobbley if "BBDEBUG" in os.environ: 381eb8dc403SDave Cobbley level = int(os.environ["BBDEBUG"]) 382c9f7865aSAndrew Geissler if level > configParams.debug: 383c9f7865aSAndrew Geissler configParams.debug = level 384eb8dc403SDave Cobbley 385c9f7865aSAndrew Geissler bb.msg.init_msgconfig(configParams.verbose, configParams.debug, 386c9f7865aSAndrew Geissler configParams.debug_domains) 387eb8dc403SDave Cobbley 388c9f7865aSAndrew Geissler server_connection, ui_module = setup_bitbake(configParams) 389eb8dc403SDave Cobbley # No server connection 390eb8dc403SDave Cobbley if server_connection is None: 391eb8dc403SDave Cobbley if configParams.status_only: 392eb8dc403SDave Cobbley return 1 393eb8dc403SDave Cobbley if configParams.kill_server: 394eb8dc403SDave Cobbley return 0 395eb8dc403SDave Cobbley 396eb8dc403SDave Cobbley if not configParams.server_only: 397eb8dc403SDave Cobbley if configParams.status_only: 398eb8dc403SDave Cobbley server_connection.terminate() 399eb8dc403SDave Cobbley return 0 400eb8dc403SDave Cobbley 401eb8dc403SDave Cobbley try: 402eb8dc403SDave Cobbley for event in bb.event.ui_queue: 403eb8dc403SDave Cobbley server_connection.events.queue_event(event) 404eb8dc403SDave Cobbley bb.event.ui_queue = [] 405eb8dc403SDave Cobbley 406eb8dc403SDave Cobbley return ui_module.main(server_connection.connection, server_connection.events, 407eb8dc403SDave Cobbley configParams) 408eb8dc403SDave Cobbley finally: 409eb8dc403SDave Cobbley server_connection.terminate() 410eb8dc403SDave Cobbley else: 411eb8dc403SDave Cobbley return 0 412eb8dc403SDave Cobbley 413eb8dc403SDave Cobbley return 1 414eb8dc403SDave Cobbley 415517393d9SAndrew Geisslerdef timestamp(): 416517393d9SAndrew Geissler return datetime.datetime.now().strftime('%H:%M:%S.%f') 417517393d9SAndrew Geissler 418c9f7865aSAndrew Geisslerdef setup_bitbake(configParams, extrafeatures=None): 419eb8dc403SDave Cobbley # Ensure logging messages get sent to the UI as events 420eb8dc403SDave Cobbley handler = bb.event.LogHandler() 421eb8dc403SDave Cobbley if not configParams.status_only: 422eb8dc403SDave Cobbley # In status only mode there are no logs and no UI 423eb8dc403SDave Cobbley logger.addHandler(handler) 424eb8dc403SDave Cobbley 425517393d9SAndrew Geissler if configParams.dump_signatures: 426517393d9SAndrew Geissler if extrafeatures is None: 427517393d9SAndrew Geissler extrafeatures = [] 428517393d9SAndrew Geissler extrafeatures.append(bb.cooker.CookerFeatures.RECIPE_SIGGEN_INFO) 429517393d9SAndrew Geissler 430eb8dc403SDave Cobbley if configParams.server_only: 431eb8dc403SDave Cobbley featureset = [] 432eb8dc403SDave Cobbley ui_module = None 433eb8dc403SDave Cobbley else: 434eb8dc403SDave Cobbley ui_module = import_extension_module(bb.ui, configParams.ui, 'main') 435eb8dc403SDave Cobbley # Collect the feature set for the UI 436eb8dc403SDave Cobbley featureset = getattr(ui_module, "featureSet", []) 437eb8dc403SDave Cobbley 438eb8dc403SDave Cobbley if extrafeatures: 439eb8dc403SDave Cobbley for feature in extrafeatures: 440eb8dc403SDave Cobbley if not feature in featureset: 441eb8dc403SDave Cobbley featureset.append(feature) 442eb8dc403SDave Cobbley 443eb8dc403SDave Cobbley server_connection = None 444eb8dc403SDave Cobbley 4456ef3265dSBrad Bishop # Clear away any spurious environment variables while we stoke up the cooker 4466ef3265dSBrad Bishop # (done after import_extension_module() above since for example import gi triggers env var usage) 4476ef3265dSBrad Bishop cleanedvars = bb.utils.clean_environment() 4486ef3265dSBrad Bishop 449eb8dc403SDave Cobbley if configParams.remote_server: 450eb8dc403SDave Cobbley # Connect to a remote XMLRPC server 451eb8dc403SDave Cobbley server_connection = bb.server.xmlrpcclient.connectXMLRPC(configParams.remote_server, featureset, 452eb8dc403SDave Cobbley configParams.observe_only, configParams.xmlrpctoken) 453eb8dc403SDave Cobbley else: 454eb8dc403SDave Cobbley retries = 8 455eb8dc403SDave Cobbley while retries: 456eb8dc403SDave Cobbley try: 457517393d9SAndrew Geissler topdir, lock, lockfile = lockBitbake() 458eb8dc403SDave Cobbley sockname = topdir + "/bitbake.sock" 459eb8dc403SDave Cobbley if lock: 460eb8dc403SDave Cobbley if configParams.status_only or configParams.kill_server: 461eb8dc403SDave Cobbley logger.info("bitbake server is not running.") 462eb8dc403SDave Cobbley lock.close() 463eb8dc403SDave Cobbley return None, None 464c9f7865aSAndrew Geissler # we start a server with a given featureset 465eb8dc403SDave Cobbley logger.info("Starting bitbake server...") 466eb8dc403SDave Cobbley # Clear the event queue since we already displayed messages 467eb8dc403SDave Cobbley bb.event.ui_queue = [] 468517393d9SAndrew Geissler server = bb.server.process.BitBakeServer(lock, sockname, featureset, configParams.server_timeout, configParams.xmlrpcinterface, configParams.profile) 469eb8dc403SDave Cobbley 470eb8dc403SDave Cobbley else: 471eb8dc403SDave Cobbley logger.info("Reconnecting to bitbake server...") 472eb8dc403SDave Cobbley if not os.path.exists(sockname): 473517393d9SAndrew Geissler logger.info("Previous bitbake instance shutting down?, waiting to retry... (%s)" % timestamp()) 474517393d9SAndrew Geissler procs = bb.server.process.get_lockfile_process_msg(lockfile) 475517393d9SAndrew Geissler if procs: 476517393d9SAndrew Geissler logger.info("Processes holding bitbake.lock (missing socket %s):\n%s" % (sockname, procs)) 477517393d9SAndrew Geissler logger.info("Directory listing: %s" % (str(os.listdir(topdir)))) 478eb8dc403SDave Cobbley i = 0 479eb8dc403SDave Cobbley lock = None 480eb8dc403SDave Cobbley # Wait for 5s or until we can get the lock 481eb8dc403SDave Cobbley while not lock and i < 50: 482eb8dc403SDave Cobbley time.sleep(0.1) 483517393d9SAndrew Geissler _, lock, _ = lockBitbake() 484eb8dc403SDave Cobbley i += 1 485eb8dc403SDave Cobbley if lock: 486eb8dc403SDave Cobbley bb.utils.unlockfile(lock) 487eb8dc403SDave Cobbley raise bb.server.process.ProcessTimeout("Bitbake still shutting down as socket exists but no lock?") 488eb8dc403SDave Cobbley if not configParams.server_only: 489eb8dc403SDave Cobbley server_connection = bb.server.process.connectProcessServer(sockname, featureset) 490eb8dc403SDave Cobbley 491eb8dc403SDave Cobbley if server_connection or configParams.server_only: 492eb8dc403SDave Cobbley break 493eb8dc403SDave Cobbley except BBMainFatal: 494eb8dc403SDave Cobbley raise 4954c19ea12SAndrew Geissler except (Exception, bb.server.process.ProcessTimeout, SystemExit) as e: 4964c19ea12SAndrew Geissler # SystemExit does not inherit from the Exception class, needs to be included explicitly 497eb8dc403SDave Cobbley if not retries: 498eb8dc403SDave Cobbley raise 499eb8dc403SDave Cobbley retries -= 1 50019323693SBrad Bishop tryno = 8 - retries 5014c19ea12SAndrew Geissler if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError, SystemExit)): 502517393d9SAndrew Geissler logger.info("Retrying server connection (#%d)... (%s)" % (tryno, timestamp())) 503eb8dc403SDave Cobbley else: 504517393d9SAndrew Geissler logger.info("Retrying server connection (#%d)... (%s, %s)" % (tryno, traceback.format_exc(), timestamp())) 5054c19ea12SAndrew Geissler 506eb8dc403SDave Cobbley if not retries: 50796ff1984SBrad Bishop bb.fatal("Unable to connect to bitbake server, or start one (server startup failures would be in bitbake-cookerdaemon.log).") 50896ff1984SBrad Bishop bb.event.print_ui_queue() 509eb8dc403SDave Cobbley if retries < 5: 510eb8dc403SDave Cobbley time.sleep(5) 511eb8dc403SDave Cobbley 512eb8dc403SDave Cobbley if configParams.kill_server: 513eb8dc403SDave Cobbley server_connection.connection.terminateServer() 514eb8dc403SDave Cobbley server_connection.terminate() 515eb8dc403SDave Cobbley bb.event.ui_queue = [] 516eb8dc403SDave Cobbley logger.info("Terminated bitbake server.") 517eb8dc403SDave Cobbley return None, None 518eb8dc403SDave Cobbley 519eb8dc403SDave Cobbley # Restore the environment in case the UI needs it 520eb8dc403SDave Cobbley for k in cleanedvars: 521eb8dc403SDave Cobbley os.environ[k] = cleanedvars[k] 522eb8dc403SDave Cobbley 523eb8dc403SDave Cobbley logger.removeHandler(handler) 524eb8dc403SDave Cobbley 525eb8dc403SDave Cobbley return server_connection, ui_module 526eb8dc403SDave Cobbley 527eb8dc403SDave Cobbleydef lockBitbake(): 528eb8dc403SDave Cobbley topdir = bb.cookerdata.findTopdir() 529eb8dc403SDave Cobbley if not topdir: 53015ae2509SBrad Bishop bb.error("Unable to find conf/bblayers.conf or conf/bitbake.conf. BBPATH is unset and/or not in a build directory?") 531eb8dc403SDave Cobbley raise BBMainFatal 532eb8dc403SDave Cobbley lockfile = topdir + "/bitbake.lock" 533517393d9SAndrew Geissler return topdir, bb.utils.lockfile(lockfile, False, False), lockfile 534eb8dc403SDave Cobbley 535