summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/command.py
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2016-12-13 20:07:06 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-12-14 12:25:07 +0000
commit7d5c9860de05efc4272256ccefc530113f01d24e (patch)
tree659eb51c50941c2920215512e38d59da9cb85ee5 /bitbake/lib/bb/command.py
parente271d7dc606185130e0e47327205bd423490b7c2 (diff)
downloadpoky-7d5c9860de05efc4272256ccefc530113f01d24e.tar.gz
bitbake: tinfoil: rewrite as a wrapper around the UI
Rewrite tinfoil as a wrapper around the UI, instead of the earlier approach of starting up just enough of cooker to do what we want. This has several advantages: * It now works when bitbake is memory-resident instead of failing with "ERROR: Only one copy of bitbake should be run against a build directory". * We can now connect an actual UI, thus you get things like the recipe parsing / cache loading progress bar and parse error handling for free * We can now handle events generated by the server if we wish to do so * We can potentially extend this to do more stuff, e.g. actually running build operations - this needs to be made more practical before we can use it though (since you effectively have to become the UI yourself for this at the moment.) The downside is that tinfoil no longer has direct access to cooker, the global datastore, or the cache. To mitigate this I have extended data_smart to provide remote access capability for the datastore, and created "fake" cooker and cooker.recipecache / cooker.collection adapter objects in order to avoid breaking too many tinfoil-using scripts that might be out there (we've never officially documented tinfoil or BitBake's internal code, but we can still make accommodations where practical). I've at least gone far enough to support all of the utilities that use tinfoil in OE-Core with some changes, but I know there are scripts such as Chris Larson's "bb" out there that do make other calls into BitBake code that I'm not currently providing access to through the adapters. Part of the fix for [YOCTO #5470]. (Bitbake rev: 3bbf8d611c859f74d563778115677a04f5c4ab43) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/command.py')
-rw-r--r--bitbake/lib/bb/command.py195
1 files changed, 195 insertions, 0 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index 012b35faf6..d5be86dab8 100644
--- a/bitbake/lib/bb/command.py
+++ b/bitbake/lib/bb/command.py
@@ -28,8 +28,15 @@ and must not trigger events, directly or indirectly.
28Commands are queued in a CommandQueue 28Commands are queued in a CommandQueue
29""" 29"""
30 30
31from collections import OrderedDict, defaultdict
32
31import bb.event 33import bb.event
32import bb.cooker 34import bb.cooker
35import bb.remotedata
36
37class DataStoreConnectionHandle(object):
38 def __init__(self, dsindex=0):
39 self.dsindex = dsindex
33 40
34class CommandCompleted(bb.event.Event): 41class CommandCompleted(bb.event.Event):
35 pass 42 pass
@@ -55,6 +62,7 @@ class Command:
55 self.cooker = cooker 62 self.cooker = cooker
56 self.cmds_sync = CommandsSync() 63 self.cmds_sync = CommandsSync()
57 self.cmds_async = CommandsAsync() 64 self.cmds_async = CommandsAsync()
65 self.remotedatastores = bb.remotedata.RemoteDatastores(cooker)
58 66
59 # FIXME Add lock for this 67 # FIXME Add lock for this
60 self.currentAsyncCommand = None 68 self.currentAsyncCommand = None
@@ -298,6 +306,193 @@ class CommandsSync:
298 command.cooker.updateConfigOpts(options, environment) 306 command.cooker.updateConfigOpts(options, environment)
299 updateConfig.needconfig = False 307 updateConfig.needconfig = False
300 308
309 def parseConfiguration(self, command, params):
310 """Instruct bitbake to parse its configuration
311 NOTE: it is only necessary to call this if you aren't calling any normal action
312 (otherwise parsing is taken care of automatically)
313 """
314 command.cooker.parseConfiguration()
315 parseConfiguration.needconfig = False
316
317 def getLayerPriorities(self, command, params):
318 ret = []
319 # regex objects cannot be marshalled by xmlrpc
320 for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
321 ret.append((collection, pattern, regex.pattern, pri))
322 return ret
323 getLayerPriorities.readonly = True
324
325 def getRecipes(self, command, params):
326 try:
327 mc = params[0]
328 except IndexError:
329 mc = ''
330 return list(command.cooker.recipecaches[mc].pkg_pn.items())
331 getRecipes.readonly = True
332
333 def getRecipeDepends(self, command, params):
334 try:
335 mc = params[0]
336 except IndexError:
337 mc = ''
338 return list(command.cooker.recipecaches[mc].deps.items())
339 getRecipeDepends.readonly = True
340
341 def getRecipeVersions(self, command, params):
342 try:
343 mc = params[0]
344 except IndexError:
345 mc = ''
346 return command.cooker.recipecaches[mc].pkg_pepvpr
347 getRecipeVersions.readonly = True
348
349 def getRuntimeDepends(self, command, params):
350 ret = []
351 try:
352 mc = params[0]
353 except IndexError:
354 mc = ''
355 rundeps = command.cooker.recipecaches[mc].rundeps
356 for key, value in rundeps.items():
357 if isinstance(value, defaultdict):
358 value = dict(value)
359 ret.append((key, value))
360 return ret
361 getRuntimeDepends.readonly = True
362
363 def getRuntimeRecommends(self, command, params):
364 ret = []
365 try:
366 mc = params[0]
367 except IndexError:
368 mc = ''
369 runrecs = command.cooker.recipecaches[mc].runrecs
370 for key, value in runrecs.items():
371 if isinstance(value, defaultdict):
372 value = dict(value)
373 ret.append((key, value))
374 return ret
375 getRuntimeRecommends.readonly = True
376
377 def getRecipeInherits(self, command, params):
378 try:
379 mc = params[0]
380 except IndexError:
381 mc = ''
382 return command.cooker.recipecaches[mc].inherits
383 getRecipeInherits.readonly = True
384
385 def getBbFilePriority(self, command, params):
386 try:
387 mc = params[0]
388 except IndexError:
389 mc = ''
390 return command.cooker.recipecaches[mc].bbfile_priority
391 getBbFilePriority.readonly = True
392
393 def getDefaultPreference(self, command, params):
394 try:
395 mc = params[0]
396 except IndexError:
397 mc = ''
398 return command.cooker.recipecaches[mc].pkg_dp
399 getDefaultPreference.readonly = True
400
401 def getSkippedRecipes(self, command, params):
402 # Return list sorted by reverse priority order
403 import bb.cache
404 skipdict = OrderedDict(sorted(command.cooker.skiplist.items(),
405 key=lambda x: (-command.cooker.collection.calc_bbfile_priority(bb.cache.virtualfn2realfn(x[0])[0]), x[0])))
406 return list(skipdict.items())
407 getSkippedRecipes.readonly = True
408
409 def getOverlayedRecipes(self, command, params):
410 return list(command.cooker.collection.overlayed.items())
411 getOverlayedRecipes.readonly = True
412
413 def getFileAppends(self, command, params):
414 fn = params[0]
415 return command.cooker.collection.get_file_appends(fn)
416 getFileAppends.readonly = True
417
418 def getAllAppends(self, command, params):
419 return command.cooker.collection.bbappends
420 getAllAppends.readonly = True
421
422 def findProviders(self, command, params):
423 return command.cooker.findProviders()
424 findProviders.readonly = True
425
426 def findBestProvider(self, command, params):
427 pn = params[0]
428 return command.cooker.findBestProvider(pn)
429 findBestProvider.readonly = True
430
431 def allProviders(self, command, params):
432 try:
433 mc = params[0]
434 except IndexError:
435 mc = ''
436 return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
437 allProviders.readonly = True
438
439 def getRuntimeProviders(self, command, params):
440 rprovide = params[0]
441 try:
442 mc = params[1]
443 except IndexError:
444 mc = ''
445 all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
446 if all_p:
447 best = bb.providers.filterProvidersRunTime(all_p, rprovide,
448 command.cooker.data,
449 command.cooker.recipecaches[mc])[0][0]
450 else:
451 best = None
452 return all_p, best
453 getRuntimeProviders.readonly = True
454
455 def dataStoreConnectorFindVar(self, command, params):
456 dsindex = params[0]
457 name = params[1]
458 datastore = command.remotedatastores[dsindex]
459 value = datastore._findVar(name)
460
461 if value:
462 content = value.get('_content', None)
463 if isinstance(content, bb.data_smart.DataSmart):
464 # Value is a datastore (e.g. BB_ORIGENV) - need to handle this carefully
465 idx = command.remotedatastores.check_store(content, True)
466 return {'_content': DataStoreConnectionHandle(idx), '_connector_origtype': 'DataStoreConnectionHandle'}
467 elif isinstance(content, set):
468 return {'_content': list(content), '_connector_origtype': 'set'}
469 return value
470 dataStoreConnectorFindVar.readonly = True
471
472 def dataStoreConnectorGetKeys(self, command, params):
473 dsindex = params[0]
474 datastore = command.remotedatastores[dsindex]
475 return list(datastore.keys())
476 dataStoreConnectorGetKeys.readonly = True
477
478 def dataStoreConnectorGetVarHistory(self, command, params):
479 dsindex = params[0]
480 name = params[1]
481 datastore = command.remotedatastores[dsindex]
482 return datastore.varhistory.variable(name)
483 dataStoreConnectorGetVarHistory.readonly = True
484
485 def dataStoreConnectorExpandPythonRef(self, command, params):
486 dsindex = params[0]
487 varname = params[1]
488 expr = params[2]
489 if dsindex:
490 datastore = self.dataStores[dsindex]
491 else:
492 datastore = command.cooker.data
493 varparse = bb.data_smart.VariableParse(varname, datastore)
494 return varparse.python_sub(expr)
495
301class CommandsAsync: 496class CommandsAsync:
302 """ 497 """
303 A class of asynchronous commands 498 A class of asynchronous commands