summaryrefslogtreecommitdiffstats
path: root/bitbake/bin/bitbake
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/bin/bitbake')
-rwxr-xr-xbitbake/bin/bitbake400
1 files changed, 400 insertions, 0 deletions
diff --git a/bitbake/bin/bitbake b/bitbake/bin/bitbake
new file mode 100755
index 0000000000..41cf8c86c0
--- /dev/null
+++ b/bitbake/bin/bitbake
@@ -0,0 +1,400 @@
1#!/usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# Copyright (C) 2003, 2004 Chris Larson
6# Copyright (C) 2003, 2004 Phil Blundell
7# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
8# Copyright (C) 2005 Holger Hans Peter Freyther
9# Copyright (C) 2005 ROAD GmbH
10# Copyright (C) 2006 Richard Purdie
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License version 2 as
14# published by the Free Software Foundation.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25import os
26import sys, logging
27sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),
28 'lib'))
29
30import optparse
31import warnings
32from traceback import format_exception
33try:
34 import bb
35except RuntimeError as exc:
36 sys.exit(str(exc))
37from bb import event
38import bb.msg
39from bb import cooker
40from bb import ui
41from bb import server
42from bb import cookerdata
43
44__version__ = "1.24.0"
45logger = logging.getLogger("BitBake")
46
47# Python multiprocessing requires /dev/shm
48if not os.access('/dev/shm', os.W_OK | os.X_OK):
49 sys.exit("FATAL: /dev/shm does not exist or is not writable")
50
51# Unbuffer stdout to avoid log truncation in the event
52# of an unorderly exit as well as to provide timely
53# updates to log files for use with tail
54try:
55 if sys.stdout.name == '<stdout>':
56 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
57except:
58 pass
59
60
61def get_ui(config):
62 if not config.ui:
63 # modify 'ui' attribute because it is also read by cooker
64 config.ui = os.environ.get('BITBAKE_UI', 'knotty')
65
66 interface = config.ui
67
68 try:
69 # Dynamically load the UI based on the ui name. Although we
70 # suggest a fixed set this allows you to have flexibility in which
71 # ones are available.
72 module = __import__("bb.ui", fromlist = [interface])
73 return getattr(module, interface)
74 except AttributeError:
75 sys.exit("FATAL: Invalid user interface '%s' specified.\n"
76 "Valid interfaces: depexp, goggle, ncurses, hob, knotty [default]." % interface)
77
78
79# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
80warnlog = logging.getLogger("BitBake.Warnings")
81_warnings_showwarning = warnings.showwarning
82def _showwarning(message, category, filename, lineno, file=None, line=None):
83 if file is not None:
84 if _warnings_showwarning is not None:
85 _warnings_showwarning(message, category, filename, lineno, file, line)
86 else:
87 s = warnings.formatwarning(message, category, filename, lineno)
88 warnlog.warn(s)
89
90warnings.showwarning = _showwarning
91warnings.filterwarnings("ignore")
92warnings.filterwarnings("default", module="(<string>$|(oe|bb)\.)")
93warnings.filterwarnings("ignore", category=PendingDeprecationWarning)
94warnings.filterwarnings("ignore", category=ImportWarning)
95warnings.filterwarnings("ignore", category=DeprecationWarning, module="<string>$")
96warnings.filterwarnings("ignore", message="With-statements now directly support multiple context managers")
97
98class BitBakeConfigParameters(cookerdata.ConfigParameters):
99
100 def parseCommandLine(self):
101 parser = optparse.OptionParser(
102 version = "BitBake Build Tool Core version %s, %%prog version %s" % (bb.__version__, __version__),
103 usage = """%prog [options] [recipename/target ...]
104
105 Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
106 It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
107 will provide the layer, BBFILES and other configuration information.""")
108
109 parser.add_option("-b", "--buildfile", help = "Execute tasks from a specific .bb recipe directly. WARNING: Does not handle any dependencies from other recipes.",
110 action = "store", dest = "buildfile", default = None)
111
112 parser.add_option("-k", "--continue", help = "Continue as much as possible after an error. While the target that failed and anything depending on it cannot be built, as much as possible will be built before stopping.",
113 action = "store_false", dest = "abort", default = True)
114
115 parser.add_option("-a", "--tryaltconfigs", help = "Continue with builds by trying to use alternative providers where possible.",
116 action = "store_true", dest = "tryaltconfigs", default = False)
117
118 parser.add_option("-f", "--force", help = "Force the specified targets/task to run (invalidating any existing stamp file).",
119 action = "store_true", dest = "force", default = False)
120
121 parser.add_option("-c", "--cmd", help = "Specify the task to execute. The exact options available depend on the metadata. Some examples might be 'compile' or 'populate_sysroot' or 'listtasks' may give a list of the tasks available.",
122 action = "store", dest = "cmd")
123
124 parser.add_option("-C", "--clear-stamp", help = "Invalidate the stamp for the specified task such as 'compile' and then run the default task for the specified target(s).",
125 action = "store", dest = "invalidate_stamp")
126
127 parser.add_option("-r", "--read", help = "Read the specified file before bitbake.conf.",
128 action = "append", dest = "prefile", default = [])
129
130 parser.add_option("-R", "--postread", help = "Read the specified file after bitbake.conf.",
131 action = "append", dest = "postfile", default = [])
132
133 parser.add_option("-v", "--verbose", help = "Output more log message data to the terminal.",
134 action = "store_true", dest = "verbose", default = False)
135
136 parser.add_option("-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
137 action = "count", dest="debug", default = 0)
138
139 parser.add_option("-n", "--dry-run", help = "Don't execute, just go through the motions.",
140 action = "store_true", dest = "dry_run", default = False)
141
142 parser.add_option("-S", "--dump-signatures", help = "Dump out the signature construction information, with no task execution. The SIGNATURE_HANDLER parameter is passed to the handler. Two common values are none and printdiff but the handler may define more/less. none means only dump the signature, printdiff means compare the dumped signature with the cached one.",
143 action = "append", dest = "dump_signatures", default = [], metavar="SIGNATURE_HANDLER")
144
145 parser.add_option("-p", "--parse-only", help = "Quit after parsing the BB recipes.",
146 action = "store_true", dest = "parse_only", default = False)
147
148 parser.add_option("-s", "--show-versions", help = "Show current and preferred versions of all recipes.",
149 action = "store_true", dest = "show_versions", default = False)
150
151 parser.add_option("-e", "--environment", help = "Show the global or per-recipe environment complete with information about where variables were set/changed.",
152 action = "store_true", dest = "show_environment", default = False)
153
154 parser.add_option("-g", "--graphviz", help = "Save dependency tree information for the specified targets in the dot syntax.",
155 action = "store_true", dest = "dot_graph", default = False)
156
157 parser.add_option("-I", "--ignore-deps", help = """Assume these dependencies don't exist and are already provided (equivalent to ASSUME_PROVIDED). Useful to make dependency graphs more appealing""",
158 action = "append", dest = "extra_assume_provided", default = [])
159
160 parser.add_option("-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
161 action = "append", dest = "debug_domains", default = [])
162
163 parser.add_option("-P", "--profile", help = "Profile the command and save reports.",
164 action = "store_true", dest = "profile", default = False)
165
166 parser.add_option("-u", "--ui", help = "The user interface to use (e.g. knotty, hob, depexp).",
167 action = "store", dest = "ui")
168
169 parser.add_option("-t", "--servertype", help = "Choose which server to use, process or xmlrpc.",
170 action = "store", dest = "servertype")
171
172 parser.add_option("", "--token", help = "Specify the connection token to be used when connecting to a remote server.",
173 action = "store", dest = "xmlrpctoken")
174
175 parser.add_option("", "--revisions-changed", help = "Set the exit code depending on whether upstream floating revisions have changed or not.",
176 action = "store_true", dest = "revisions_changed", default = False)
177
178 parser.add_option("", "--server-only", help = "Run bitbake without a UI, only starting a server (cooker) process.",
179 action = "store_true", dest = "server_only", default = False)
180
181 parser.add_option("-B", "--bind", help = "The name/address for the bitbake server to bind to.",
182 action = "store", dest = "bind", default = False)
183
184 parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks. sstate will be ignored and everything needed, built.",
185 action = "store_true", dest = "nosetscene", default = False)
186
187 parser.add_option("", "--remote-server", help = "Connect to the specified server.",
188 action = "store", dest = "remote_server", default = False)
189
190 parser.add_option("-m", "--kill-server", help = "Terminate the remote server.",
191 action = "store_true", dest = "kill_server", default = False)
192
193 parser.add_option("", "--observe-only", help = "Connect to a server as an observing-only client.",
194 action = "store_true", dest = "observe_only", default = False)
195
196 parser.add_option("", "--status-only", help = "Check the status of the remote bitbake server.",
197 action = "store_true", dest = "status_only", default = False)
198
199 parser.add_option("-w", "--write-log", help = "Writes the event log of the build to a bitbake event json file. Use '' (empty string) to assign the name automatically.",
200 action = "store", dest = "writeeventlog")
201
202 options, targets = parser.parse_args(sys.argv)
203
204 # some environmental variables set also configuration options
205 if "BBSERVER" in os.environ:
206 options.servertype = "xmlrpc"
207 options.remote_server = os.environ["BBSERVER"]
208
209 if "BBTOKEN" in os.environ:
210 options.xmlrpctoken = os.environ["BBTOKEN"]
211
212 if "BBEVENTLOG" is os.environ:
213 options.writeeventlog = os.environ["BBEVENTLOG"]
214
215 # fill in proper log name if not supplied
216 if options.writeeventlog is not None and len(options.writeeventlog) == 0:
217 import datetime
218 options.writeeventlog = "bitbake_eventlog_%s.json" % datetime.datetime.now().strftime("%Y%m%d%H%M%S")
219
220 # if BBSERVER says to autodetect, let's do that
221 if options.remote_server:
222 [host, port] = options.remote_server.split(":", 2)
223 port = int(port)
224 # use automatic port if port set to -1, means read it from
225 # the bitbake.lock file; this is a bit tricky, but we always expect
226 # to be in the base of the build directory if we need to have a
227 # chance to start the server later, anyway
228 if port == -1:
229 lock_location = "./bitbake.lock"
230 # we try to read the address at all times; if the server is not started,
231 # we'll try to start it after the first connect fails, below
232 try:
233 lf = open(lock_location, 'r')
234 remotedef = lf.readline()
235 [host, port] = remotedef.split(":")
236 port = int(port)
237 lf.close()
238 options.remote_server = remotedef
239 except Exception as e:
240 sys.exit("Failed to read bitbake.lock (%s), invalid port" % str(e))
241
242 return options, targets[1:]
243
244
245def start_server(servermodule, configParams, configuration, features):
246 server = servermodule.BitBakeServer()
247 if configParams.bind:
248 (host, port) = configParams.bind.split(':')
249 server.initServer((host, int(port)))
250 configuration.interface = [ server.serverImpl.host, server.serverImpl.port ]
251 else:
252 server.initServer()
253 configuration.interface = []
254
255 try:
256 configuration.setServerRegIdleCallback(server.getServerIdleCB())
257
258 cooker = bb.cooker.BBCooker(configuration, features)
259
260 server.addcooker(cooker)
261 server.saveConnectionDetails()
262 except Exception as e:
263 exc_info = sys.exc_info()
264 while hasattr(server, "event_queue"):
265 try:
266 import queue
267 except ImportError:
268 import Queue as queue
269 try:
270 event = server.event_queue.get(block=False)
271 except (queue.Empty, IOError):
272 break
273 if isinstance(event, logging.LogRecord):
274 logger.handle(event)
275 raise exc_info[1], None, exc_info[2]
276 server.detach()
277 return server
278
279
280def main():
281
282 configParams = BitBakeConfigParameters()
283 configuration = cookerdata.CookerConfiguration()
284 configuration.setConfigParameters(configParams)
285
286 ui_module = get_ui(configParams)
287
288 # Server type can be xmlrpc or process currently, if nothing is specified,
289 # the default server is process
290 if configParams.servertype:
291 server_type = configParams.servertype
292 else:
293 server_type = 'process'
294
295 try:
296 module = __import__("bb.server", fromlist = [server_type])
297 servermodule = getattr(module, server_type)
298 except AttributeError:
299 sys.exit("FATAL: Invalid server type '%s' specified.\n"
300 "Valid interfaces: xmlrpc, process [default]." % server_type)
301
302 if configParams.server_only:
303 if configParams.servertype != "xmlrpc":
304 sys.exit("FATAL: If '--server-only' is defined, we must set the servertype as 'xmlrpc'.\n")
305 if not configParams.bind:
306 sys.exit("FATAL: The '--server-only' option requires a name/address to bind to with the -B option.\n")
307 if configParams.remote_server:
308 sys.exit("FATAL: The '--server-only' option conflicts with %s.\n" %
309 ("the BBSERVER environment variable" if "BBSERVER" in os.environ else "the '--remote-server' option" ))
310
311 if configParams.bind and configParams.servertype != "xmlrpc":
312 sys.exit("FATAL: If '-B' or '--bind' is defined, we must set the servertype as 'xmlrpc'.\n")
313
314 if configParams.remote_server and configParams.servertype != "xmlrpc":
315 sys.exit("FATAL: If '--remote-server' is defined, we must set the servertype as 'xmlrpc'.\n")
316
317 if configParams.observe_only and (not configParams.remote_server or configParams.bind):
318 sys.exit("FATAL: '--observe-only' can only be used by UI clients connecting to a server.\n")
319
320 if configParams.kill_server and not configParams.remote_server:
321 sys.exit("FATAL: '--kill-server' can only be used to terminate a remote server")
322
323 if "BBDEBUG" in os.environ:
324 level = int(os.environ["BBDEBUG"])
325 if level > configuration.debug:
326 configuration.debug = level
327
328 bb.msg.init_msgconfig(configParams.verbose, configuration.debug,
329 configuration.debug_domains)
330
331 # Ensure logging messages get sent to the UI as events
332 handler = bb.event.LogHandler()
333 if not configParams.status_only:
334 # In status only mode there are no logs and no UI
335 logger.addHandler(handler)
336
337 # Clear away any spurious environment variables while we stoke up the cooker
338 cleanedvars = bb.utils.clean_environment()
339
340 featureset = []
341 if not configParams.server_only:
342 # Collect the feature set for the UI
343 featureset = getattr(ui_module, "featureSet", [])
344
345 if not configParams.remote_server:
346 # we start a server with a given configuration
347 server = start_server(servermodule, configParams, configuration, featureset)
348 bb.event.ui_queue = []
349 else:
350 # we start a stub server that is actually a XMLRPClient that connects to a real server
351 server = servermodule.BitBakeXMLRPCClient(configParams.observe_only, configParams.xmlrpctoken)
352 server.saveConnectionDetails(configParams.remote_server)
353
354
355 if not configParams.server_only:
356 try:
357 server_connection = server.establishConnection(featureset)
358 except Exception as e:
359 if configParams.kill_server:
360 sys.exit(0)
361 bb.fatal("Could not connect to server %s: %s" % (configParams.remote_server, str(e)))
362
363 # Restore the environment in case the UI needs it
364 for k in cleanedvars:
365 os.environ[k] = cleanedvars[k]
366
367 logger.removeHandler(handler)
368
369
370 if configParams.status_only:
371 server_connection.terminate()
372 sys.exit(0)
373
374 if configParams.kill_server:
375 server_connection.connection.terminateServer()
376 bb.event.ui_queue = []
377 sys.exit(0)
378
379 try:
380 return ui_module.main(server_connection.connection, server_connection.events, configParams)
381 finally:
382 bb.event.ui_queue = []
383 server_connection.terminate()
384 else:
385 print("server address: %s, server port: %s" % (server.serverImpl.host, server.serverImpl.port))
386 return 0
387
388 return 1
389
390if __name__ == "__main__":
391 try:
392 ret = main()
393 except bb.BBHandledException:
394 ret = 1
395 except Exception:
396 ret = 1
397 import traceback
398 traceback.print_exc()
399 sys.exit(ret)
400