bitbake: tinfoil: create simple interface for bitbake-based utilities

The code to initialise BitBake within bitbake-layers should be useful
for other utilities that need to query configuration or recipe
information, so refactor it out into its own class, "Tinfoil" (to
continue with our cooking metaphor).

(Bitbake rev: e5707e3938ace47c4a8d1fa2e81583fd4dc6b95d)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Paul Eggleton 2012-08-27 21:44:31 +01:00 committed by Richard Purdie
parent e8d87846e3
commit 56a66a1fab
1 changed files with 47 additions and 99 deletions

View File

@ -6,10 +6,22 @@
# Copyright (C) 2011 Mentor Graphics Corporation # Copyright (C) 2011 Mentor Graphics Corporation
# Copyright (C) 2012 Intel Corporation # Copyright (C) 2012 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import cmd import cmd
import logging import logging
import warnings
import os import os
import sys import sys
import fnmatch import fnmatch
@ -23,26 +35,14 @@ import bb.cache
import bb.cooker import bb.cooker
import bb.providers import bb.providers
import bb.utils import bb.utils
from bb.cooker import state import bb.tinfoil
import bb.fetch2
logger = logging.getLogger('BitBake') logger = logging.getLogger('BitBake')
warnings.filterwarnings("ignore", category=DeprecationWarning)
def main(args): def main(args):
# Set up logging cmds = Commands()
console = logging.StreamHandler(sys.stdout)
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
bb.msg.addDefaultlogFilter(console)
console.setFormatter(format)
logger.addHandler(console)
initialenv = os.environ.copy()
bb.utils.clean_environment()
cmds = Commands(initialenv)
if args: if args:
# Allow user to specify e.g. show-layers instead of show_layers # Allow user to specify e.g. show-layers instead of show_layers
args = [args[0].replace('-', '_')] + args[1:] args = [args[0].replace('-', '_')] + args[1:]
@ -53,46 +53,11 @@ def main(args):
class Commands(cmd.Cmd): class Commands(cmd.Cmd):
def __init__(self, initialenv): def __init__(self):
cmd.Cmd.__init__(self) cmd.Cmd.__init__(self)
self.bbhandler = bb.tinfoil.Tinfoil()
self.returncode = 0 self.returncode = 0
self.config = Config(parse_only=True) self.bblayers = (self.bbhandler.config_data.getVar('BBLAYERS', True) or "").split()
self.cooker = bb.cooker.BBCooker(self.config,
self.register_idle_function,
initialenv)
self.config_data = self.cooker.configuration.data
bb.providers.logger.setLevel(logging.ERROR)
self.cooker_data = None
self.bblayers = (self.config_data.getVar('BBLAYERS', True) or "").split()
def register_idle_function(self, function, data):
pass
def prepare_cooker(self):
sys.stderr.write("Parsing recipes..")
logger.setLevel(logging.WARNING)
try:
while self.cooker.state in (state.initial, state.parsing):
self.cooker.updateCache()
except KeyboardInterrupt:
self.cooker.shutdown()
self.cooker.updateCache()
sys.exit(2)
logger.setLevel(logging.INFO)
sys.stderr.write("done.\n")
self.cooker_data = self.cooker.status
self.cooker_data.appends = self.cooker.appendlist
def check_prepare_cooker(self, config_only = False):
if not self.cooker_data:
if config_only:
self.cooker.parseConfiguration()
self.cooker_data = self.cooker.status
else:
self.prepare_cooker()
def default(self, line): def default(self, line):
"""Handle unrecognised commands""" """Handle unrecognised commands"""
@ -117,13 +82,13 @@ class Commands(cmd.Cmd):
def do_show_layers(self, args): def do_show_layers(self, args):
"""show current configured layers""" """show current configured layers"""
self.check_prepare_cooker(config_only = True) self.bbhandler.prepare(config_only = True)
logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority")) logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
logger.plain('=' * 74) logger.plain('=' * 74)
for layerdir in self.bblayers: for layerdir in self.bblayers:
layername = self.get_layer_name(layerdir) layername = self.get_layer_name(layerdir)
layerpri = 0 layerpri = 0
for layer, _, regex, pri in self.cooker.status.bbfile_config_priorities: for layer, _, regex, pri in self.bbhandler.cooker.status.bbfile_config_priorities:
if regex.match(os.path.join(layerdir, 'test')): if regex.match(os.path.join(layerdir, 'test')):
layerpri = pri layerpri = pri
break break
@ -154,7 +119,7 @@ Options:
recipes with the ones they overlay indented underneath recipes with the ones they overlay indented underneath
-s only list overlayed recipes where the version is the same -s only list overlayed recipes where the version is the same
""" """
self.check_prepare_cooker() self.bbhandler.prepare()
show_filenames = False show_filenames = False
show_same_ver_only = False show_same_ver_only = False
@ -186,7 +151,7 @@ Options:
# factor - however, each layer.conf is free to either prepend or append to # 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 # BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
# not be exactly the order present in bblayers.conf either. # not be exactly the order present in bblayers.conf either.
bbpath = str(self.config_data.getVar('BBPATH', True)) bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
overlayed_class_found = False overlayed_class_found = False
for (classfile, classdirs) in classes.items(): for (classfile, classdirs) in classes.items():
if len(classdirs) > 1: if len(classdirs) > 1:
@ -237,7 +202,7 @@ Options:
-m only list where multiple recipes (in the same layer or different -m only list where multiple recipes (in the same layer or different
layers) exist for the same recipe name layers) exist for the same recipe name
""" """
self.check_prepare_cooker() self.bbhandler.prepare()
show_filenames = False show_filenames = False
show_multi_provider_only = False show_multi_provider_only = False
@ -259,15 +224,15 @@ Options:
def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only): def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only):
pkg_pn = self.cooker.status.pkg_pn pkg_pn = self.bbhandler.cooker.status.pkg_pn
(latest_versions, preferred_versions) = bb.providers.findProviders(self.cooker.configuration.data, self.cooker.status, pkg_pn) (latest_versions, preferred_versions) = bb.providers.findProviders(self.bbhandler.cooker.configuration.data, self.bbhandler.cooker.status, pkg_pn)
allproviders = bb.providers.allProviders(self.cooker.status) allproviders = bb.providers.allProviders(self.bbhandler.cooker.status)
# Ensure we list skipped recipes # Ensure we list skipped recipes
# We are largely guessing about PN, PV and the preferred version here, # We are largely guessing about PN, PV and the preferred version here,
# but we have no choice since skipped recipes are not fully parsed # but we have no choice since skipped recipes are not fully parsed
skiplist = self.cooker.skiplist.keys() skiplist = self.bbhandler.cooker.skiplist.keys()
skiplist.sort( key=lambda fileitem: self.cooker.calc_bbfile_priority(fileitem) ) skiplist.sort( key=lambda fileitem: self.bbhandler.cooker.calc_bbfile_priority(fileitem) )
skiplist.reverse() skiplist.reverse()
for fn in skiplist: for fn in skiplist:
recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_') recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
@ -375,7 +340,7 @@ build results (as the layer priority order has effectively changed).
logger.error('Directory %s exists and is non-empty, please clear it out first' % outputdir) logger.error('Directory %s exists and is non-empty, please clear it out first' % outputdir)
return return
self.check_prepare_cooker() self.bbhandler.prepare()
layers = self.bblayers layers = self.bblayers
if len(arglist) > 2: if len(arglist) > 2:
layernames = arglist[:-1] layernames = arglist[:-1]
@ -405,8 +370,8 @@ build results (as the layer priority order has effectively changed).
appended_recipes = [] appended_recipes = []
for layer in layers: for layer in layers:
overlayed = [] overlayed = []
for f in self.cooker.overlayed.iterkeys(): for f in self.bbhandler.cooker.overlayed.iterkeys():
for of in self.cooker.overlayed[f]: for of in self.bbhandler.cooker.overlayed[f]:
if of.startswith(layer): if of.startswith(layer):
overlayed.append(of) overlayed.append(of)
@ -430,8 +395,8 @@ build results (as the layer priority order has effectively changed).
logger.warn('Overwriting file %s', fdest) logger.warn('Overwriting file %s', fdest)
bb.utils.copyfile(f1full, fdest) bb.utils.copyfile(f1full, fdest)
if ext == '.bb': if ext == '.bb':
if f1 in self.cooker_data.appends: if f1 in self.bbhandler.cooker.appendlist:
appends = self.cooker_data.appends[f1] appends = self.bbhandler.cooker.appendlist[f1]
if appends: if appends:
logger.plain(' Applying appends to %s' % fdest ) logger.plain(' Applying appends to %s' % fdest )
for appendname in appends: for appendname in appends:
@ -440,9 +405,9 @@ build results (as the layer priority order has effectively changed).
appended_recipes.append(f1) appended_recipes.append(f1)
# Take care of when some layers are excluded and yet we have included bbappends for those recipes # Take care of when some layers are excluded and yet we have included bbappends for those recipes
for recipename in self.cooker_data.appends.iterkeys(): for recipename in self.bbhandler.cooker.appendlist.iterkeys():
if recipename not in appended_recipes: if recipename not in appended_recipes:
appends = self.cooker_data.appends[recipename] appends = self.bbhandler.cooker.appendlist[recipename]
first_append = None first_append = None
for appendname in appends: for appendname in appends:
layer = layer_path_match(appendname) layer = layer_path_match(appendname)
@ -460,14 +425,14 @@ build results (as the layer priority order has effectively changed).
# have come from) # have come from)
first_regex = None first_regex = None
layerdir = layers[0] layerdir = layers[0]
for layername, pattern, regex, _ in self.cooker.status.bbfile_config_priorities: for layername, pattern, regex, _ in self.bbhandler.cooker.status.bbfile_config_priorities:
if regex.match(os.path.join(layerdir, 'test')): if regex.match(os.path.join(layerdir, 'test')):
first_regex = regex first_regex = regex
break break
if first_regex: if first_regex:
# Find the BBFILES entries that match (which will have come from this conf/layer.conf file) # Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
bbfiles = str(self.config_data.getVar('BBFILES', True)).split() bbfiles = str(self.bbhandler.config_data.getVar('BBFILES', True)).split()
bbfiles_layer = [] bbfiles_layer = []
for item in bbfiles: for item in bbfiles:
if first_regex.match(item): if first_regex.match(item):
@ -490,7 +455,7 @@ build results (as the layer priority order has effectively changed).
logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full) logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full)
def get_file_layer(self, filename): def get_file_layer(self, filename):
for layer, _, regex, _ in self.cooker.status.bbfile_config_priorities: for layer, _, regex, _ in self.bbhandler.cooker.status.bbfile_config_priorities:
if regex.match(filename): if regex.match(filename):
for layerdir in self.bblayers: for layerdir in self.bblayers:
if regex.match(os.path.join(layerdir, 'test')): if regex.match(os.path.join(layerdir, 'test')):
@ -516,14 +481,14 @@ usage: show-appends
Recipes are listed with the bbappends that apply to them as subitems. Recipes are listed with the bbappends that apply to them as subitems.
""" """
self.check_prepare_cooker() self.bbhandler.prepare()
if not self.cooker_data.appends: if not self.bbhandler.cooker.appendlist:
logger.plain('No append files found') logger.plain('No append files found')
return return
logger.plain('=== Appended recipes ===') logger.plain('=== Appended recipes ===')
pnlist = list(self.cooker_data.pkg_pn.keys()) pnlist = list(self.bbhandler.cooker_data.pkg_pn.keys())
pnlist.sort() pnlist.sort()
for pn in pnlist: for pn in pnlist:
self.show_appends_for_pn(pn) self.show_appends_for_pn(pn)
@ -531,19 +496,19 @@ Recipes are listed with the bbappends that apply to them as subitems.
self.show_appends_for_skipped() self.show_appends_for_skipped()
def show_appends_for_pn(self, pn): def show_appends_for_pn(self, pn):
filenames = self.cooker_data.pkg_pn[pn] filenames = self.bbhandler.cooker_data.pkg_pn[pn]
best = bb.providers.findBestProvider(pn, best = bb.providers.findBestProvider(pn,
self.cooker.configuration.data, self.bbhandler.cooker.configuration.data,
self.cooker_data, self.bbhandler.cooker_data,
self.cooker_data.pkg_pn) self.bbhandler.cooker_data.pkg_pn)
best_filename = os.path.basename(best[3]) best_filename = os.path.basename(best[3])
self.show_appends_output(filenames, best_filename) self.show_appends_output(filenames, best_filename)
def show_appends_for_skipped(self): def show_appends_for_skipped(self):
filenames = [os.path.basename(f) filenames = [os.path.basename(f)
for f in self.cooker.skiplist.iterkeys()] for f in self.bbhandler.cooker.skiplist.iterkeys()]
self.show_appends_output(filenames, None, " (skipped)") self.show_appends_output(filenames, None, " (skipped)")
def show_appends_output(self, filenames, best_filename, name_suffix = ''): def show_appends_output(self, filenames, best_filename, name_suffix = ''):
@ -569,7 +534,7 @@ Recipes are listed with the bbappends that apply to them as subitems.
continue continue
basename = os.path.basename(filename) basename = os.path.basename(filename)
appends = self.cooker_data.appends.get(basename) appends = self.bbhandler.cooker.appendlist.get(basename)
if appends: if appends:
appended.append((basename, list(appends))) appended.append((basename, list(appends)))
else: else:
@ -577,22 +542,5 @@ Recipes are listed with the bbappends that apply to them as subitems.
return appended, notappended return appended, notappended
class Config(object):
def __init__(self, **options):
self.pkgs_to_build = []
self.debug_domains = []
self.extra_assume_provided = []
self.prefile = []
self.postfile = []
self.debug = 0
self.__dict__.update(options)
def __getattr__(self, attribute):
try:
return super(Config, self).__getattribute__(attribute)
except AttributeError:
return None
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv[1:]) or 0) sys.exit(main(sys.argv[1:]) or 0)