blob: 3902ccca71326872b6746a2fbd08e84cc53b8cec [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()
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057 self.remotedatastores = bb.remotedata.RemoteDatastores(cooker)
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)
64 if hasattr(CommandsSync, command):
65 # Can run synchronous commands straight away
66 command_method = getattr(self.cmds_sync, command)
67 if ro_only:
Andrew Geissler82c905d2020-04-13 13:39:40 -050068 if not hasattr(command_method, 'readonly') or not getattr(command_method, 'readonly'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069 return None, "Not able to execute not readonly commands in readonly mode"
70 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071 self.cooker.process_inotify_updates()
72 if getattr(command_method, 'needconfig', True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050073 self.cooker.updateCacheSync()
74 result = command_method(self, commandline)
75 except CommandError as exc:
76 return None, exc.args[0]
77 except (Exception, SystemExit):
78 import traceback
79 return None, traceback.format_exc()
80 else:
81 return result, None
82 if self.currentAsyncCommand is not None:
83 return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
84 if command not in CommandsAsync.__dict__:
85 return None, "No such command"
86 self.currentAsyncCommand = (command, commandline)
87 self.cooker.configuration.server_register_idlecallback(self.cooker.runCommands, self.cooker)
88 return True, None
89
90 def runAsyncCommand(self):
91 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050092 self.cooker.process_inotify_updates()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093 if self.cooker.state in (bb.cooker.state.error, bb.cooker.state.shutdown, bb.cooker.state.forceshutdown):
94 # updateCache will trigger a shutdown of the parser
95 # and then raise BBHandledException triggering an exit
96 self.cooker.updateCache()
97 return False
98 if self.currentAsyncCommand is not None:
99 (command, options) = self.currentAsyncCommand
100 commandmethod = getattr(CommandsAsync, command)
101 needcache = getattr( commandmethod, "needcache" )
102 if needcache and self.cooker.state != bb.cooker.state.running:
103 self.cooker.updateCache()
104 return True
105 else:
106 commandmethod(self.cmds_async, self, options)
107 return False
108 else:
109 return False
110 except KeyboardInterrupt as exc:
111 self.finishAsyncCommand("Interrupted")
112 return False
113 except SystemExit as exc:
114 arg = exc.args[0]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600115 if isinstance(arg, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116 self.finishAsyncCommand(arg)
117 else:
118 self.finishAsyncCommand("Exited with %s" % arg)
119 return False
120 except Exception as exc:
121 import traceback
122 if isinstance(exc, bb.BBHandledException):
123 self.finishAsyncCommand("")
124 else:
125 self.finishAsyncCommand(traceback.format_exc())
126 return False
127
128 def finishAsyncCommand(self, msg=None, code=None):
129 if msg or msg == "":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500130 bb.event.fire(CommandFailed(msg), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500131 elif code:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500132 bb.event.fire(CommandExit(code), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500134 bb.event.fire(CommandCompleted(), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135 self.currentAsyncCommand = None
136 self.cooker.finishcommand()
137
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500138 def reset(self):
139 self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
140
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141class CommandsSync:
142 """
143 A class of synchronous commands
144 These should run quickly so as not to hurt interactive performance.
145 These must not influence any running synchronous command.
146 """
147
148 def stateShutdown(self, command, params):
149 """
150 Trigger cooker 'shutdown' mode
151 """
152 command.cooker.shutdown(False)
153
154 def stateForceShutdown(self, command, params):
155 """
156 Stop the cooker
157 """
158 command.cooker.shutdown(True)
159
160 def getAllKeysWithFlags(self, command, params):
161 """
162 Returns a dump of the global state. Call with
163 variable flags to be retrieved as params.
164 """
165 flaglist = params[0]
166 return command.cooker.getAllKeysWithFlags(flaglist)
167 getAllKeysWithFlags.readonly = True
168
169 def getVariable(self, command, params):
170 """
171 Read the value of a variable from data
172 """
173 varname = params[0]
174 expand = True
175 if len(params) > 1:
176 expand = (params[1] == "True")
177
178 return command.cooker.data.getVar(varname, expand)
179 getVariable.readonly = True
180
181 def setVariable(self, command, params):
182 """
183 Set the value of variable in data
184 """
185 varname = params[0]
186 value = str(params[1])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187 command.cooker.extraconfigdata[varname] = value
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500188 command.cooker.data.setVar(varname, value)
189
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500190 def getSetVariable(self, command, params):
191 """
192 Read the value of a variable from data and set it into the datastore
193 which effectively expands and locks the value.
194 """
195 varname = params[0]
196 result = self.getVariable(command, params)
197 command.cooker.data.setVar(varname, result)
198 return result
199
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 def setConfig(self, command, params):
201 """
202 Set the value of variable in configuration
203 """
204 varname = params[0]
205 value = str(params[1])
206 setattr(command.cooker.configuration, varname, value)
207
208 def enableDataTracking(self, command, params):
209 """
210 Enable history tracking for variables
211 """
212 command.cooker.enableDataTracking()
213
214 def disableDataTracking(self, command, params):
215 """
216 Disable history tracking for variables
217 """
218 command.cooker.disableDataTracking()
219
220 def setPrePostConfFiles(self, command, params):
221 prefiles = params[0].split()
222 postfiles = params[1].split()
223 command.cooker.configuration.prefile = prefiles
224 command.cooker.configuration.postfile = postfiles
225 setPrePostConfFiles.needconfig = False
226
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500227 def matchFile(self, command, params):
228 fMatch = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500229 try:
230 mc = params[0]
231 except IndexError:
232 mc = ''
233 return command.cooker.matchFile(fMatch, mc)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500234 matchFile.needconfig = False
235
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500236 def getUIHandlerNum(self, command, params):
237 return bb.event.get_uihandler()
238 getUIHandlerNum.needconfig = False
239 getUIHandlerNum.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500240
241 def setEventMask(self, command, params):
242 handlerNum = params[0]
243 llevel = params[1]
244 debug_domains = params[2]
245 mask = params[3]
246 return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
247 setEventMask.needconfig = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500248 setEventMask.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500249
250 def setFeatures(self, command, params):
251 """
252 Set the cooker features to include the passed list of features
253 """
254 features = params[0]
255 command.cooker.setFeatures(features)
256 setFeatures.needconfig = False
257 # although we change the internal state of the cooker, this is transparent since
258 # we always take and leave the cooker in state.initial
259 setFeatures.readonly = True
260
261 def updateConfig(self, command, params):
262 options = params[0]
263 environment = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500264 cmdline = params[2]
265 command.cooker.updateConfigOpts(options, environment, cmdline)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500266 updateConfig.needconfig = False
267
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500268 def parseConfiguration(self, command, params):
269 """Instruct bitbake to parse its configuration
270 NOTE: it is only necessary to call this if you aren't calling any normal action
271 (otherwise parsing is taken care of automatically)
272 """
273 command.cooker.parseConfiguration()
274 parseConfiguration.needconfig = False
275
276 def getLayerPriorities(self, command, params):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500277 command.cooker.parseConfiguration()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500278 ret = []
279 # regex objects cannot be marshalled by xmlrpc
280 for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
281 ret.append((collection, pattern, regex.pattern, pri))
282 return ret
283 getLayerPriorities.readonly = True
284
285 def getRecipes(self, command, params):
286 try:
287 mc = params[0]
288 except IndexError:
289 mc = ''
290 return list(command.cooker.recipecaches[mc].pkg_pn.items())
291 getRecipes.readonly = True
292
293 def getRecipeDepends(self, command, params):
294 try:
295 mc = params[0]
296 except IndexError:
297 mc = ''
298 return list(command.cooker.recipecaches[mc].deps.items())
299 getRecipeDepends.readonly = True
300
301 def getRecipeVersions(self, command, params):
302 try:
303 mc = params[0]
304 except IndexError:
305 mc = ''
306 return command.cooker.recipecaches[mc].pkg_pepvpr
307 getRecipeVersions.readonly = True
308
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500309 def getRecipeProvides(self, command, params):
310 try:
311 mc = params[0]
312 except IndexError:
313 mc = ''
314 return command.cooker.recipecaches[mc].fn_provides
315 getRecipeProvides.readonly = True
316
317 def getRecipePackages(self, command, params):
318 try:
319 mc = params[0]
320 except IndexError:
321 mc = ''
322 return command.cooker.recipecaches[mc].packages
323 getRecipePackages.readonly = True
324
325 def getRecipePackagesDynamic(self, command, params):
326 try:
327 mc = params[0]
328 except IndexError:
329 mc = ''
330 return command.cooker.recipecaches[mc].packages_dynamic
331 getRecipePackagesDynamic.readonly = True
332
333 def getRProviders(self, command, params):
334 try:
335 mc = params[0]
336 except IndexError:
337 mc = ''
338 return command.cooker.recipecaches[mc].rproviders
339 getRProviders.readonly = True
340
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500341 def getRuntimeDepends(self, command, params):
342 ret = []
343 try:
344 mc = params[0]
345 except IndexError:
346 mc = ''
347 rundeps = command.cooker.recipecaches[mc].rundeps
348 for key, value in rundeps.items():
349 if isinstance(value, defaultdict):
350 value = dict(value)
351 ret.append((key, value))
352 return ret
353 getRuntimeDepends.readonly = True
354
355 def getRuntimeRecommends(self, command, params):
356 ret = []
357 try:
358 mc = params[0]
359 except IndexError:
360 mc = ''
361 runrecs = command.cooker.recipecaches[mc].runrecs
362 for key, value in runrecs.items():
363 if isinstance(value, defaultdict):
364 value = dict(value)
365 ret.append((key, value))
366 return ret
367 getRuntimeRecommends.readonly = True
368
369 def getRecipeInherits(self, command, params):
370 try:
371 mc = params[0]
372 except IndexError:
373 mc = ''
374 return command.cooker.recipecaches[mc].inherits
375 getRecipeInherits.readonly = True
376
377 def getBbFilePriority(self, command, params):
378 try:
379 mc = params[0]
380 except IndexError:
381 mc = ''
382 return command.cooker.recipecaches[mc].bbfile_priority
383 getBbFilePriority.readonly = True
384
385 def getDefaultPreference(self, command, params):
386 try:
387 mc = params[0]
388 except IndexError:
389 mc = ''
390 return command.cooker.recipecaches[mc].pkg_dp
391 getDefaultPreference.readonly = True
392
393 def getSkippedRecipes(self, command, params):
394 # Return list sorted by reverse priority order
395 import bb.cache
Andrew Geissler5a43b432020-06-13 10:46:56 -0500396 def sortkey(x):
397 vfn, _ = x
398 realfn, _, mc = bb.cache.virtualfn2realfn(vfn)
399 return (-command.cooker.collections[mc].calc_bbfile_priority(realfn), vfn)
400
401 skipdict = OrderedDict(sorted(command.cooker.skiplist.items(), key=sortkey))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500402 return list(skipdict.items())
403 getSkippedRecipes.readonly = True
404
405 def getOverlayedRecipes(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500406 try:
407 mc = params[0]
408 except IndexError:
409 mc = ''
410 return list(command.cooker.collections[mc].overlayed.items())
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500411 getOverlayedRecipes.readonly = True
412
413 def getFileAppends(self, command, params):
414 fn = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500415 try:
416 mc = params[1]
417 except IndexError:
418 mc = ''
419 return command.cooker.collections[mc].get_file_appends(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500420 getFileAppends.readonly = True
421
422 def getAllAppends(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500423 try:
424 mc = params[0]
425 except IndexError:
426 mc = ''
427 return command.cooker.collections[mc].bbappends
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500428 getAllAppends.readonly = True
429
430 def findProviders(self, command, params):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500431 try:
432 mc = params[0]
433 except IndexError:
434 mc = ''
435 return command.cooker.findProviders(mc)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500436 findProviders.readonly = True
437
438 def findBestProvider(self, command, params):
Andrew Geissler5a43b432020-06-13 10:46:56 -0500439 (mc, pn) = bb.runqueue.split_mc(params[0])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500440 return command.cooker.findBestProvider(pn, mc)
441 findBestProvider.readonly = True
442
443 def allProviders(self, command, params):
444 try:
445 mc = params[0]
446 except IndexError:
447 mc = ''
448 return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
449 allProviders.readonly = True
450
451 def getRuntimeProviders(self, command, params):
452 rprovide = params[0]
453 try:
454 mc = params[1]
455 except IndexError:
456 mc = ''
457 all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
458 if all_p:
459 best = bb.providers.filterProvidersRunTime(all_p, rprovide,
460 command.cooker.data,
461 command.cooker.recipecaches[mc])[0][0]
462 else:
463 best = None
464 return all_p, best
465 getRuntimeProviders.readonly = True
466
Andrew Geissler82c905d2020-04-13 13:39:40 -0500467 def dataStoreConnectorCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500468 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500469 method = params[1]
470 args = params[2]
471 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500472
Andrew Geissler82c905d2020-04-13 13:39:40 -0500473 d = command.remotedatastores[dsindex]
474 ret = getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500475
Andrew Geissler82c905d2020-04-13 13:39:40 -0500476 if isinstance(ret, bb.data_smart.DataSmart):
477 idx = command.remotedatastores.store(ret)
478 return DataStoreConnectionHandle(idx)
479
480 return ret
481
482 def dataStoreConnectorVarHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500483 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500484 method = params[1]
485 args = params[2]
486 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500487
Andrew Geissler82c905d2020-04-13 13:39:40 -0500488 d = command.remotedatastores[dsindex].varhistory
489 return getattr(d, method)(*args, **kwargs)
490
491 def dataStoreConnectorIncHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500492 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500493 method = params[1]
494 args = params[2]
495 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500496
Andrew Geissler82c905d2020-04-13 13:39:40 -0500497 d = command.remotedatastores[dsindex].inchistory
498 return getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500499
500 def dataStoreConnectorRelease(self, command, params):
501 dsindex = params[0]
502 if dsindex <= 0:
503 raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
504 command.remotedatastores.release(dsindex)
505
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500506 def parseRecipeFile(self, command, params):
507 """
508 Parse the specified recipe file (with or without bbappends)
509 and return a datastore object representing the environment
510 for the recipe.
511 """
512 fn = params[0]
Andrew Geissler5a43b432020-06-13 10:46:56 -0500513 mc = bb.runqueue.mc_from_tid(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500514 appends = params[1]
515 appendlist = params[2]
516 if len(params) > 3:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500517 config_data = command.remotedatastores[params[3]]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500518 else:
519 config_data = None
520
521 if appends:
522 if appendlist is not None:
523 appendfiles = appendlist
524 else:
Andrew Geissler5a43b432020-06-13 10:46:56 -0500525 appendfiles = command.cooker.collections[mc].get_file_appends(fn)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500526 else:
527 appendfiles = []
528 # We are calling bb.cache locally here rather than on the server,
529 # but that's OK because it doesn't actually need anything from
530 # the server barring the global datastore (which we have a remote
531 # version of)
532 if config_data:
533 # We have to use a different function here if we're passing in a datastore
534 # NOTE: we took a copy above, so we don't do it here again
Andrew Geissler5a43b432020-06-13 10:46:56 -0500535 envdata = bb.cache.parse_recipe(config_data, fn, appendfiles, mc)['']
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500536 else:
537 # Use the standard path
538 parser = bb.cache.NoCache(command.cooker.databuilder)
539 envdata = parser.loadDataFull(fn, appendfiles)
540 idx = command.remotedatastores.store(envdata)
541 return DataStoreConnectionHandle(idx)
542 parseRecipeFile.readonly = True
543
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500544class CommandsAsync:
545 """
546 A class of asynchronous commands
547 These functions communicate via generated events.
548 Any function that requires metadata parsing should be here.
549 """
550
551 def buildFile(self, command, params):
552 """
553 Build a single specified .bb file
554 """
555 bfile = params[0]
556 task = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500557 if len(params) > 2:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500558 internal = params[2]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500559 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500560 internal = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500561
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500562 if internal:
563 command.cooker.buildFileInternal(bfile, task, fireevents=False, quietlog=True)
564 else:
565 command.cooker.buildFile(bfile, task)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500566 buildFile.needcache = False
567
568 def buildTargets(self, command, params):
569 """
570 Build a set of targets
571 """
572 pkgs_to_build = params[0]
573 task = params[1]
574
575 command.cooker.buildTargets(pkgs_to_build, task)
576 buildTargets.needcache = True
577
578 def generateDepTreeEvent(self, command, params):
579 """
580 Generate an event containing the dependency information
581 """
582 pkgs_to_build = params[0]
583 task = params[1]
584
585 command.cooker.generateDepTreeEvent(pkgs_to_build, task)
586 command.finishAsyncCommand()
587 generateDepTreeEvent.needcache = True
588
589 def generateDotGraph(self, command, params):
590 """
591 Dump dependency information to disk as .dot files
592 """
593 pkgs_to_build = params[0]
594 task = params[1]
595
596 command.cooker.generateDotGraphFiles(pkgs_to_build, task)
597 command.finishAsyncCommand()
598 generateDotGraph.needcache = True
599
600 def generateTargetsTree(self, command, params):
601 """
602 Generate a tree of buildable targets.
603 If klass is provided ensure all recipes that inherit the class are
604 included in the package list.
605 If pkg_list provided use that list (plus any extras brought in by
606 klass) rather than generating a tree for all packages.
607 """
608 klass = params[0]
609 pkg_list = params[1]
610
611 command.cooker.generateTargetsTree(klass, pkg_list)
612 command.finishAsyncCommand()
613 generateTargetsTree.needcache = True
614
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500615 def findConfigFiles(self, command, params):
616 """
617 Find config files which provide appropriate values
618 for the passed configuration variable. i.e. MACHINE
619 """
620 varname = params[0]
621
622 command.cooker.findConfigFiles(varname)
623 command.finishAsyncCommand()
624 findConfigFiles.needcache = False
625
626 def findFilesMatchingInDir(self, command, params):
627 """
628 Find implementation files matching the specified pattern
629 in the requested subdirectory of a BBPATH
630 """
631 pattern = params[0]
632 directory = params[1]
633
634 command.cooker.findFilesMatchingInDir(pattern, directory)
635 command.finishAsyncCommand()
636 findFilesMatchingInDir.needcache = False
637
638 def findConfigFilePath(self, command, params):
639 """
640 Find the path of the requested configuration file
641 """
642 configfile = params[0]
643
644 command.cooker.findConfigFilePath(configfile)
645 command.finishAsyncCommand()
646 findConfigFilePath.needcache = False
647
648 def showVersions(self, command, params):
649 """
650 Show the currently selected versions
651 """
652 command.cooker.showVersions()
653 command.finishAsyncCommand()
654 showVersions.needcache = True
655
656 def showEnvironmentTarget(self, command, params):
657 """
658 Print the environment of a target recipe
659 (needs the cache to work out which recipe to use)
660 """
661 pkg = params[0]
662
663 command.cooker.showEnvironment(None, pkg)
664 command.finishAsyncCommand()
665 showEnvironmentTarget.needcache = True
666
667 def showEnvironment(self, command, params):
668 """
669 Print the standard environment
670 or if specified the environment for a specified recipe
671 """
672 bfile = params[0]
673
674 command.cooker.showEnvironment(bfile)
675 command.finishAsyncCommand()
676 showEnvironment.needcache = False
677
678 def parseFiles(self, command, params):
679 """
680 Parse the .bb files
681 """
682 command.cooker.updateCache()
683 command.finishAsyncCommand()
684 parseFiles.needcache = True
685
686 def compareRevisions(self, command, params):
687 """
688 Parse the .bb files
689 """
690 if bb.fetch.fetcher_compare_revisions(command.cooker.data):
691 command.finishAsyncCommand(code=1)
692 else:
693 command.finishAsyncCommand()
694 compareRevisions.needcache = True
695
696 def triggerEvent(self, command, params):
697 """
698 Trigger a certain event
699 """
700 event = params[0]
701 bb.event.fire(eval(event), command.cooker.data)
702 command.currentAsyncCommand = None
703 triggerEvent.needcache = False
704
705 def resetCooker(self, command, params):
706 """
707 Reset the cooker to its initial state, thus forcing a reparse for
708 any async command that has the needcache property set to True
709 """
710 command.cooker.reset()
711 command.finishAsyncCommand()
712 resetCooker.needcache = False
713
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500714 def clientComplete(self, command, params):
715 """
716 Do the right thing when the controlling client exits
717 """
718 command.cooker.clientComplete()
719 command.finishAsyncCommand()
720 clientComplete.needcache = False
721
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500722 def findSigInfo(self, command, params):
723 """
724 Find signature info files via the signature generator
725 """
726 pn = params[0]
727 taskname = params[1]
728 sigs = params[2]
729 res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.data)
730 bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.data)
731 command.finishAsyncCommand()
732 findSigInfo.needcache = False