summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2017-07-19 11:56:08 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-07-21 08:41:12 +0100
commit388ae704bbd5116cfba517177b109fb18377f0e2 (patch)
tree22165780b820ea94e9e1c2eefc1a2d2526f4a3f9 /bitbake
parent9e8bbe7c6f83fe58d903bc43f09fafd6c6d25f14 (diff)
downloadpoky-388ae704bbd5116cfba517177b109fb18377f0e2.tar.gz
bitbake: tinfoil: add simple API for getting cached recipe information
A common task for tinfoil-using scripts is to iterate over all recipes. This isn't too difficult with the current API, but the pkg_* variables are a little awkward and are really designed for bitbake's internal usage - and it gets a bit more difficult when you want to access some of the other information such as packages and rprovides. To resolve this, create a new recipe info class and add an all_recipes() function to generate this for all recipes. Also add a get_recipe_info() function to get the information for a specific recipe (by PN). (It might perhaps be suggested that we already have a structure similar to this in the cache, however the one we add here is designed for external use and allows the internal structures to change if needed without affecting the API). (Bitbake rev: 308994028e59735ca726c5d2c1f0f85baccfe89d) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/tinfoil.py142
1 files changed, 142 insertions, 0 deletions
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py
index 456cbf80be..30d6c9af3e 100644
--- a/bitbake/lib/bb/tinfoil.py
+++ b/bitbake/lib/bb/tinfoil.py
@@ -217,6 +217,82 @@ class TinfoilCookerAdapter:
217 return self.tinfoil.find_best_provider(pn) 217 return self.tinfoil.find_best_provider(pn)
218 218
219 219
220class TinfoilRecipeInfo:
221 """
222 Provides a convenient representation of the cached information for a single recipe.
223 Some attributes are set on construction, others are read on-demand (which internally
224 may result in a remote procedure call to the bitbake server the first time).
225 Note that only information which is cached is available through this object - if
226 you need other variable values you will need to parse the recipe using
227 Tinfoil.parse_recipe().
228 """
229 def __init__(self, recipecache, d, pn, fn, fns):
230 self._recipecache = recipecache
231 self._d = d
232 self.pn = pn
233 self.fn = fn
234 self.fns = fns
235 self.inherit_files = recipecache.inherits[fn]
236 self.depends = recipecache.deps[fn]
237 (self.pe, self.pv, self.pr) = recipecache.pkg_pepvpr[fn]
238 self._cached_packages = None
239 self._cached_rprovides = None
240 self._cached_packages_dynamic = None
241
242 def __getattr__(self, name):
243 if name == 'alternates':
244 return [x for x in self.fns if x != self.fn]
245 elif name == 'rdepends':
246 return self._recipecache.rundeps[self.fn]
247 elif name == 'rrecommends':
248 return self._recipecache.runrecs[self.fn]
249 elif name == 'provides':
250 return self._recipecache.fn_provides[self.fn]
251 elif name == 'packages':
252 if self._cached_packages is None:
253 self._cached_packages = []
254 for pkg, fns in self._recipecache.packages.items():
255 if self.fn in fns:
256 self._cached_packages.append(pkg)
257 return self._cached_packages
258 elif name == 'packages_dynamic':
259 if self._cached_packages_dynamic is None:
260 self._cached_packages_dynamic = []
261 for pkg, fns in self._recipecache.packages_dynamic.items():
262 if self.fn in fns:
263 self._cached_packages_dynamic.append(pkg)
264 return self._cached_packages_dynamic
265 elif name == 'rprovides':
266 if self._cached_rprovides is None:
267 self._cached_rprovides = []
268 for pkg, fns in self._recipecache.rproviders.items():
269 if self.fn in fns:
270 self._cached_rprovides.append(pkg)
271 return self._cached_rprovides
272 else:
273 raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
274 def inherits(self, only_recipe=False):
275 """
276 Get the inherited classes for a recipe. Returns the class names only.
277 Parameters:
278 only_recipe: True to return only the classes inherited by the recipe
279 itself, False to return all classes inherited within
280 the context for the recipe (which includes globally
281 inherited classes).
282 """
283 if only_recipe:
284 global_inherit = [x for x in (self._d.getVar('BBINCLUDED') or '').split() if x.endswith('.bbclass')]
285 else:
286 global_inherit = []
287 for clsfile in self.inherit_files:
288 if only_recipe and clsfile in global_inherit:
289 continue
290 clsname = os.path.splitext(os.path.basename(clsfile))[0]
291 yield clsname
292 def __str__(self):
293 return '%s' % self.pn
294
295
220class Tinfoil: 296class Tinfoil:
221 297
222 def __init__(self, output=sys.stdout, tracking=False, setup_logging=True): 298 def __init__(self, output=sys.stdout, tracking=False, setup_logging=True):
@@ -401,6 +477,72 @@ class Tinfoil:
401 def get_file_appends(self, fn): 477 def get_file_appends(self, fn):
402 return self.run_command('getFileAppends', fn) 478 return self.run_command('getFileAppends', fn)
403 479
480 def all_recipes(self, mc='', sort=True):
481 """
482 Enable iterating over all recipes in the current configuration.
483 Returns an iterator over TinfoilRecipeInfo objects created on demand.
484 Parameters:
485 mc: The multiconfig, default of '' uses the main configuration.
486 sort: True to sort recipes alphabetically (default), False otherwise
487 """
488 recipecache = self.cooker.recipecaches[mc]
489 if sort:
490 recipes = sorted(recipecache.pkg_pn.items())
491 else:
492 recipes = recipecache.pkg_pn.items()
493 for pn, fns in recipes:
494 prov = self.find_best_provider(pn)
495 recipe = TinfoilRecipeInfo(recipecache,
496 self.config_data,
497 pn=pn,
498 fn=prov[3],
499 fns=fns)
500 yield recipe
501
502 def all_recipe_files(self, mc='', variants=True, preferred_only=False):
503 """
504 Enable iterating over all recipe files in the current configuration.
505 Returns an iterator over file paths.
506 Parameters:
507 mc: The multiconfig, default of '' uses the main configuration.
508 variants: True to include variants of recipes created through
509 BBCLASSEXTEND (default) or False to exclude them
510 preferred_only: True to include only the preferred recipe where
511 multiple exist providing the same PN, False to list
512 all recipes
513 """
514 recipecache = self.cooker.recipecaches[mc]
515 if preferred_only:
516 files = []
517 for pn in recipecache.pkg_pn.keys():
518 prov = self.find_best_provider(pn)
519 files.append(prov[3])
520 else:
521 files = recipecache.pkg_fn.keys()
522 for fn in sorted(files):
523 if not variants and fn.startswith('virtual:'):
524 continue
525 yield fn
526
527
528 def get_recipe_info(self, pn, mc=''):
529 """
530 Get information on a specific recipe in the current configuration by name (PN).
531 Returns a TinfoilRecipeInfo object created on demand.
532 Parameters:
533 mc: The multiconfig, default of '' uses the main configuration.
534 """
535 recipecache = self.cooker.recipecaches[mc]
536 prov = self.find_best_provider(pn)
537 fn = prov[3]
538 actual_pn = recipecache.pkg_fn[fn]
539 recipe = TinfoilRecipeInfo(recipecache,
540 self.config_data,
541 pn=actual_pn,
542 fn=fn,
543 fns=recipecache.pkg_pn[actual_pn])
544 return recipe
545
404 def parse_recipe(self, pn): 546 def parse_recipe(self, pn):
405 """ 547 """
406 Parse the specified recipe and return a datastore object 548 Parse the specified recipe and return a datastore object