blob: bca8ebfa090bc3adde650d3b0b31b033fdc48574 [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"
Patrick Williams03514f12024-04-05 07:04:11 -0500220 " means recursively compare the dumped signature with the most recent"
221 " one in a local build or sstate cache (can be used to find out why tasks re-run"
222 " when that is not expected)")
Andrew Geissler517393d2023-01-13 08:55:19 -0600223
224 exec_group.add_argument("--revisions-changed", action="store_true",
225 help="Set the exit code depending on whether upstream floating "
226 "revisions have changed or not.")
227
228 exec_group.add_argument("-b", "--buildfile",
229 help="Execute tasks from a specific .bb recipe directly. WARNING: Does "
230 "not handle any dependencies from other recipes.")
231
232 logging_group.add_argument("-D", "--debug", action="count", default=0,
233 help="Increase the debug level. You can specify this "
234 "more than once. -D sets the debug level to 1, "
235 "where only bb.debug(1, ...) messages are printed "
236 "to stdout; -DD sets the debug level to 2, where "
237 "both bb.debug(1, ...) and bb.debug(2, ...) "
238 "messages are printed; etc. Without -D, no debug "
239 "messages are printed. Note that -D only affects "
240 "output to stdout. All debug messages are written "
241 "to ${T}/log.do_taskname, regardless of the debug "
242 "level.")
243
244 logging_group.add_argument("-l", "--log-domains", action="append", dest="debug_domains",
245 default=[],
246 help="Show debug logging for the specified logging domains.")
247
248 logging_group.add_argument("-v", "--verbose", action="store_true",
249 help="Enable tracing of shell tasks (with 'set -x'). "
250 "Also print bb.note(...) messages to stdout (in "
251 "addition to writing them to ${T}/log.do_<task>).")
252
253 logging_group.add_argument("-q", "--quiet", action="count", default=0,
254 help="Output less log message data to the terminal. You can specify this "
255 "more than once.")
256
257 logging_group.add_argument("-w", "--write-log", dest="writeeventlog",
258 default=os.environ.get("BBEVENTLOG"),
259 help="Writes the event log of the build to a bitbake event json file. "
260 "Use '' (empty string) to assign the name automatically.")
261
262
263 server_group.add_argument("-B", "--bind", default=False,
264 help="The name/address for the bitbake xmlrpc server to bind to.")
265
266 server_group.add_argument("-T", "--idle-timeout", type=float, dest="server_timeout",
267 default=os.getenv("BB_SERVER_TIMEOUT"),
268 help="Set timeout to unload bitbake server due to inactivity, "
269 "set to -1 means no unload, "
270 "default: Environment variable BB_SERVER_TIMEOUT.")
271
272 server_group.add_argument("--remote-server",
273 default=os.environ.get("BBSERVER"),
274 help="Connect to the specified server.")
275
276 server_group.add_argument("-m", "--kill-server", action="store_true",
277 help="Terminate any running bitbake server.")
278
279 server_group.add_argument("--token", dest="xmlrpctoken",
280 default=os.environ.get("BBTOKEN"),
281 help="Specify the connection token to be used when connecting "
282 "to a remote server.")
283
284 server_group.add_argument("--observe-only", action="store_true",
285 help="Connect to a server as an observing-only client.")
286
287 server_group.add_argument("--status-only", action="store_true",
288 help="Check the status of the remote bitbake server.")
289
290 server_group.add_argument("--server-only", action="store_true",
291 help="Run bitbake without a UI, only starting a server "
292 "(cooker) process.")
293
294
295 config_group.add_argument("-r", "--read", action="append", dest="prefile", default=[],
296 help="Read the specified file before bitbake.conf.")
297
298 config_group.add_argument("-R", "--postread", action="append", dest="postfile", default=[],
299 help="Read the specified file after bitbake.conf.")
300
301
302 config_group.add_argument("-I", "--ignore-deps", action="append",
303 dest="extra_assume_provided", default=[],
304 help="Assume these dependencies don't exist and are already provided "
305 "(equivalent to ASSUME_PROVIDED). Useful to make dependency "
306 "graphs more appealing.")
307
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600308 return parser
Brad Bishop316dfdd2018-06-25 12:45:53 -0400309
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500310
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600311class BitBakeConfigParameters(cookerdata.ConfigParameters):
312 def parseCommandLine(self, argv=sys.argv):
313 parser = create_bitbake_parser()
Andrew Geissler517393d2023-01-13 08:55:19 -0600314 options = parser.parse_intermixed_args(argv[1:])
315
316 if options.version:
317 print("BitBake Build Tool Core version %s" % bb.__version__)
318 sys.exit(0)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500319
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600320 if options.quiet and options.verbose:
321 parser.error("options --quiet and --verbose are mutually exclusive")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500322
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600323 if options.quiet and options.debug:
324 parser.error("options --quiet and --debug are mutually exclusive")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500325
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600326 # use configuration files from environment variables
327 if "BBPRECONF" in os.environ:
328 options.prefile.append(os.environ["BBPRECONF"])
329
330 if "BBPOSTCONF" in os.environ:
331 options.postfile.append(os.environ["BBPOSTCONF"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500332
333 # fill in proper log name if not supplied
334 if options.writeeventlog is not None and len(options.writeeventlog) == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600335 from datetime import datetime
336 eventlog = "bitbake_eventlog_%s.json" % datetime.now().strftime("%Y%m%d%H%M%S")
337 options.writeeventlog = eventlog
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500338
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500339 if options.bind:
340 try:
341 #Checking that the port is a number and is a ':' delimited value
342 (host, port) = options.bind.split(':')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600343 port = int(port)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500344 except (ValueError,IndexError):
345 raise BBMainException("FATAL: Malformed host:port bind parameter")
346 options.xmlrpcinterface = (host, port)
347 else:
348 options.xmlrpcinterface = (None, 0)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500349
Andrew Geissler517393d2023-01-13 08:55:19 -0600350 return options, options.targets
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351
352
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500353def bitbake_main(configParams, configuration):
354
355 # Python multiprocessing requires /dev/shm on Linux
356 if sys.platform.startswith('linux') and not os.access('/dev/shm', os.W_OK | os.X_OK):
357 raise BBMainException("FATAL: /dev/shm does not exist or is not writable")
358
359 # Unbuffer stdout to avoid log truncation in the event
360 # of an unorderly exit as well as to provide timely
361 # updates to log files for use with tail
362 try:
363 if sys.stdout.name == '<stdout>':
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600364 # Reopen with O_SYNC (unbuffered)
365 fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL)
366 fl |= os.O_SYNC
367 fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500368 except:
369 pass
370
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500371 if configParams.server_only and configParams.remote_server:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500372 raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" %
373 ("the BBSERVER environment variable" if "BBSERVER" in os.environ \
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600374 else "the '--remote-server' option"))
375
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500376 if configParams.observe_only and not (configParams.remote_server or configParams.bind):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500377 raise BBMainException("FATAL: '--observe-only' can only be used by UI clients "
378 "connecting to a server.\n")
379
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500380 if "BBDEBUG" in os.environ:
381 level = int(os.environ["BBDEBUG"])
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500382 if level > configParams.debug:
383 configParams.debug = level
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500384
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500385 bb.msg.init_msgconfig(configParams.verbose, configParams.debug,
386 configParams.debug_domains)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500387
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500388 server_connection, ui_module = setup_bitbake(configParams)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500389 # No server connection
390 if server_connection is None:
391 if configParams.status_only:
392 return 1
393 if configParams.kill_server:
394 return 0
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395
396 if not configParams.server_only:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397 if configParams.status_only:
398 server_connection.terminate()
399 return 0
400
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500401 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500402 for event in bb.event.ui_queue:
403 server_connection.events.queue_event(event)
404 bb.event.ui_queue = []
405
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600406 return ui_module.main(server_connection.connection, server_connection.events,
407 configParams)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500408 finally:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409 server_connection.terminate()
410 else:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411 return 0
412
413 return 1
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500414
Andrew Geissler517393d2023-01-13 08:55:19 -0600415def timestamp():
416 return datetime.datetime.now().strftime('%H:%M:%S.%f')
417
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500418def setup_bitbake(configParams, extrafeatures=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500419 # Ensure logging messages get sent to the UI as events
420 handler = bb.event.LogHandler()
421 if not configParams.status_only:
422 # In status only mode there are no logs and no UI
423 logger.addHandler(handler)
424
Andrew Geissler517393d2023-01-13 08:55:19 -0600425 if configParams.dump_signatures:
426 if extrafeatures is None:
427 extrafeatures = []
428 extrafeatures.append(bb.cooker.CookerFeatures.RECIPE_SIGGEN_INFO)
429
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500430 if configParams.server_only:
431 featureset = []
432 ui_module = None
433 else:
434 ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
435 # Collect the feature set for the UI
436 featureset = getattr(ui_module, "featureSet", [])
437
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500438 if extrafeatures:
439 for feature in extrafeatures:
440 if not feature in featureset:
441 featureset.append(feature)
442
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500443 server_connection = None
444
Brad Bishop6ef32652018-10-09 18:59:25 +0100445 # Clear away any spurious environment variables while we stoke up the cooker
446 # (done after import_extension_module() above since for example import gi triggers env var usage)
447 cleanedvars = bb.utils.clean_environment()
448
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500449 if configParams.remote_server:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500450 # Connect to a remote XMLRPC server
451 server_connection = bb.server.xmlrpcclient.connectXMLRPC(configParams.remote_server, featureset,
452 configParams.observe_only, configParams.xmlrpctoken)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500453 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500454 retries = 8
455 while retries:
456 try:
Andrew Geissler517393d2023-01-13 08:55:19 -0600457 topdir, lock, lockfile = lockBitbake()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500458 sockname = topdir + "/bitbake.sock"
459 if lock:
460 if configParams.status_only or configParams.kill_server:
461 logger.info("bitbake server is not running.")
462 lock.close()
463 return None, None
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500464 # we start a server with a given featureset
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500465 logger.info("Starting bitbake server...")
466 # Clear the event queue since we already displayed messages
467 bb.event.ui_queue = []
Andrew Geissler517393d2023-01-13 08:55:19 -0600468 server = bb.server.process.BitBakeServer(lock, sockname, featureset, configParams.server_timeout, configParams.xmlrpcinterface, configParams.profile)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500469
470 else:
471 logger.info("Reconnecting to bitbake server...")
472 if not os.path.exists(sockname):
Andrew Geissler517393d2023-01-13 08:55:19 -0600473 logger.info("Previous bitbake instance shutting down?, waiting to retry... (%s)" % timestamp())
474 procs = bb.server.process.get_lockfile_process_msg(lockfile)
475 if procs:
476 logger.info("Processes holding bitbake.lock (missing socket %s):\n%s" % (sockname, procs))
477 logger.info("Directory listing: %s" % (str(os.listdir(topdir))))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500478 i = 0
479 lock = None
480 # Wait for 5s or until we can get the lock
481 while not lock and i < 50:
482 time.sleep(0.1)
Andrew Geissler517393d2023-01-13 08:55:19 -0600483 _, lock, _ = lockBitbake()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500484 i += 1
485 if lock:
486 bb.utils.unlockfile(lock)
487 raise bb.server.process.ProcessTimeout("Bitbake still shutting down as socket exists but no lock?")
488 if not configParams.server_only:
Brad Bishop96ff1982019-08-19 13:50:42 -0400489 server_connection = bb.server.process.connectProcessServer(sockname, featureset)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500490
491 if server_connection or configParams.server_only:
492 break
493 except BBMainFatal:
494 raise
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500495 except (Exception, bb.server.process.ProcessTimeout, SystemExit) as e:
496 # SystemExit does not inherit from the Exception class, needs to be included explicitly
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500497 if not retries:
498 raise
499 retries -= 1
Brad Bishop19323692019-04-05 15:28:33 -0400500 tryno = 8 - retries
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500501 if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError, SystemExit)):
Andrew Geissler517393d2023-01-13 08:55:19 -0600502 logger.info("Retrying server connection (#%d)... (%s)" % (tryno, timestamp()))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500503 else:
Andrew Geissler517393d2023-01-13 08:55:19 -0600504 logger.info("Retrying server connection (#%d)... (%s, %s)" % (tryno, traceback.format_exc(), timestamp()))
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600505
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500506 if not retries:
Brad Bishop96ff1982019-08-19 13:50:42 -0400507 bb.fatal("Unable to connect to bitbake server, or start one (server startup failures would be in bitbake-cookerdaemon.log).")
508 bb.event.print_ui_queue()
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500509 if retries < 5:
510 time.sleep(5)
511
512 if configParams.kill_server:
513 server_connection.connection.terminateServer()
514 server_connection.terminate()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500515 bb.event.ui_queue = []
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500516 logger.info("Terminated bitbake server.")
517 return None, None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500518
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500519 # Restore the environment in case the UI needs it
520 for k in cleanedvars:
521 os.environ[k] = cleanedvars[k]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500522
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500523 logger.removeHandler(handler)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500524
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500525 return server_connection, ui_module
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500526
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500527def lockBitbake():
528 topdir = bb.cookerdata.findTopdir()
529 if not topdir:
Brad Bishop15ae2502019-06-18 21:44:24 -0400530 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 -0500531 raise BBMainFatal
532 lockfile = topdir + "/bitbake.lock"
Andrew Geissler517393d2023-01-13 08:55:19 -0600533 return topdir, bb.utils.lockfile(lockfile, False, False), lockfile
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500534