blob: dd77cdd6e2460882da992ce1e2f86a01ad8bc1a1 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2BitBake 'Command' module
3
4Provide an interface to interact with the bitbake server through 'commands'
5"""
6
7# Copyright (C) 2006-2007 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
12"""
13The bitbake server takes 'commands' from its UI/commandline.
14Commands are either synchronous or asynchronous.
15Async commands return data to the client in the form of events.
16Sync commands must only return data through the function return value
17and must not trigger events, directly or indirectly.
18Commands are queued in a CommandQueue
19"""
20
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021from collections import OrderedDict, defaultdict
22
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023import bb.event
24import bb.cooker
Brad Bishop6e60e8b2018-02-01 10:27:11 -050025import bb.remotedata
26
27class DataStoreConnectionHandle(object):
28 def __init__(self, dsindex=0):
29 self.dsindex = dsindex
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030
31class CommandCompleted(bb.event.Event):
32 pass
33
34class CommandExit(bb.event.Event):
35 def __init__(self, exitcode):
36 bb.event.Event.__init__(self)
37 self.exitcode = int(exitcode)
38
39class CommandFailed(CommandExit):
40 def __init__(self, message):
41 self.error = message
42 CommandExit.__init__(self, 1)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050043 def __str__(self):
44 return "Command execution failed: %s" % self.error
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045
46class CommandError(Exception):
47 pass
48
49class Command:
50 """
51 A queue of asynchronous commands for bitbake
52 """
53 def __init__(self, cooker):
54 self.cooker = cooker
55 self.cmds_sync = CommandsSync()
56 self.cmds_async = CommandsAsync()
Andrew Geisslerc9f78652020-09-18 14:11:35 -050057 self.remotedatastores = None
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
59 # FIXME Add lock for this
60 self.currentAsyncCommand = None
61
62 def runCommand(self, commandline, ro_only = False):
63 command = commandline.pop(0)
Andrew Geisslerc9f78652020-09-18 14:11:35 -050064
65 # Ensure cooker is ready for commands
66 if command != "updateConfig" and command != "setFeatures":
67 self.cooker.init_configdata()
68 if not self.remotedatastores:
69 self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
70
Patrick Williamsc124f4f2015-09-15 14:41:29 -050071 if hasattr(CommandsSync, command):
72 # Can run synchronous commands straight away
73 command_method = getattr(self.cmds_sync, command)
74 if ro_only:
Andrew Geissler82c905d2020-04-13 13:39:40 -050075 if not hasattr(command_method, 'readonly') or not getattr(command_method, 'readonly'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076 return None, "Not able to execute not readonly commands in readonly mode"
77 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050078 self.cooker.process_inotify_updates()
79 if getattr(command_method, 'needconfig', True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080 self.cooker.updateCacheSync()
81 result = command_method(self, commandline)
82 except CommandError as exc:
83 return None, exc.args[0]
Andrew Geissleraf5e4ef2020-10-16 10:22:50 -050084 except (Exception, SystemExit) as exc:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085 import traceback
Andrew Geissleraf5e4ef2020-10-16 10:22:50 -050086 if isinstance(exc, bb.BBHandledException):
87 # We need to start returning real exceptions here. Until we do, we can't
88 # tell if an exception is an instance of bb.BBHandledException
89 return None, "bb.BBHandledException()\n" + traceback.format_exc()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090 return None, traceback.format_exc()
91 else:
92 return result, None
93 if self.currentAsyncCommand is not None:
94 return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
95 if command not in CommandsAsync.__dict__:
96 return None, "No such command"
97 self.currentAsyncCommand = (command, commandline)
Andrew Geissler635e0e42020-08-21 15:58:33 -050098 self.cooker.idleCallBackRegister(self.cooker.runCommands, self.cooker)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099 return True, None
100
101 def runAsyncCommand(self):
102 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500103 self.cooker.process_inotify_updates()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 if self.cooker.state in (bb.cooker.state.error, bb.cooker.state.shutdown, bb.cooker.state.forceshutdown):
105 # updateCache will trigger a shutdown of the parser
106 # and then raise BBHandledException triggering an exit
107 self.cooker.updateCache()
108 return False
109 if self.currentAsyncCommand is not None:
110 (command, options) = self.currentAsyncCommand
111 commandmethod = getattr(CommandsAsync, command)
112 needcache = getattr( commandmethod, "needcache" )
113 if needcache and self.cooker.state != bb.cooker.state.running:
114 self.cooker.updateCache()
115 return True
116 else:
117 commandmethod(self.cmds_async, self, options)
118 return False
119 else:
120 return False
121 except KeyboardInterrupt as exc:
122 self.finishAsyncCommand("Interrupted")
123 return False
124 except SystemExit as exc:
125 arg = exc.args[0]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600126 if isinstance(arg, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127 self.finishAsyncCommand(arg)
128 else:
129 self.finishAsyncCommand("Exited with %s" % arg)
130 return False
131 except Exception as exc:
132 import traceback
133 if isinstance(exc, bb.BBHandledException):
134 self.finishAsyncCommand("")
135 else:
136 self.finishAsyncCommand(traceback.format_exc())
137 return False
138
139 def finishAsyncCommand(self, msg=None, code=None):
140 if msg or msg == "":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141 bb.event.fire(CommandFailed(msg), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142 elif code:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500143 bb.event.fire(CommandExit(code), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500145 bb.event.fire(CommandCompleted(), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500146 self.currentAsyncCommand = None
147 self.cooker.finishcommand()
148
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500149 def reset(self):
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500150 if self.remotedatastores:
151 self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500152
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500153class CommandsSync:
154 """
155 A class of synchronous commands
156 These should run quickly so as not to hurt interactive performance.
157 These must not influence any running synchronous command.
158 """
159
160 def stateShutdown(self, command, params):
161 """
162 Trigger cooker 'shutdown' mode
163 """
164 command.cooker.shutdown(False)
165
166 def stateForceShutdown(self, command, params):
167 """
168 Stop the cooker
169 """
170 command.cooker.shutdown(True)
171
172 def getAllKeysWithFlags(self, command, params):
173 """
174 Returns a dump of the global state. Call with
175 variable flags to be retrieved as params.
176 """
177 flaglist = params[0]
178 return command.cooker.getAllKeysWithFlags(flaglist)
179 getAllKeysWithFlags.readonly = True
180
181 def getVariable(self, command, params):
182 """
183 Read the value of a variable from data
184 """
185 varname = params[0]
186 expand = True
187 if len(params) > 1:
188 expand = (params[1] == "True")
189
190 return command.cooker.data.getVar(varname, expand)
191 getVariable.readonly = True
192
193 def setVariable(self, command, params):
194 """
195 Set the value of variable in data
196 """
197 varname = params[0]
198 value = str(params[1])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500199 command.cooker.extraconfigdata[varname] = value
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 command.cooker.data.setVar(varname, value)
201
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500202 def getSetVariable(self, command, params):
203 """
204 Read the value of a variable from data and set it into the datastore
205 which effectively expands and locks the value.
206 """
207 varname = params[0]
208 result = self.getVariable(command, params)
209 command.cooker.data.setVar(varname, result)
210 return result
211
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500212 def setConfig(self, command, params):
213 """
214 Set the value of variable in configuration
215 """
216 varname = params[0]
217 value = str(params[1])
218 setattr(command.cooker.configuration, varname, value)
219
220 def enableDataTracking(self, command, params):
221 """
222 Enable history tracking for variables
223 """
224 command.cooker.enableDataTracking()
225
226 def disableDataTracking(self, command, params):
227 """
228 Disable history tracking for variables
229 """
230 command.cooker.disableDataTracking()
231
232 def setPrePostConfFiles(self, command, params):
233 prefiles = params[0].split()
234 postfiles = params[1].split()
235 command.cooker.configuration.prefile = prefiles
236 command.cooker.configuration.postfile = postfiles
237 setPrePostConfFiles.needconfig = False
238
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500239 def matchFile(self, command, params):
240 fMatch = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500241 try:
242 mc = params[0]
243 except IndexError:
244 mc = ''
245 return command.cooker.matchFile(fMatch, mc)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500246 matchFile.needconfig = False
247
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500248 def getUIHandlerNum(self, command, params):
249 return bb.event.get_uihandler()
250 getUIHandlerNum.needconfig = False
251 getUIHandlerNum.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500252
253 def setEventMask(self, command, params):
254 handlerNum = params[0]
255 llevel = params[1]
256 debug_domains = params[2]
257 mask = params[3]
258 return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
259 setEventMask.needconfig = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500260 setEventMask.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500261
262 def setFeatures(self, command, params):
263 """
264 Set the cooker features to include the passed list of features
265 """
266 features = params[0]
267 command.cooker.setFeatures(features)
268 setFeatures.needconfig = False
269 # although we change the internal state of the cooker, this is transparent since
270 # we always take and leave the cooker in state.initial
271 setFeatures.readonly = True
272
273 def updateConfig(self, command, params):
274 options = params[0]
275 environment = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500276 cmdline = params[2]
277 command.cooker.updateConfigOpts(options, environment, cmdline)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500278 updateConfig.needconfig = False
279
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500280 def parseConfiguration(self, command, params):
281 """Instruct bitbake to parse its configuration
282 NOTE: it is only necessary to call this if you aren't calling any normal action
283 (otherwise parsing is taken care of automatically)
284 """
285 command.cooker.parseConfiguration()
286 parseConfiguration.needconfig = False
287
288 def getLayerPriorities(self, command, params):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500289 command.cooker.parseConfiguration()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500290 ret = []
291 # regex objects cannot be marshalled by xmlrpc
292 for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
293 ret.append((collection, pattern, regex.pattern, pri))
294 return ret
295 getLayerPriorities.readonly = True
296
297 def getRecipes(self, command, params):
298 try:
299 mc = params[0]
300 except IndexError:
301 mc = ''
302 return list(command.cooker.recipecaches[mc].pkg_pn.items())
303 getRecipes.readonly = True
304
305 def getRecipeDepends(self, command, params):
306 try:
307 mc = params[0]
308 except IndexError:
309 mc = ''
310 return list(command.cooker.recipecaches[mc].deps.items())
311 getRecipeDepends.readonly = True
312
313 def getRecipeVersions(self, command, params):
314 try:
315 mc = params[0]
316 except IndexError:
317 mc = ''
318 return command.cooker.recipecaches[mc].pkg_pepvpr
319 getRecipeVersions.readonly = True
320
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500321 def getRecipeProvides(self, command, params):
322 try:
323 mc = params[0]
324 except IndexError:
325 mc = ''
326 return command.cooker.recipecaches[mc].fn_provides
327 getRecipeProvides.readonly = True
328
329 def getRecipePackages(self, command, params):
330 try:
331 mc = params[0]
332 except IndexError:
333 mc = ''
334 return command.cooker.recipecaches[mc].packages
335 getRecipePackages.readonly = True
336
337 def getRecipePackagesDynamic(self, command, params):
338 try:
339 mc = params[0]
340 except IndexError:
341 mc = ''
342 return command.cooker.recipecaches[mc].packages_dynamic
343 getRecipePackagesDynamic.readonly = True
344
345 def getRProviders(self, command, params):
346 try:
347 mc = params[0]
348 except IndexError:
349 mc = ''
350 return command.cooker.recipecaches[mc].rproviders
351 getRProviders.readonly = True
352
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500353 def getRuntimeDepends(self, command, params):
354 ret = []
355 try:
356 mc = params[0]
357 except IndexError:
358 mc = ''
359 rundeps = command.cooker.recipecaches[mc].rundeps
360 for key, value in rundeps.items():
361 if isinstance(value, defaultdict):
362 value = dict(value)
363 ret.append((key, value))
364 return ret
365 getRuntimeDepends.readonly = True
366
367 def getRuntimeRecommends(self, command, params):
368 ret = []
369 try:
370 mc = params[0]
371 except IndexError:
372 mc = ''
373 runrecs = command.cooker.recipecaches[mc].runrecs
374 for key, value in runrecs.items():
375 if isinstance(value, defaultdict):
376 value = dict(value)
377 ret.append((key, value))
378 return ret
379 getRuntimeRecommends.readonly = True
380
381 def getRecipeInherits(self, command, params):
382 try:
383 mc = params[0]
384 except IndexError:
385 mc = ''
386 return command.cooker.recipecaches[mc].inherits
387 getRecipeInherits.readonly = True
388
389 def getBbFilePriority(self, command, params):
390 try:
391 mc = params[0]
392 except IndexError:
393 mc = ''
394 return command.cooker.recipecaches[mc].bbfile_priority
395 getBbFilePriority.readonly = True
396
397 def getDefaultPreference(self, command, params):
398 try:
399 mc = params[0]
400 except IndexError:
401 mc = ''
402 return command.cooker.recipecaches[mc].pkg_dp
403 getDefaultPreference.readonly = True
404
405 def getSkippedRecipes(self, command, params):
406 # Return list sorted by reverse priority order
407 import bb.cache
Andrew Geissler5a43b432020-06-13 10:46:56 -0500408 def sortkey(x):
409 vfn, _ = x
410 realfn, _, mc = bb.cache.virtualfn2realfn(vfn)
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500411 return (-command.cooker.collections[mc].calc_bbfile_priority(realfn)[0], vfn)
Andrew Geissler5a43b432020-06-13 10:46:56 -0500412
413 skipdict = OrderedDict(sorted(command.cooker.skiplist.items(), key=sortkey))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500414 return list(skipdict.items())
415 getSkippedRecipes.readonly = True
416
417 def getOverlayedRecipes(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500418 try:
419 mc = params[0]
420 except IndexError:
421 mc = ''
422 return list(command.cooker.collections[mc].overlayed.items())
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500423 getOverlayedRecipes.readonly = True
424
425 def getFileAppends(self, command, params):
426 fn = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500427 try:
428 mc = params[1]
429 except IndexError:
430 mc = ''
431 return command.cooker.collections[mc].get_file_appends(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500432 getFileAppends.readonly = True
433
434 def getAllAppends(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500435 try:
436 mc = params[0]
437 except IndexError:
438 mc = ''
439 return command.cooker.collections[mc].bbappends
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500440 getAllAppends.readonly = True
441
442 def findProviders(self, command, params):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500443 try:
444 mc = params[0]
445 except IndexError:
446 mc = ''
447 return command.cooker.findProviders(mc)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500448 findProviders.readonly = True
449
450 def findBestProvider(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500451 (mc, pn) = bb.runqueue.split_mc(params[0])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500452 return command.cooker.findBestProvider(pn, mc)
453 findBestProvider.readonly = True
454
455 def allProviders(self, command, params):
456 try:
457 mc = params[0]
458 except IndexError:
459 mc = ''
460 return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
461 allProviders.readonly = True
462
463 def getRuntimeProviders(self, command, params):
464 rprovide = params[0]
465 try:
466 mc = params[1]
467 except IndexError:
468 mc = ''
469 all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
470 if all_p:
471 best = bb.providers.filterProvidersRunTime(all_p, rprovide,
472 command.cooker.data,
473 command.cooker.recipecaches[mc])[0][0]
474 else:
475 best = None
476 return all_p, best
477 getRuntimeProviders.readonly = True
478
Andrew Geissler82c905d2020-04-13 13:39:40 -0500479 def dataStoreConnectorCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500480 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500481 method = params[1]
482 args = params[2]
483 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500484
Andrew Geissler82c905d2020-04-13 13:39:40 -0500485 d = command.remotedatastores[dsindex]
486 ret = getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500487
Andrew Geissler82c905d2020-04-13 13:39:40 -0500488 if isinstance(ret, bb.data_smart.DataSmart):
489 idx = command.remotedatastores.store(ret)
490 return DataStoreConnectionHandle(idx)
491
492 return ret
493
494 def dataStoreConnectorVarHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500495 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500496 method = params[1]
497 args = params[2]
498 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500499
Andrew Geissler82c905d2020-04-13 13:39:40 -0500500 d = command.remotedatastores[dsindex].varhistory
501 return getattr(d, method)(*args, **kwargs)
502
503 def dataStoreConnectorIncHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500504 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500505 method = params[1]
506 args = params[2]
507 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500508
Andrew Geissler82c905d2020-04-13 13:39:40 -0500509 d = command.remotedatastores[dsindex].inchistory
510 return getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500511
512 def dataStoreConnectorRelease(self, command, params):
513 dsindex = params[0]
514 if dsindex <= 0:
515 raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
516 command.remotedatastores.release(dsindex)
517
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500518 def parseRecipeFile(self, command, params):
519 """
520 Parse the specified recipe file (with or without bbappends)
521 and return a datastore object representing the environment
522 for the recipe.
523 """
524 fn = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500525 mc = bb.runqueue.mc_from_tid(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500526 appends = params[1]
527 appendlist = params[2]
528 if len(params) > 3:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500529 config_data = command.remotedatastores[params[3]]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500530 else:
531 config_data = None
532
533 if appends:
534 if appendlist is not None:
535 appendfiles = appendlist
536 else:
Andrew Geissler5a43b432020-06-13 10:46:56 -0500537 appendfiles = command.cooker.collections[mc].get_file_appends(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500538 else:
539 appendfiles = []
540 # We are calling bb.cache locally here rather than on the server,
541 # but that's OK because it doesn't actually need anything from
542 # the server barring the global datastore (which we have a remote
543 # version of)
544 if config_data:
545 # We have to use a different function here if we're passing in a datastore
546 # NOTE: we took a copy above, so we don't do it here again
Andrew Geissler5a43b432020-06-13 10:46:56 -0500547 envdata = bb.cache.parse_recipe(config_data, fn, appendfiles, mc)['']
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500548 else:
549 # Use the standard path
550 parser = bb.cache.NoCache(command.cooker.databuilder)
551 envdata = parser.loadDataFull(fn, appendfiles)
552 idx = command.remotedatastores.store(envdata)
553 return DataStoreConnectionHandle(idx)
554 parseRecipeFile.readonly = True
555
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500556class CommandsAsync:
557 """
558 A class of asynchronous commands
559 These functions communicate via generated events.
560 Any function that requires metadata parsing should be here.
561 """
562
563 def buildFile(self, command, params):
564 """
565 Build a single specified .bb file
566 """
567 bfile = params[0]
568 task = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500569 if len(params) > 2:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500570 internal = params[2]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500571 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500572 internal = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500574 if internal:
575 command.cooker.buildFileInternal(bfile, task, fireevents=False, quietlog=True)
576 else:
577 command.cooker.buildFile(bfile, task)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500578 buildFile.needcache = False
579
580 def buildTargets(self, command, params):
581 """
582 Build a set of targets
583 """
584 pkgs_to_build = params[0]
585 task = params[1]
586
587 command.cooker.buildTargets(pkgs_to_build, task)
588 buildTargets.needcache = True
589
590 def generateDepTreeEvent(self, command, params):
591 """
592 Generate an event containing the dependency information
593 """
594 pkgs_to_build = params[0]
595 task = params[1]
596
597 command.cooker.generateDepTreeEvent(pkgs_to_build, task)
598 command.finishAsyncCommand()
599 generateDepTreeEvent.needcache = True
600
601 def generateDotGraph(self, command, params):
602 """
603 Dump dependency information to disk as .dot files
604 """
605 pkgs_to_build = params[0]
606 task = params[1]
607
608 command.cooker.generateDotGraphFiles(pkgs_to_build, task)
609 command.finishAsyncCommand()
610 generateDotGraph.needcache = True
611
612 def generateTargetsTree(self, command, params):
613 """
614 Generate a tree of buildable targets.
615 If klass is provided ensure all recipes that inherit the class are
616 included in the package list.
617 If pkg_list provided use that list (plus any extras brought in by
618 klass) rather than generating a tree for all packages.
619 """
620 klass = params[0]
621 pkg_list = params[1]
622
623 command.cooker.generateTargetsTree(klass, pkg_list)
624 command.finishAsyncCommand()
625 generateTargetsTree.needcache = True
626
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627 def findConfigFiles(self, command, params):
628 """
629 Find config files which provide appropriate values
630 for the passed configuration variable. i.e. MACHINE
631 """
632 varname = params[0]
633
634 command.cooker.findConfigFiles(varname)
635 command.finishAsyncCommand()
636 findConfigFiles.needcache = False
637
638 def findFilesMatchingInDir(self, command, params):
639 """
640 Find implementation files matching the specified pattern
641 in the requested subdirectory of a BBPATH
642 """
643 pattern = params[0]
644 directory = params[1]
645
646 command.cooker.findFilesMatchingInDir(pattern, directory)
647 command.finishAsyncCommand()
648 findFilesMatchingInDir.needcache = False
649
650 def findConfigFilePath(self, command, params):
651 """
652 Find the path of the requested configuration file
653 """
654 configfile = params[0]
655
656 command.cooker.findConfigFilePath(configfile)
657 command.finishAsyncCommand()
658 findConfigFilePath.needcache = False
659
660 def showVersions(self, command, params):
661 """
662 Show the currently selected versions
663 """
664 command.cooker.showVersions()
665 command.finishAsyncCommand()
666 showVersions.needcache = True
667
668 def showEnvironmentTarget(self, command, params):
669 """
670 Print the environment of a target recipe
671 (needs the cache to work out which recipe to use)
672 """
673 pkg = params[0]
674
675 command.cooker.showEnvironment(None, pkg)
676 command.finishAsyncCommand()
677 showEnvironmentTarget.needcache = True
678
679 def showEnvironment(self, command, params):
680 """
681 Print the standard environment
682 or if specified the environment for a specified recipe
683 """
684 bfile = params[0]
685
686 command.cooker.showEnvironment(bfile)
687 command.finishAsyncCommand()
688 showEnvironment.needcache = False
689
690 def parseFiles(self, command, params):
691 """
692 Parse the .bb files
693 """
694 command.cooker.updateCache()
695 command.finishAsyncCommand()
696 parseFiles.needcache = True
697
698 def compareRevisions(self, command, params):
699 """
700 Parse the .bb files
701 """
702 if bb.fetch.fetcher_compare_revisions(command.cooker.data):
703 command.finishAsyncCommand(code=1)
704 else:
705 command.finishAsyncCommand()
706 compareRevisions.needcache = True
707
708 def triggerEvent(self, command, params):
709 """
710 Trigger a certain event
711 """
712 event = params[0]
713 bb.event.fire(eval(event), command.cooker.data)
714 command.currentAsyncCommand = None
715 triggerEvent.needcache = False
716
717 def resetCooker(self, command, params):
718 """
719 Reset the cooker to its initial state, thus forcing a reparse for
720 any async command that has the needcache property set to True
721 """
722 command.cooker.reset()
723 command.finishAsyncCommand()
724 resetCooker.needcache = False
725
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500726 def clientComplete(self, command, params):
727 """
728 Do the right thing when the controlling client exits
729 """
730 command.cooker.clientComplete()
731 command.finishAsyncCommand()
732 clientComplete.needcache = False
733
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500734 def findSigInfo(self, command, params):
735 """
736 Find signature info files via the signature generator
737 """
Andrew Geissler635e0e42020-08-21 15:58:33 -0500738 (mc, pn) = bb.runqueue.split_mc(params[0])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500739 taskname = params[1]
740 sigs = params[2]
Andrew Geissler635e0e42020-08-21 15:58:33 -0500741 res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.databuilder.mcdata[mc])
742 bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.databuilder.mcdata[mc])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500743 command.finishAsyncCommand()
744 findSigInfo.needcache = False