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