summaryrefslogtreecommitdiff
path: root/import-layers/yocto-poky/bitbake/lib/bblayers/query.py
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/bitbake/lib/bblayers/query.py')
-rw-r--r--import-layers/yocto-poky/bitbake/lib/bblayers/query.py501
1 files changed, 0 insertions, 501 deletions
diff --git a/import-layers/yocto-poky/bitbake/lib/bblayers/query.py b/import-layers/yocto-poky/bitbake/lib/bblayers/query.py
deleted file mode 100644
index 9294dfa88..000000000
--- a/import-layers/yocto-poky/bitbake/lib/bblayers/query.py
+++ /dev/null
@@ -1,501 +0,0 @@
-import collections
-import fnmatch
-import logging
-import sys
-import os
-import re
-
-import bb.utils
-
-from bblayers.common import LayerPlugin
-
-logger = logging.getLogger('bitbake-layers')
-
-
-def plugin_init(plugins):
- return QueryPlugin()
-
-
-class QueryPlugin(LayerPlugin):
- def do_show_layers(self, args):
- """show current configured layers."""
- logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
- logger.plain('=' * 74)
- for layer, _, regex, pri in self.tinfoil.cooker.bbfile_config_priorities:
- layerdir = self.bbfile_collections.get(layer, None)
- layername = self.get_layer_name(layerdir)
- logger.plain("%s %s %d" % (layername.ljust(20), layerdir.ljust(40), pri))
-
- def version_str(self, pe, pv, pr = None):
- verstr = "%s" % pv
- if pr:
- verstr = "%s-%s" % (verstr, pr)
- if pe:
- verstr = "%s:%s" % (pe, verstr)
- return verstr
-
- def do_show_overlayed(self, args):
- """list overlayed recipes (where the same recipe exists in another layer)
-
-Lists the names of overlayed recipes and the available versions in each
-layer, with the preferred version first. Note that skipped recipes that
-are overlayed will also be listed, with a " (skipped)" suffix.
-"""
-
- items_listed = self.list_recipes('Overlayed recipes', None, True, args.same_version, args.filenames, True, None)
-
- # Check for overlayed .bbclass files
- classes = collections.defaultdict(list)
- for layerdir in self.bblayers:
- classdir = os.path.join(layerdir, 'classes')
- if os.path.exists(classdir):
- for classfile in os.listdir(classdir):
- if os.path.splitext(classfile)[1] == '.bbclass':
- classes[classfile].append(classdir)
-
- # Locating classes and other files is a bit more complicated than recipes -
- # layer priority is not a factor; instead BitBake uses the first matching
- # file in BBPATH, which is manipulated directly by each layer's
- # conf/layer.conf in turn, thus the order of layers in bblayers.conf is a
- # factor - however, each layer.conf is free to either prepend or append to
- # BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
- # not be exactly the order present in bblayers.conf either.
- bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
- overlayed_class_found = False
- for (classfile, classdirs) in classes.items():
- if len(classdirs) > 1:
- if not overlayed_class_found:
- logger.plain('=== Overlayed classes ===')
- overlayed_class_found = True
-
- mainfile = bb.utils.which(bbpath, os.path.join('classes', classfile))
- if args.filenames:
- logger.plain('%s' % mainfile)
- else:
- # We effectively have to guess the layer here
- logger.plain('%s:' % classfile)
- mainlayername = '?'
- for layerdir in self.bblayers:
- classdir = os.path.join(layerdir, 'classes')
- if mainfile.startswith(classdir):
- mainlayername = self.get_layer_name(layerdir)
- logger.plain(' %s' % mainlayername)
- for classdir in classdirs:
- fullpath = os.path.join(classdir, classfile)
- if fullpath != mainfile:
- if args.filenames:
- print(' %s' % fullpath)
- else:
- print(' %s' % self.get_layer_name(os.path.dirname(classdir)))
-
- if overlayed_class_found:
- items_listed = True;
-
- if not items_listed:
- logger.plain('No overlayed files found.')
-
- def do_show_recipes(self, args):
- """list available recipes, showing the layer they are provided by
-
-Lists the names of recipes and the available versions in each
-layer, with the preferred version first. Optionally you may specify
-pnspec to match a specified recipe name (supports wildcards). Note that
-skipped recipes will also be listed, with a " (skipped)" suffix.
-"""
-
- inheritlist = args.inherits.split(',') if args.inherits else []
- if inheritlist or args.pnspec or args.multiple:
- title = 'Matching recipes:'
- else:
- title = 'Available recipes:'
- self.list_recipes(title, args.pnspec, False, False, args.filenames, args.multiple, inheritlist)
-
- def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only, inherits):
- if inherits:
- bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
- for classname in inherits:
- classfile = 'classes/%s.bbclass' % classname
- if not bb.utils.which(bbpath, classfile, history=False):
- logger.error('No class named %s found in BBPATH', classfile)
- sys.exit(1)
-
- pkg_pn = self.tinfoil.cooker.recipecaches[''].pkg_pn
- (latest_versions, preferred_versions) = self.tinfoil.find_providers()
- allproviders = self.tinfoil.get_all_providers()
-
- # Ensure we list skipped recipes
- # We are largely guessing about PN, PV and the preferred version here,
- # but we have no choice since skipped recipes are not fully parsed
- skiplist = list(self.tinfoil.cooker.skiplist.keys())
- for fn in skiplist:
- recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
- p = recipe_parts[0]
- if len(recipe_parts) > 1:
- ver = (None, recipe_parts[1], None)
- else:
- ver = (None, 'unknown', None)
- allproviders[p].append((ver, fn))
- if not p in pkg_pn:
- pkg_pn[p] = 'dummy'
- preferred_versions[p] = (ver, fn)
-
- def print_item(f, pn, ver, layer, ispref):
- if f in skiplist:
- skipped = ' (skipped)'
- else:
- skipped = ''
- if show_filenames:
- if ispref:
- logger.plain("%s%s", f, skipped)
- else:
- logger.plain(" %s%s", f, skipped)
- else:
- if ispref:
- logger.plain("%s:", pn)
- logger.plain(" %s %s%s", layer.ljust(20), ver, skipped)
-
- global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
- cls_re = re.compile('classes/')
-
- preffiles = []
- items_listed = False
- for p in sorted(pkg_pn):
- if pnspec:
- found=False
- for pnm in pnspec:
- if fnmatch.fnmatch(p, pnm):
- found=True
- break
- if not found:
- continue
-
- if len(allproviders[p]) > 1 or not show_multi_provider_only:
- pref = preferred_versions[p]
- realfn = bb.cache.virtualfn2realfn(pref[1])
- preffile = realfn[0]
-
- # We only display once per recipe, we should prefer non extended versions of the
- # recipe if present (so e.g. in OpenEmbedded, openssl rather than nativesdk-openssl
- # which would otherwise sort first).
- if realfn[1] and realfn[0] in self.tinfoil.cooker.recipecaches[''].pkg_fn:
- continue
-
- if inherits:
- matchcount = 0
- recipe_inherits = self.tinfoil.cooker_data.inherits.get(preffile, [])
- for cls in recipe_inherits:
- if cls_re.match(cls):
- continue
- classname = os.path.splitext(os.path.basename(cls))[0]
- if classname in global_inherit:
- continue
- elif classname in inherits:
- matchcount += 1
- if matchcount != len(inherits):
- # No match - skip this recipe
- continue
-
- if preffile not in preffiles:
- preflayer = self.get_file_layer(preffile)
- multilayer = False
- same_ver = True
- provs = []
- for prov in allproviders[p]:
- provfile = bb.cache.virtualfn2realfn(prov[1])[0]
- provlayer = self.get_file_layer(provfile)
- provs.append((provfile, provlayer, prov[0]))
- if provlayer != preflayer:
- multilayer = True
- if prov[0] != pref[0]:
- same_ver = False
-
- if (multilayer or not show_overlayed_only) and (same_ver or not show_same_ver_only):
- if not items_listed:
- logger.plain('=== %s ===' % title)
- items_listed = True
- print_item(preffile, p, self.version_str(pref[0][0], pref[0][1]), preflayer, True)
- for (provfile, provlayer, provver) in provs:
- if provfile != preffile:
- print_item(provfile, p, self.version_str(provver[0], provver[1]), provlayer, False)
- # Ensure we don't show two entries for BBCLASSEXTENDed recipes
- preffiles.append(preffile)
-
- return items_listed
-
- def get_file_layer(self, filename):
- layerdir = self.get_file_layerdir(filename)
- if layerdir:
- return self.get_layer_name(layerdir)
- else:
- return '?'
-
- def get_file_layerdir(self, filename):
- layer = bb.utils.get_file_layer(filename, self.tinfoil.config_data)
- return self.bbfile_collections.get(layer, None)
-
- def remove_layer_prefix(self, f):
- """Remove the layer_dir prefix, e.g., f = /path/to/layer_dir/foo/blah, the
- return value will be: layer_dir/foo/blah"""
- f_layerdir = self.get_file_layerdir(f)
- if not f_layerdir:
- return f
- prefix = os.path.join(os.path.dirname(f_layerdir), '')
- return f[len(prefix):] if f.startswith(prefix) else f
-
- def do_show_appends(self, args):
- """list bbappend files and recipe files they apply to
-
-Lists recipes with the bbappends that apply to them as subitems.
-"""
- if args.pnspec:
- logger.plain('=== Matched appended recipes ===')
- else:
- logger.plain('=== Appended recipes ===')
-
- pnlist = list(self.tinfoil.cooker_data.pkg_pn.keys())
- pnlist.sort()
- appends = False
- for pn in pnlist:
- if args.pnspec:
- found=False
- for pnm in args.pnspec:
- if fnmatch.fnmatch(pn, pnm):
- found=True
- break
- if not found:
- continue
-
- if self.show_appends_for_pn(pn):
- appends = True
-
- if not args.pnspec and self.show_appends_for_skipped():
- appends = True
-
- if not appends:
- logger.plain('No append files found')
-
- def show_appends_for_pn(self, pn):
- filenames = self.tinfoil.cooker_data.pkg_pn[pn]
-
- best = self.tinfoil.find_best_provider(pn)
- best_filename = os.path.basename(best[3])
-
- return self.show_appends_output(filenames, best_filename)
-
- def show_appends_for_skipped(self):
- filenames = [os.path.basename(f)
- for f in self.tinfoil.cooker.skiplist.keys()]
- return self.show_appends_output(filenames, None, " (skipped)")
-
- def show_appends_output(self, filenames, best_filename, name_suffix = ''):
- appended, missing = self.get_appends_for_files(filenames)
- if appended:
- for basename, appends in appended:
- logger.plain('%s%s:', basename, name_suffix)
- for append in appends:
- logger.plain(' %s', append)
-
- if best_filename:
- if best_filename in missing:
- logger.warning('%s: missing append for preferred version',
- best_filename)
- return True
- else:
- return False
-
- def get_appends_for_files(self, filenames):
- appended, notappended = [], []
- for filename in filenames:
- _, cls, _ = bb.cache.virtualfn2realfn(filename)
- if cls:
- continue
-
- basename = os.path.basename(filename)
- appends = self.tinfoil.cooker.collection.get_file_appends(basename)
- if appends:
- appended.append((basename, list(appends)))
- else:
- notappended.append(basename)
- return appended, notappended
-
- def do_show_cross_depends(self, args):
- """Show dependencies between recipes that cross layer boundaries.
-
-Figure out the dependencies between recipes that cross layer boundaries.
-
-NOTE: .bbappend files can impact the dependencies.
-"""
- ignore_layers = (args.ignore or '').split(',')
-
- pkg_fn = self.tinfoil.cooker_data.pkg_fn
- bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
- self.require_re = re.compile(r"require\s+(.+)")
- self.include_re = re.compile(r"include\s+(.+)")
- self.inherit_re = re.compile(r"inherit\s+(.+)")
-
- global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
-
- # The bb's DEPENDS and RDEPENDS
- for f in pkg_fn:
- f = bb.cache.virtualfn2realfn(f)[0]
- # Get the layername that the file is in
- layername = self.get_file_layer(f)
-
- # The DEPENDS
- deps = self.tinfoil.cooker_data.deps[f]
- for pn in deps:
- if pn in self.tinfoil.cooker_data.pkg_pn:
- best = self.tinfoil.find_best_provider(pn)
- self.check_cross_depends("DEPENDS", layername, f, best[3], args.filenames, ignore_layers)
-
- # The RDPENDS
- all_rdeps = self.tinfoil.cooker_data.rundeps[f].values()
- # Remove the duplicated or null one.
- sorted_rdeps = {}
- # The all_rdeps is the list in list, so we need two for loops
- for k1 in all_rdeps:
- for k2 in k1:
- sorted_rdeps[k2] = 1
- all_rdeps = sorted_rdeps.keys()
- for rdep in all_rdeps:
- all_p, best = self.tinfoil.get_runtime_providers(rdep)
- if all_p:
- if f in all_p:
- # The recipe provides this one itself, ignore
- continue
- self.check_cross_depends("RDEPENDS", layername, f, best, args.filenames, ignore_layers)
-
- # The RRECOMMENDS
- all_rrecs = self.tinfoil.cooker_data.runrecs[f].values()
- # Remove the duplicated or null one.
- sorted_rrecs = {}
- # The all_rrecs is the list in list, so we need two for loops
- for k1 in all_rrecs:
- for k2 in k1:
- sorted_rrecs[k2] = 1
- all_rrecs = sorted_rrecs.keys()
- for rrec in all_rrecs:
- all_p, best = self.tinfoil.get_runtime_providers(rrec)
- if all_p:
- if f in all_p:
- # The recipe provides this one itself, ignore
- continue
- self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)
-
- # The inherit class
- cls_re = re.compile('classes/')
- if f in self.tinfoil.cooker_data.inherits:
- inherits = self.tinfoil.cooker_data.inherits[f]
- for cls in inherits:
- # The inherits' format is [classes/cls, /path/to/classes/cls]
- # ignore the classes/cls.
- if not cls_re.match(cls):
- classname = os.path.splitext(os.path.basename(cls))[0]
- if classname in global_inherit:
- continue
- inherit_layername = self.get_file_layer(cls)
- if inherit_layername != layername and not inherit_layername in ignore_layers:
- if not args.filenames:
- f_short = self.remove_layer_prefix(f)
- cls = self.remove_layer_prefix(cls)
- else:
- f_short = f
- logger.plain("%s inherits %s" % (f_short, cls))
-
- # The 'require/include xxx' in the bb file
- pv_re = re.compile(r"\${PV}")
- with open(f, 'r') as fnfile:
- line = fnfile.readline()
- while line:
- m, keyword = self.match_require_include(line)
- # Found the 'require/include xxxx'
- if m:
- needed_file = m.group(1)
- # Replace the ${PV} with the real PV
- if pv_re.search(needed_file) and f in self.tinfoil.cooker_data.pkg_pepvpr:
- pv = self.tinfoil.cooker_data.pkg_pepvpr[f][1]
- needed_file = re.sub(r"\${PV}", pv, needed_file)
- self.print_cross_files(bbpath, keyword, layername, f, needed_file, args.filenames, ignore_layers)
- line = fnfile.readline()
-
- # The "require/include xxx" in conf/machine/*.conf, .inc and .bbclass
- conf_re = re.compile(".*/conf/machine/[^\/]*\.conf$")
- inc_re = re.compile(".*\.inc$")
- # The "inherit xxx" in .bbclass
- bbclass_re = re.compile(".*\.bbclass$")
- for layerdir in self.bblayers:
- layername = self.get_layer_name(layerdir)
- for dirpath, dirnames, filenames in os.walk(layerdir):
- for name in filenames:
- f = os.path.join(dirpath, name)
- s = conf_re.match(f) or inc_re.match(f) or bbclass_re.match(f)
- if s:
- with open(f, 'r') as ffile:
- line = ffile.readline()
- while line:
- m, keyword = self.match_require_include(line)
- # Only bbclass has the "inherit xxx" here.
- bbclass=""
- if not m and f.endswith(".bbclass"):
- m, keyword = self.match_inherit(line)
- bbclass=".bbclass"
- # Find a 'require/include xxxx'
- if m:
- self.print_cross_files(bbpath, keyword, layername, f, m.group(1) + bbclass, args.filenames, ignore_layers)
- line = ffile.readline()
-
- def print_cross_files(self, bbpath, keyword, layername, f, needed_filename, show_filenames, ignore_layers):
- """Print the depends that crosses a layer boundary"""
- needed_file = bb.utils.which(bbpath, needed_filename)
- if needed_file:
- # Which layer is this file from
- needed_layername = self.get_file_layer(needed_file)
- if needed_layername != layername and not needed_layername in ignore_layers:
- if not show_filenames:
- f = self.remove_layer_prefix(f)
- needed_file = self.remove_layer_prefix(needed_file)
- logger.plain("%s %s %s" %(f, keyword, needed_file))
-
- def match_inherit(self, line):
- """Match the inherit xxx line"""
- return (self.inherit_re.match(line), "inherits")
-
- def match_require_include(self, line):
- """Match the require/include xxx line"""
- m = self.require_re.match(line)
- keyword = "requires"
- if not m:
- m = self.include_re.match(line)
- keyword = "includes"
- return (m, keyword)
-
- def check_cross_depends(self, keyword, layername, f, needed_file, show_filenames, ignore_layers):
- """Print the DEPENDS/RDEPENDS file that crosses a layer boundary"""
- best_realfn = bb.cache.virtualfn2realfn(needed_file)[0]
- needed_layername = self.get_file_layer(best_realfn)
- if needed_layername != layername and not needed_layername in ignore_layers:
- if not show_filenames:
- f = self.remove_layer_prefix(f)
- best_realfn = self.remove_layer_prefix(best_realfn)
-
- logger.plain("%s %s %s" % (f, keyword, best_realfn))
-
- def register_commands(self, sp):
- self.add_command(sp, 'show-layers', self.do_show_layers, parserecipes=False)
-
- parser_show_overlayed = self.add_command(sp, 'show-overlayed', self.do_show_overlayed)
- parser_show_overlayed.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
- parser_show_overlayed.add_argument('-s', '--same-version', help='only list overlayed recipes where the version is the same', action='store_true')
-
- parser_show_recipes = self.add_command(sp, 'show-recipes', self.do_show_recipes)
- parser_show_recipes.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
- parser_show_recipes.add_argument('-m', '--multiple', help='only list where multiple recipes (in the same layer or different layers) exist for the same recipe name', action='store_true')
- parser_show_recipes.add_argument('-i', '--inherits', help='only list recipes that inherit the named class(es) - separate multiple classes using , (without spaces)', metavar='CLASS', default='')
- parser_show_recipes.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
-
- parser_show_appends = self.add_command(sp, 'show-appends', self.do_show_appends)
- parser_show_appends.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
-
- parser_show_cross_depends = self.add_command(sp, 'show-cross-depends', self.do_show_cross_depends)
- parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true')
- parser_show_cross_depends.add_argument('-i', '--ignore', help='ignore dependencies on items in the specified layer(s) (split multiple layer names with commas, no spaces)', metavar='LAYERNAME')