blob: 92d8dc02931b9c5350c31aa90dfb261c79a38bbd [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# Copyright (C) 2003, 2004 Chris Larson
3# Copyright (C) 2003, 2004 Phil Blundell
4# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
5# Copyright (C) 2005 Holger Hans Peter Freyther
6# Copyright (C) 2005 ROAD GmbH
7# Copyright (C) 2006 Richard Purdie
8#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011
12import os
13import sys
14import logging
Andrew Geissler517393d2023-01-13 08:55:19 -060015import argparse
Patrick Williamsc124f4f2015-09-15 14:41:29 -050016import warnings
Patrick Williamsc0f7c042017-02-23 20:41:17 -060017import fcntl
Brad Bishopd7bf8c12018-02-25 22:55:05 -050018import time
19import traceback
Andrew Geissler517393d2023-01-13 08:55:19 -060020import datetime
Patrick Williamsc124f4f2015-09-15 14:41:29 -050021
22import bb
23from bb import event
24import bb.msg
25from bb import cooker
26from bb import ui
27from bb import server
28from bb import cookerdata
29
Brad Bishopd7bf8c12018-02-25 22:55:05 -050030import bb.server.process
31import bb.server.xmlrpcclient
32
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033logger = logging.getLogger("BitBake")
34
35class BBMainException(Exception):
36 pass
37
Brad Bishopd7bf8c12018-02-25 22:55:05 -050038class BBMainFatal(bb.BBHandledException):
39 pass
40
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041def present_options(optionlist):
42 if len(optionlist) > 1:
43 return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
44 else:
45 return optionlist[0]
46
Andrew Geissler517393d2023-01-13 08:55:19 -060047class BitbakeHelpFormatter(argparse.HelpFormatter):
48 def _get_help_string(self, action):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049 # We need to do this here rather than in the text we supply to
50 # add_option() because we don't want to call list_extension_modules()
51 # on every execution (since it imports all of the modules)
52 # Note also that we modify option.help rather than the returned text
53 # - this is so that we don't have to re-format the text ourselves
Andrew Geissler517393d2023-01-13 08:55:19 -060054 if action.dest == 'ui':
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055 valid_uis = list_extension_modules(bb.ui, 'main')
Andrew Geissler517393d2023-01-13 08:55:19 -060056 return action.help.replace('@CHOICES@', present_options(valid_uis))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050057
Andrew Geissler517393d2023-01-13 08:55:19 -060058 return action.help
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059
60def list_extension_modules(pkg, checkattr):
61 """
62 Lists extension modules in a specific Python package
63 (e.g. UIs, servers). NOTE: Calling this function will import all of the
64 submodules of the specified module in order to check for the specified
65 attribute; this can have unusual side-effects. As a result, this should
66 only be called when displaying help text or error messages.
67 Parameters:
68 pkg: previously imported Python package to list
69 checkattr: attribute to look for in module to determine if it's valid
70 as the type of extension you are looking for
71 """
72 import pkgutil
73 pkgdir = os.path.dirname(pkg.__file__)
74
75 modules = []
76 for _, modulename, _ in pkgutil.iter_modules([pkgdir]):
77 if os.path.isdir(os.path.join(pkgdir, modulename)):
78 # ignore directories
79 continue
80 try:
81 module = __import__(pkg.__name__, fromlist=[modulename])
82 except:
83 # If we can't import it, it's not valid
84 continue
85 module_if = getattr(module, modulename)
86 if getattr(module_if, 'hidden_extension', False):
87 continue
88 if not checkattr or hasattr(module_if, checkattr):
89 modules.append(modulename)
90 return modules
91
92def import_extension_module(pkg, modulename, checkattr):
93 try:
94 # Dynamically load the UI based on the ui name. Although we
95 # suggest a fixed set this allows you to have flexibility in which
96 # ones are available.
Patrick Williamsc0f7c042017-02-23 20:41:17 -060097 module = __import__(pkg.__name__, fromlist=[modulename])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 return getattr(module, modulename)
99 except AttributeError:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600100 modules = present_options(list_extension_modules(pkg, checkattr))
101 raise BBMainException('FATAL: Unable to import extension module "%s" from %s. '
102 'Valid extension modules: %s' % (modulename, pkg.__name__, modules))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103
104# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
105warnlog = logging.getLogger("BitBake.Warnings")
106_warnings_showwarning = warnings.showwarning
107def _showwarning(message, category, filename, lineno, file=None, line=None):
108 if file is not None:
109 if _warnings_showwarning is not None:
110 _warnings_showwarning(message, category, filename, lineno, file, line)
111 else:
112 s = warnings.formatwarning(message, category, filename, lineno)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600113 warnlog.warning(s)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500114
115warnings.showwarning = _showwarning
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600117def create_bitbake_parser():
Andrew Geissler517393d2023-01-13 08:55:19 -0600118 parser = argparse.ArgumentParser(
119 description="""\
120 It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
121 will provide the layer, BBFILES and other configuration information.
122 """,
123 formatter_class=BitbakeHelpFormatter,
124 allow_abbrev=False,
125 add_help=False, # help is manually added below in a specific argument group
126 )
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127
Andrew Geissler517393d2023-01-13 08:55:19 -0600128 general_group = parser.add_argument_group('General options')
129 task_group = parser.add_argument_group('Task control options')
130 exec_group = parser.add_argument_group('Execution control options')
131 logging_group = parser.add_argument_group('Logging/output control options')
132 server_group = parser.add_argument_group('Server options')
133 config_group = parser.add_argument_group('Configuration options')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500134
Andrew Geissler517393d2023-01-13 08:55:19 -0600135 general_group.add_argument("targets", nargs="*", metavar="recipename/target",
136 help="Execute the specified task (default is 'build') for these target "
137 "recipes (.bb files).")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500138
Andrew Geissler517393d2023-01-13 08:55:19 -0600139 general_group.add_argument("-s", "--show-versions", action="store_true",
140 help="Show current and preferred versions of all recipes.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
Andrew Geissler517393d2023-01-13 08:55:19 -0600142 general_group.add_argument("-e", "--environment", action="store_true",
143 dest="show_environment",
144 help="Show the global or per-recipe environment complete with information"
145 " about where variables were set/changed.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500146
Andrew Geissler517393d2023-01-13 08:55:19 -0600147 general_group.add_argument("-g", "--graphviz", action="store_true", dest="dot_graph",
148 help="Save dependency tree information for the specified "
149 "targets in the dot syntax.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500150
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600151 # @CHOICES@ is substituted out by BitbakeHelpFormatter above
Andrew Geissler517393d2023-01-13 08:55:19 -0600152 general_group.add_argument("-u", "--ui",
153 default=os.environ.get('BITBAKE_UI', 'knotty'),
154 help="The user interface to use (@CHOICES@ - default %(default)s).")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155
Andrew Geissler517393d2023-01-13 08:55:19 -0600156 general_group.add_argument("--version", action="store_true",
157 help="Show programs version and exit.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158
Andrew Geissler517393d2023-01-13 08:55:19 -0600159 general_group.add_argument('-h', '--help', action='help',
160 help='Show this help message and exit.')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500161
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500162
Andrew Geissler517393d2023-01-13 08:55:19 -0600163 task_group.add_argument("-f", "--force", action="store_true",
164 help="Force the specified targets/task to run (invalidating any "
165 "existing stamp file).")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500166
Andrew Geissler517393d2023-01-13 08:55:19 -0600167 task_group.add_argument("-c", "--cmd",
168 help="Specify the task to execute. The exact options available "
169 "depend on the metadata. Some examples might be 'compile'"
170 " or 'populate_sysroot' or 'listtasks' may give a list of "
171 "the tasks available.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500172
Andrew Geissler517393d2023-01-13 08:55:19 -0600173 task_group.add_argument("-C", "--clear-stamp", dest="invalidate_stamp",
174 help="Invalidate the stamp for the specified task such as 'compile' "
175 "and then run the default task for the specified target(s).")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500176
Andrew Geissler517393d2023-01-13 08:55:19 -0600177 task_group.add_argument("--runall", action="append", default=[],
178 help="Run the specified task for any recipe in the taskgraph of the "
179 "specified target (even if it wouldn't otherwise have run).")
Brad Bishop96ff1982019-08-19 13:50:42 -0400180
Andrew Geissler517393d2023-01-13 08:55:19 -0600181 task_group.add_argument("--runonly", action="append",
182 help="Run only the specified task within the taskgraph of the "
183 "specified targets (and any task dependencies those tasks may have).")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500184
Andrew Geissler517393d2023-01-13 08:55:19 -0600185 task_group.add_argument("--no-setscene", action="store_true",
186 dest="nosetscene",
187 help="Do not run any setscene tasks. sstate will be ignored and "
188 "everything needed, built.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500189
Andrew Geissler517393d2023-01-13 08:55:19 -0600190 task_group.add_argument("--skip-setscene", action="store_true",
191 dest="skipsetscene",
192 help="Skip setscene tasks if they would be executed. Tasks previously "
193 "restored from sstate will be kept, unlike --no-setscene.")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600194
Andrew Geissler517393d2023-01-13 08:55:19 -0600195 task_group.add_argument("--setscene-only", action="store_true",
196 dest="setsceneonly",
197 help="Only run setscene tasks, don't run any real tasks.")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600198
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600199
Andrew Geissler517393d2023-01-13 08:55:19 -0600200 exec_group.add_argument("-n", "--dry-run", action="store_true",
201 help="Don't execute, just go through the motions.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202
Andrew Geissler517393d2023-01-13 08:55:19 -0600203 exec_group.add_argument("-p", "--parse-only", action="store_true",
204 help="Quit after parsing the BB recipes.")
Brad Bishop316dfdd2018-06-25 12:45:53 -0400205
Andrew Geissler517393d2023-01-13 08:55:19 -0600206 exec_group.add_argument("-k", "--continue", action="store_false", dest="halt",
207 help="Continue as much as possible after an error. While the target that "
208 "failed and anything depending on it cannot be built, as much as "
209 "possible will be built before stopping.")
210
211 exec_group.add_argument("-P", "--profile", action="store_true",
212 help="Profile the command and save reports.")
213
214 exec_group.add_argument("-S", "--dump-signatures", action="append",
215 default=[], metavar="SIGNATURE_HANDLER",
216 help="Dump out the signature construction information, with no task "
217 "execution. The SIGNATURE_HANDLER parameter is passed to the "
218 "handler. Two common values are none and printdiff but the handler "
219 "may define more/less. none means only dump the signature, printdiff"
220 " means compare the dumped signature with the cached one.")
221
222 exec_group.add_argument("--revisions-changed", action="store_true",
223 help="Set the exit code depending on whether upstream floating "
224 "revisions have changed or not.")
225
226 exec_group.add_argument("-b", "--buildfile",
227 help="Execute tasks from a specific .bb recipe directly. WARNING: Does "
228 "not handle any dependencies from other recipes.")
229
230 logging_group.add_argument("-D", "--debug", action="count", default=0,
231 help="Increase the debug level. You can specify this "
232 "more than once. -D sets the debug level to 1, "
233 "where only bb.debug(1, ...) messages are printed "
234 "to stdout; -DD sets the debug level to 2, where "
235 "both bb.debug(1, ...) and bb.debug(2, ...) "
236 "messages are printed; etc. Without -D, no debug "
237 "messages are printed. Note that -D only affects "
238 "output to stdout. All debug messages are written "
239 "to ${T}/log.do_taskname, regardless of the debug "
240 "level.")
241
242 logging_group.add_argument("-l", "--log-domains", action="append", dest="debug_domains",
243 default=[],
244 help="Show debug logging for the specified logging domains.")
245
246 logging_group.add_argument("-v", "--verbose", action="store_true",
247 help="Enable tracing of shell tasks (with 'set -x'). "
248 "Also print bb.note(...) messages to stdout (in "
249 "addition to writing them to ${T}/log.do_<task>).")
250
251 logging_group.add_argument("-q", "--quiet", action="count", default=0,
252 help="Output less log message data to the terminal. You can specify this "
253 "more than once.")
254
255 logging_group.add_argument("-w", "--write-log", dest="writeeventlog",
256 default=os.environ.get("BBEVENTLOG"),
257 help="Writes the event log of the build to a bitbake event json file. "
258 "Use '' (empty string) to assign the name automatically.")
259
260
261 server_group.add_argument("-B", "--bind", default=False,
262 help="The name/address for the bitbake xmlrpc server to bind to.")
263
264 server_group.add_argument("-T", "--idle-timeout", type=float, dest="server_timeout",
265 default=os.getenv("BB_SERVER_TIMEOUT"),
266 help="Set timeout to unload bitbake server due to inactivity, "
267 "set to -1 means no unload, "
268 "default: Environment variable BB_SERVER_TIMEOUT.")
269
270 server_group.add_argument("--remote-server",
271 default=os.environ.get("BBSERVER"),
272 help="Connect to the specified server.")
273
274 server_group.add_argument("-m", "--kill-server", action="store_true",
275 help="Terminate any running bitbake server.")
276
277 server_group.add_argument("--token", dest="xmlrpctoken",
278 default=os.environ.get("BBTOKEN"),
279 help="Specify the connection token to be used when connecting "
280 "to a remote server.")
281
282 server_group.add_argument("--observe-only", action="store_true",
283 help="Connect to a server as an observing-only client.")
284
285 server_group.add_argument("--status-only", action="store_true",
286 help="Check the status of the remote bitbake server.")
287
288 server_group.add_argument("--server-only", action="store_true",
289 help="Run bitbake without a UI, only starting a server "
290 "(cooker) process.")
291
292
293 config_group.add_argument("-r", "--read", action="append", dest="prefile", default=[],
294 help="Read the specified file before bitbake.conf.")
295
296 config_group.add_argument("-R", "--postread", action="append", dest="postfile", default=[],
297 help="Read the specified file after bitbake.conf.")
298
299
300 config_group.add_argument("-I", "--ignore-deps", action="append",
301 dest="extra_assume_provided", default=[],
302 help="Assume these dependencies don't exist and are already provided "
303 "(equivalent to ASSUME_PROVIDED). Useful to make dependency "
304 "graphs more appealing.")
305
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600306 return parser
Brad Bishop316dfdd2018-06-25 12:45:53 -0400307
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500308
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600309class BitBakeConfigParameters(cookerdata.ConfigParameters):
310 def parseCommandLine(self, argv=sys.argv):
311 parser = create_bitbake_parser()
Andrew Geissler517393d2023-01-13 08:55:19 -0600312 options = parser.parse_intermixed_args(argv[1:])
313
314 if options.version:
315 print("BitBake Build Tool Core version %s" % bb.__version__)
316 sys.exit(0)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500317
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600318 if options.quiet and options.verbose:
319 parser.error("options --quiet and --verbose are mutually exclusive")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500320
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600321 if options.quiet and options.debug:
322 parser.error("options --quiet and --debug are mutually exclusive")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500323
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600324 # use configuration files from environment variables
325 if "BBPRECONF" in os.environ:
326 options.prefile.append(os.environ["BBPRECONF"])
327
328 if "BBPOSTCONF" in os.environ:
329 options.postfile.append(os.environ["BBPOSTCONF"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500330
331 # fill in proper log name if not supplied
332 if options.writeeventlog is not None and len(options.writeeventlog) == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600333 from datetime import datetime
334 eventlog = "bitbake_eventlog_%s.json" % datetime.now().strftime("%Y%m%d%H%M%S")
335 options.writeeventlog = eventlog
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500337 if options.bind:
338 try:
339 #Checking that the port is a number and is a ':' delimited value
340 (host, port) = options.bind.split(':')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600341 port = int(port)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500342 except (ValueError,IndexError):
343 raise BBMainException("FATAL: Malformed host:port bind parameter")
344 options.xmlrpcinterface = (host, port)
345 else:
346 options.xmlrpcinterface = (None, 0)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500347
Andrew Geissler517393d2023-01-13 08:55:19 -0600348 return options, options.targets
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500349
350
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351def bitbake_main(configParams, configuration):
352
353 # Python multiprocessing requires /dev/shm on Linux
354 if sys.platform.startswith('linux') and not os.access('/dev/shm', os.W_OK | os.X_OK):
355 raise BBMainException("FATAL: /dev/shm does not exist or is not writable")
356
357 # Unbuffer stdout to avoid log truncation in the event
358 # of an unorderly exit as well as to provide timely
359 # updates to log files for use with tail
360 try:
361 if sys.stdout.name == '<stdout>':
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600362 # Reopen with O_SYNC (unbuffered)
363 fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL)
364 fl |= os.O_SYNC
365 fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500366 except:
367 pass
368
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500369 if configParams.server_only and configParams.remote_server:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500370 raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" %
371 ("the BBSERVER environment variable" if "BBSERVER" in os.environ \
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600372 else "the '--remote-server' option"))
373
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500374 if configParams.observe_only and not (configParams.remote_server or configParams.bind):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375 raise BBMainException("FATAL: '--observe-only' can only be used by UI clients "
376 "connecting to a server.\n")
377
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378 if "BBDEBUG" in os.environ:
379 level = int(os.environ["BBDEBUG"])
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500380 if level > configParams.debug:
381 configParams.debug = level
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500382
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500383 bb.msg.init_msgconfig(configParams.verbose, configParams.debug,
384 configParams.debug_domains)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500385
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500386 server_connection, ui_module = setup_bitbake(configParams)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500387 # No server connection
388 if server_connection is None:
389 if configParams.status_only:
390 return 1
391 if configParams.kill_server:
392 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500393
394 if not configParams.server_only:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395 if configParams.status_only:
396 server_connection.terminate()
397 return 0
398
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500399 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500400 for event in bb.event.ui_queue:
401 server_connection.events.queue_event(event)
402 bb.event.ui_queue = []
403
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600404 return ui_module.main(server_connection.connection, server_connection.events,
405 configParams)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406 finally:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500407 server_connection.terminate()
408 else:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409 return 0
410
411 return 1
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500412
Andrew Geissler517393d2023-01-13 08:55:19 -0600413def timestamp():
414 return datetime.datetime.now().strftime('%H:%M:%S.%f')
415
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500416def setup_bitbake(configParams, extrafeatures=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500417 # Ensure logging messages get sent to the UI as events
418 handler = bb.event.LogHandler()
419 if not configParams.status_only:
420 # In status only mode there are no logs and no UI
421 logger.addHandler(handler)
422
Andrew Geissler517393d2023-01-13 08:55:19 -0600423 if configParams.dump_signatures:
424 if extrafeatures is None:
425 extrafeatures = []
426 extrafeatures.append(bb.cooker.CookerFeatures.RECIPE_SIGGEN_INFO)
427
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500428 if configParams.server_only:
429 featureset = []
430 ui_module = None
431 else:
432 ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
433 # Collect the feature set for the UI
434 featureset = getattr(ui_module, "featureSet", [])
435
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500436 if extrafeatures:
437 for feature in extrafeatures:
438 if not feature in featureset:
439 featureset.append(feature)
440
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500441 server_connection = None
442
Brad Bishop6ef32652018-10-09 18:59:25 +0100443 # Clear away any spurious environment variables while we stoke up the cooker
444 # (done after import_extension_module() above since for example import gi triggers env var usage)
445 cleanedvars = bb.utils.clean_environment()
446
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500447 if configParams.remote_server:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500448 # Connect to a remote XMLRPC server
449 server_connection = bb.server.xmlrpcclient.connectXMLRPC(configParams.remote_server, featureset,
450 configParams.observe_only, configParams.xmlrpctoken)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500451 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500452 retries = 8
453 while retries:
454 try:
Andrew Geissler517393d2023-01-13 08:55:19 -0600455 topdir, lock, lockfile = lockBitbake()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500456 sockname = topdir + "/bitbake.sock"
457 if lock:
458 if configParams.status_only or configParams.kill_server:
459 logger.info("bitbake server is not running.")
460 lock.close()
461 return None, None
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500462 # we start a server with a given featureset
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500463 logger.info("Starting bitbake server...")
464 # Clear the event queue since we already displayed messages
465 bb.event.ui_queue = []
Andrew Geissler517393d2023-01-13 08:55:19 -0600466 server = bb.server.process.BitBakeServer(lock, sockname, featureset, configParams.server_timeout, configParams.xmlrpcinterface, configParams.profile)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500467
468 else:
469 logger.info("Reconnecting to bitbake server...")
470 if not os.path.exists(sockname):
Andrew Geissler517393d2023-01-13 08:55:19 -0600471 logger.info("Previous bitbake instance shutting down?, waiting to retry... (%s)" % timestamp())
472 procs = bb.server.process.get_lockfile_process_msg(lockfile)
473 if procs:
474 logger.info("Processes holding bitbake.lock (missing socket %s):\n%s" % (sockname, procs))
475 logger.info("Directory listing: %s" % (str(os.listdir(topdir))))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500476 i = 0
477 lock = None
478 # Wait for 5s or until we can get the lock
479 while not lock and i < 50:
480 time.sleep(0.1)
Andrew Geissler517393d2023-01-13 08:55:19 -0600481 _, lock, _ = lockBitbake()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500482 i += 1
483 if lock:
484 bb.utils.unlockfile(lock)
485 raise bb.server.process.ProcessTimeout("Bitbake still shutting down as socket exists but no lock?")
486 if not configParams.server_only:
Brad Bishop96ff1982019-08-19 13:50:42 -0400487 server_connection = bb.server.process.connectProcessServer(sockname, featureset)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500488
489 if server_connection or configParams.server_only:
490 break
491 except BBMainFatal:
492 raise
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500493 except (Exception, bb.server.process.ProcessTimeout, SystemExit) as e:
494 # SystemExit does not inherit from the Exception class, needs to be included explicitly
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500495 if not retries:
496 raise
497 retries -= 1
Brad Bishop19323692019-04-05 15:28:33 -0400498 tryno = 8 - retries
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500499 if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError, SystemExit)):
Andrew Geissler517393d2023-01-13 08:55:19 -0600500 logger.info("Retrying server connection (#%d)... (%s)" % (tryno, timestamp()))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500501 else:
Andrew Geissler517393d2023-01-13 08:55:19 -0600502 logger.info("Retrying server connection (#%d)... (%s, %s)" % (tryno, traceback.format_exc(), timestamp()))
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600503
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500504 if not retries:
Brad Bishop96ff1982019-08-19 13:50:42 -0400505 bb.fatal("Unable to connect to bitbake server, or start one (server startup failures would be in bitbake-cookerdaemon.log).")
506 bb.event.print_ui_queue()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500507 if retries < 5:
508 time.sleep(5)
509
510 if configParams.kill_server:
511 server_connection.connection.terminateServer()
512 server_connection.terminate()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500513 bb.event.ui_queue = []
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500514 logger.info("Terminated bitbake server.")
515 return None, None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500516
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500517 # Restore the environment in case the UI needs it
518 for k in cleanedvars:
519 os.environ[k] = cleanedvars[k]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500520
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500521 logger.removeHandler(handler)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500522
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500523 return server_connection, ui_module
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500524
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500525def lockBitbake():
526 topdir = bb.cookerdata.findTopdir()
527 if not topdir:
Brad Bishop15ae2502019-06-18 21:44:24 -0400528 bb.error("Unable to find conf/bblayers.conf or conf/bitbake.conf. BBPATH is unset and/or not in a build directory?")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500529 raise BBMainFatal
530 lockfile = topdir + "/bitbake.lock"
Andrew Geissler517393d2023-01-13 08:55:19 -0600531 return topdir, bb.utils.lockfile(lockfile, False, False), lockfile
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500532