summaryrefslogtreecommitdiffstats
path: root/import-layers/yocto-poky/bitbake/bin
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/bitbake/bin')
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake7
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-diffsigs16
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-dumpsig8
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-layers1073
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-prserv2
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-selftest63
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitbake-worker103
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/bitdoc2
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/image-writer122
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/toaster97
-rwxr-xr-ximport-layers/yocto-poky/bitbake/bin/toaster-eventreplay222
11 files changed, 315 insertions, 1400 deletions
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake b/import-layers/yocto-poky/bitbake/bin/bitbake
index b03683e12..2a4fc7203 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
@@ -35,7 +35,10 @@ except RuntimeError as exc:
from bb import cookerdata
from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException
-__version__ = "1.30.0"
+if sys.getfilesystemencoding() != "utf-8":
+ sys.exit("Please use a locale setting which supports utf-8.\nPython can't change the filesystem locale after loading so we need a utf-8 when python starts or things won't work.")
+
+__version__ = "1.32.0"
if __name__ == "__main__":
if __version__ != bb.__version__:
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-diffsigs b/import-layers/yocto-poky/bitbake/bin/bitbake-diffsigs
index 196f0b73e..527d2c7a9 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-diffsigs
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-diffsigs
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# bitbake-diffsigs
# BitBake task signature data comparison utility
@@ -24,6 +24,7 @@ import warnings
import fnmatch
import optparse
import logging
+import pickle
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
@@ -95,7 +96,7 @@ def find_compare_task(bbhandler, pn, taskname):
# Recurse into signature comparison
output = bb.siggen.compare_sigfiles(latestfiles[0], latestfiles[1], recursecb)
if output:
- print '\n'.join(output)
+ print('\n'.join(output))
sys.exit(0)
@@ -114,14 +115,13 @@ parser.add_option("-t", "--task",
options, args = parser.parse_args(sys.argv)
if options.taskargs:
- tinfoil = bb.tinfoil.Tinfoil()
- tinfoil.prepare(config_only = True)
- find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1])
+ with bb.tinfoil.Tinfoil() as tinfoil:
+ tinfoil.prepare(config_only=True)
+ find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1])
else:
if len(args) == 1:
parser.print_help()
else:
- import cPickle
try:
if len(args) == 2:
output = bb.siggen.dump_sigfile(sys.argv[1])
@@ -130,9 +130,9 @@ else:
except IOError as e:
logger.error(str(e))
sys.exit(1)
- except cPickle.UnpicklingError, EOFError:
+ except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying sigdata/siginfo files')
sys.exit(1)
if output:
- print '\n'.join(output)
+ print('\n'.join(output))
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-dumpsig b/import-layers/yocto-poky/bitbake/bin/bitbake-dumpsig
index 656d93a5a..58ba1cad0 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-dumpsig
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-dumpsig
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# bitbake-dumpsig
# BitBake task signature dump utility
@@ -23,6 +23,7 @@ import sys
import warnings
import optparse
import logging
+import pickle
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
@@ -51,15 +52,14 @@ options, args = parser.parse_args(sys.argv)
if len(args) == 1:
parser.print_help()
else:
- import cPickle
try:
output = bb.siggen.dump_sigfile(args[1])
except IOError as e:
logger.error(str(e))
sys.exit(1)
- except cPickle.UnpicklingError, EOFError:
+ except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying a sigdata/siginfo file')
sys.exit(1)
if output:
- print '\n'.join(output)
+ print('\n'.join(output))
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-layers b/import-layers/yocto-poky/bitbake/bin/bitbake-layers
index d47a6690e..946def220 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-layers
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-layers
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# This script has subcommands which operate against your bitbake layers, either
# displaying useful information, or acting against them.
@@ -23,1048 +23,105 @@
import logging
import os
import sys
-import fnmatch
-from collections import defaultdict
import argparse
-import re
-import httplib, urlparse, json
-import subprocess
bindir = os.path.dirname(__file__)
topdir = os.path.dirname(bindir)
sys.path[0:0] = [os.path.join(topdir, 'lib')]
-import bb.cache
-import bb.cooker
-import bb.providers
-import bb.utils
import bb.tinfoil
+def tinfoil_init(parserecipes):
+ import bb.tinfoil
+ tinfoil = bb.tinfoil.Tinfoil(tracking=True)
+ tinfoil.prepare(not parserecipes)
+ tinfoil.logger.setLevel(logger.getEffectiveLevel())
+ return tinfoil
+
+
def logger_create(name, output=sys.stderr):
logger = logging.getLogger(name)
- console = logging.StreamHandler(output)
- format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
- if output.isatty():
- format.enable_color()
- console.setFormatter(format)
- logger.addHandler(console)
+ loggerhandler = logging.StreamHandler(output)
+ loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+ logger.addHandler(loggerhandler)
logger.setLevel(logging.INFO)
return logger
-logger = logger_create('bitbake-layers', sys.stdout)
-
-class UserError(Exception):
- pass
-
-class Commands():
- def __init__(self):
- self.bbhandler = None
- self.bblayers = []
-
- def init_bbhandler(self, config_only = False):
- if not self.bbhandler:
- self.bbhandler = bb.tinfoil.Tinfoil(tracking=True)
- self.bblayers = (self.bbhandler.config_data.getVar('BBLAYERS', True) or "").split()
- self.bbhandler.prepare(config_only)
- layerconfs = self.bbhandler.config_data.varhistory.get_variable_items_files('BBFILE_COLLECTIONS', self.bbhandler.config_data)
- self.bbfile_collections = {layer: os.path.dirname(os.path.dirname(path)) for layer, path in layerconfs.iteritems()}
-
-
- def do_show_layers(self, args):
- """show current configured layers"""
- self.init_bbhandler(config_only = True)
- logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
- logger.plain('=' * 74)
- for layer, _, regex, pri in self.bbhandler.cooker.recipecache.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 do_add_layer(self, args):
- """Add a layer to bblayers.conf
-
-Adds the specified layer to bblayers.conf
-"""
- layerdir = os.path.abspath(args.layerdir)
- if not os.path.exists(layerdir):
- sys.stderr.write("Specified layer directory doesn't exist\n")
- return 1
-
- layer_conf = os.path.join(layerdir, 'conf', 'layer.conf')
- if not os.path.exists(layer_conf):
- sys.stderr.write("Specified layer directory doesn't contain a conf/layer.conf file\n")
- return 1
-
- bblayers_conf = os.path.join('conf', 'bblayers.conf')
- if not os.path.exists(bblayers_conf):
- sys.stderr.write("Unable to find bblayers.conf\n")
- return 1
-
- (notadded, _) = bb.utils.edit_bblayers_conf(bblayers_conf, layerdir, None)
- if notadded:
- for item in notadded:
- sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)
-
-
- def do_remove_layer(self, args):
- """Remove a layer from bblayers.conf
-
-Removes the specified layer from bblayers.conf
-"""
- bblayers_conf = os.path.join('conf', 'bblayers.conf')
- if not os.path.exists(bblayers_conf):
- sys.stderr.write("Unable to find bblayers.conf\n")
- return 1
-
- if args.layerdir.startswith('*'):
- layerdir = args.layerdir
- elif not '/' in args.layerdir:
- layerdir = '*/%s' % args.layerdir
- else:
- layerdir = os.path.abspath(args.layerdir)
- (_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdir)
- if notremoved:
- for item in notremoved:
- sys.stderr.write("No layers matching %s found in BBLAYERS\n" % item)
- return 1
-
-
- def get_json_data(self, apiurl):
- proxy_settings = os.environ.get("http_proxy", None)
- conn = None
- _parsedurl = urlparse.urlparse(apiurl)
- path = _parsedurl.path
- query = _parsedurl.query
- def parse_url(url):
- parsedurl = urlparse.urlparse(url)
- if parsedurl.netloc[0] == '[':
- host, port = parsedurl.netloc[1:].split(']', 1)
- if ':' in port:
- port = port.rsplit(':', 1)[1]
- else:
- port = None
- else:
- if parsedurl.netloc.count(':') == 1:
- (host, port) = parsedurl.netloc.split(":")
- else:
- host = parsedurl.netloc
- port = None
- return (host, 80 if port is None else int(port))
-
- if proxy_settings is None:
- host, port = parse_url(apiurl)
- conn = httplib.HTTPConnection(host, port)
- conn.request("GET", path + "?" + query)
- else:
- host, port = parse_url(proxy_settings)
- conn = httplib.HTTPConnection(host, port)
- conn.request("GET", apiurl)
-
- r = conn.getresponse()
- if r.status != 200:
- raise Exception("Failed to read " + path + ": %d %s" % (r.status, r.reason))
- return json.loads(r.read())
-
-
- def get_layer_deps(self, layername, layeritems, layerbranches, layerdependencies, branchnum, selfname=False):
- def layeritems_info_id(items_name, layeritems):
- litems_id = None
- for li in layeritems:
- if li['name'] == items_name:
- litems_id = li['id']
- break
- return litems_id
-
- def layerbranches_info(items_id, layerbranches):
- lbranch = {}
- for lb in layerbranches:
- if lb['layer'] == items_id and lb['branch'] == branchnum:
- lbranch['id'] = lb['id']
- lbranch['vcs_subdir'] = lb['vcs_subdir']
- break
- return lbranch
-
- def layerdependencies_info(lb_id, layerdependencies):
- ld_deps = []
- for ld in layerdependencies:
- if ld['layerbranch'] == lb_id and not ld['dependency'] in ld_deps:
- ld_deps.append(ld['dependency'])
- if not ld_deps:
- logger.error("The dependency of layerDependencies is not found.")
- return ld_deps
-
- def layeritems_info_name_subdir(items_id, layeritems):
- litems = {}
- for li in layeritems:
- if li['id'] == items_id:
- litems['vcs_url'] = li['vcs_url']
- litems['name'] = li['name']
- break
- return litems
-
- if selfname:
- selfid = layeritems_info_id(layername, layeritems)
- lbinfo = layerbranches_info(selfid, layerbranches)
- if lbinfo:
- selfsubdir = lbinfo['vcs_subdir']
- else:
- logger.error("%s is not found in the specified branch" % layername)
- return
- selfurl = layeritems_info_name_subdir(selfid, layeritems)['vcs_url']
- if selfurl:
- return selfurl, selfsubdir
- else:
- logger.error("Cannot get layer %s git repo and subdir" % layername)
- return
- ldict = {}
- itemsid = layeritems_info_id(layername, layeritems)
- if not itemsid:
- return layername, None
- lbid = layerbranches_info(itemsid, layerbranches)
- if lbid:
- lbid = layerbranches_info(itemsid, layerbranches)['id']
- else:
- logger.error("%s is not found in the specified branch" % layername)
- return None, None
- for dependency in layerdependencies_info(lbid, layerdependencies):
- lname = layeritems_info_name_subdir(dependency, layeritems)['name']
- lurl = layeritems_info_name_subdir(dependency, layeritems)['vcs_url']
- lsubdir = layerbranches_info(dependency, layerbranches)['vcs_subdir']
- ldict[lname] = lurl, lsubdir
- return None, ldict
-
-
- def get_fetch_layer(self, fetchdir, url, subdir, fetch_layer):
- layername = self.get_layer_name(url)
- if os.path.splitext(layername)[1] == '.git':
- layername = os.path.splitext(layername)[0]
- repodir = os.path.join(fetchdir, layername)
- layerdir = os.path.join(repodir, subdir)
- if not os.path.exists(repodir):
- if fetch_layer:
- result = subprocess.call('git clone %s %s' % (url, repodir), shell = True)
- if result:
- logger.error("Failed to download %s" % url)
- return None, None
- else:
- return layername, layerdir
- else:
- logger.plain("Repository %s needs to be fetched" % url)
- return layername, layerdir
- elif os.path.exists(layerdir):
- return layername, layerdir
- else:
- logger.error("%s is not in %s" % (url, subdir))
- return None, None
-
-
- def do_layerindex_fetch(self, args):
- """Fetches a layer from a layer index along with its dependent layers, and adds them to conf/bblayers.conf.
-"""
- self.init_bbhandler(config_only = True)
- apiurl = self.bbhandler.config_data.getVar('BBLAYERS_LAYERINDEX_URL', True)
- if not apiurl:
- logger.error("Cannot get BBLAYERS_LAYERINDEX_URL")
- return 1
- else:
- if apiurl[-1] != '/':
- apiurl += '/'
- apiurl += "api/"
- apilinks = self.get_json_data(apiurl)
- branches = self.get_json_data(apilinks['branches'])
-
- branchnum = 0
- for branch in branches:
- if branch['name'] == args.branch:
- branchnum = branch['id']
- break
- if branchnum == 0:
- validbranches = ', '.join([branch['name'] for branch in branches])
- logger.error('Invalid layer branch name "%s". Valid branches: %s' % (args.branch, validbranches))
- return 1
-
- ignore_layers = []
- for collection in self.bbhandler.config_data.getVar('BBFILE_COLLECTIONS', True).split():
- lname = self.bbhandler.config_data.getVar('BBLAYERS_LAYERINDEX_NAME_%s' % collection, True)
- if lname:
- ignore_layers.append(lname)
-
- if args.ignore:
- ignore_layers.extend(args.ignore.split(','))
-
- layeritems = self.get_json_data(apilinks['layerItems'])
- layerbranches = self.get_json_data(apilinks['layerBranches'])
- layerdependencies = self.get_json_data(apilinks['layerDependencies'])
- invaluenames = []
- repourls = {}
- printlayers = []
- def query_dependencies(layers, layeritems, layerbranches, layerdependencies, branchnum):
- depslayer = []
- for layername in layers:
- invaluename, layerdict = self.get_layer_deps(layername, layeritems, layerbranches, layerdependencies, branchnum)
- if layerdict:
- repourls[layername] = self.get_layer_deps(layername, layeritems, layerbranches, layerdependencies, branchnum, selfname=True)
- for layer in layerdict:
- if not layer in ignore_layers:
- depslayer.append(layer)
- printlayers.append((layername, layer, layerdict[layer][0], layerdict[layer][1]))
- if not layer in ignore_layers and not layer in repourls:
- repourls[layer] = (layerdict[layer][0], layerdict[layer][1])
- if invaluename and not invaluename in invaluenames:
- invaluenames.append(invaluename)
- return depslayer
-
- depslayers = query_dependencies(args.layername, layeritems, layerbranches, layerdependencies, branchnum)
- while depslayers:
- depslayer = query_dependencies(depslayers, layeritems, layerbranches, layerdependencies, branchnum)
- depslayers = depslayer
- if invaluenames:
- for invaluename in invaluenames:
- logger.error('Layer "%s" not found in layer index' % invaluename)
- return 1
- logger.plain("%s %s %s %s" % ("Layer".ljust(19), "Required by".ljust(19), "Git repository".ljust(54), "Subdirectory"))
- logger.plain('=' * 115)
- for layername in args.layername:
- layerurl = repourls[layername]
- logger.plain("%s %s %s %s" % (layername.ljust(20), '-'.ljust(20), layerurl[0].ljust(55), layerurl[1]))
- printedlayers = []
- for layer, dependency, gitrepo, subdirectory in printlayers:
- if dependency in printedlayers:
- continue
- logger.plain("%s %s %s %s" % (dependency.ljust(20), layer.ljust(20), gitrepo.ljust(55), subdirectory))
- printedlayers.append(dependency)
-
- if repourls:
- fetchdir = self.bbhandler.config_data.getVar('BBLAYERS_FETCH_DIR', True)
- if not fetchdir:
- logger.error("Cannot get BBLAYERS_FETCH_DIR")
- return 1
- if not os.path.exists(fetchdir):
- os.makedirs(fetchdir)
- addlayers = []
- for repourl, subdir in repourls.values():
- name, layerdir = self.get_fetch_layer(fetchdir, repourl, subdir, not args.show_only)
- if not name:
- # Error already shown
- return 1
- addlayers.append((subdir, name, layerdir))
- if not args.show_only:
- for subdir, name, layerdir in set(addlayers):
- if os.path.exists(layerdir):
- if subdir:
- logger.plain("Adding layer \"%s\" to conf/bblayers.conf" % subdir)
- else:
- logger.plain("Adding layer \"%s\" to conf/bblayers.conf" % name)
- localargs = argparse.Namespace()
- localargs.layerdir = layerdir
- self.do_add_layer(localargs)
- else:
- break
-
-
- def do_layerindex_show_depends(self, args):
- """Find layer dependencies from layer index.
-"""
- args.show_only = True
- args.ignore = []
- self.do_layerindex_fetch(args)
-
-
- 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.
-"""
- self.init_bbhandler()
-
- items_listed = self.list_recipes('Overlayed recipes', None, True, args.same_version, args.filenames, True, None)
-
- # Check for overlayed .bbclass files
- classes = 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.bbhandler.config_data.getVar('BBPATH', True))
- 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.
-"""
- self.init_bbhandler()
-
- 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.bbhandler.config_data.getVar('BBPATH', True))
- for classname in inherits:
- classfile = 'classes/%s.bbclass' % classname
- if not bb.utils.which(bbpath, classfile, history=False):
- raise UserError('No class named %s found in BBPATH' % classfile)
-
- pkg_pn = self.bbhandler.cooker.recipecache.pkg_pn
- (latest_versions, preferred_versions) = bb.providers.findProviders(self.bbhandler.config_data, self.bbhandler.cooker.recipecache, pkg_pn)
- allproviders = bb.providers.allProviders(self.bbhandler.cooker.recipecache)
-
- # 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 = self.bbhandler.cooker.skiplist.keys()
- skiplist.sort( key=lambda fileitem: self.bbhandler.cooker.collection.calc_bbfile_priority(fileitem) )
- skiplist.reverse()
- 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.bbhandler.config_data.getVar('INHERIT', True) or "").split()
- cls_re = re.compile('classes/')
-
- preffiles = []
- items_listed = False
- for p in sorted(pkg_pn):
- if pnspec:
- if not fnmatch.fnmatch(p, pnspec):
- continue
-
- if len(allproviders[p]) > 1 or not show_multi_provider_only:
- pref = preferred_versions[p]
- realfn = bb.cache.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.bbhandler.cooker.recipecache.pkg_fn:
- continue
-
- if inherits:
- matchcount = 0
- recipe_inherits = self.bbhandler.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.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 logger_setup_color(logger, color='auto'):
+ from bb.msg import BBLogFormatter
+ console = logging.StreamHandler(sys.stdout)
+ formatter = BBLogFormatter("%(levelname)s: %(message)s")
+ console.setFormatter(formatter)
+ logger.handlers = [console]
+ if color == 'always' or (color == 'auto' and console.stream.isatty()):
+ formatter.enable_color()
- def do_flatten(self, args):
- """flatten layer configuration into a separate output directory.
-
-Takes the specified layers (or all layers in the current layer
-configuration if none are specified) and builds a "flattened" directory
-containing the contents of all layers, with any overlayed recipes removed
-and bbappends appended to the corresponding recipes. Note that some manual
-cleanup may still be necessary afterwards, in particular:
-
-* where non-recipe files (such as patches) are overwritten (the flatten
- command will show a warning for these)
-* where anything beyond the normal layer setup has been added to
- layer.conf (only the lowest priority number layer's layer.conf is used)
-* overridden/appended items from bbappends will need to be tidied up
-* when the flattened layers do not have the same directory structure (the
- flatten command should show a warning when this will cause a problem)
-
-Warning: if you flatten several layers where another layer is intended to
-be used "inbetween" them (in layer priority order) such that recipes /
-bbappends in the layers interact, and then attempt to use the new output
-layer together with that other layer, you may no longer get the same
-build results (as the layer priority order has effectively changed).
-"""
- if len(args.layer) == 1:
- logger.error('If you specify layers to flatten you must specify at least two')
- return 1
-
- outputdir = args.outputdir
- if os.path.exists(outputdir) and os.listdir(outputdir):
- logger.error('Directory %s exists and is non-empty, please clear it out first' % outputdir)
- return 1
-
- self.init_bbhandler()
- layers = self.bblayers
- if len(args.layer) > 2:
- layernames = args.layer
- found_layernames = []
- found_layerdirs = []
- for layerdir in layers:
- layername = self.get_layer_name(layerdir)
- if layername in layernames:
- found_layerdirs.append(layerdir)
- found_layernames.append(layername)
-
- for layername in layernames:
- if not layername in found_layernames:
- logger.error('Unable to find layer %s in current configuration, please run "%s show-layers" to list configured layers' % (layername, os.path.basename(sys.argv[0])))
- return
- layers = found_layerdirs
- else:
- layernames = []
-
- # Ensure a specified path matches our list of layers
- def layer_path_match(path):
- for layerdir in layers:
- if path.startswith(os.path.join(layerdir, '')):
- return layerdir
- return None
-
- applied_appends = []
- for layer in layers:
- overlayed = []
- for f in self.bbhandler.cooker.collection.overlayed.iterkeys():
- for of in self.bbhandler.cooker.collection.overlayed[f]:
- if of.startswith(layer):
- overlayed.append(of)
-
- logger.plain('Copying files from %s...' % layer )
- for root, dirs, files in os.walk(layer):
- for f1 in files:
- f1full = os.sep.join([root, f1])
- if f1full in overlayed:
- logger.plain(' Skipping overlayed file %s' % f1full )
- else:
- ext = os.path.splitext(f1)[1]
- if ext != '.bbappend':
- fdest = f1full[len(layer):]
- fdest = os.path.normpath(os.sep.join([outputdir,fdest]))
- bb.utils.mkdirhier(os.path.dirname(fdest))
- if os.path.exists(fdest):
- if f1 == 'layer.conf' and root.endswith('/conf'):
- logger.plain(' Skipping layer config file %s' % f1full )
- continue
- else:
- logger.warn('Overwriting file %s', fdest)
- bb.utils.copyfile(f1full, fdest)
- if ext == '.bb':
- for append in self.bbhandler.cooker.collection.get_file_appends(f1full):
- if layer_path_match(append):
- logger.plain(' Applying append %s to %s' % (append, fdest))
- self.apply_append(append, fdest)
- applied_appends.append(append)
-
- # Take care of when some layers are excluded and yet we have included bbappends for those recipes
- for b in self.bbhandler.cooker.collection.bbappends:
- (recipename, appendname) = b
- if appendname not in applied_appends:
- first_append = None
- layer = layer_path_match(appendname)
- if layer:
- if first_append:
- self.apply_append(appendname, first_append)
- else:
- fdest = appendname[len(layer):]
- fdest = os.path.normpath(os.sep.join([outputdir,fdest]))
- bb.utils.mkdirhier(os.path.dirname(fdest))
- bb.utils.copyfile(appendname, fdest)
- first_append = fdest
-
- # Get the regex for the first layer in our list (which is where the conf/layer.conf file will
- # have come from)
- first_regex = None
- layerdir = layers[0]
- for layername, pattern, regex, _ in self.bbhandler.cooker.recipecache.bbfile_config_priorities:
- if regex.match(os.path.join(layerdir, 'test')):
- first_regex = regex
- break
-
- if first_regex:
- # Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
- bbfiles = str(self.bbhandler.config_data.getVar('BBFILES', True)).split()
- bbfiles_layer = []
- for item in bbfiles:
- if first_regex.match(item):
- newpath = os.path.join(outputdir, item[len(layerdir)+1:])
- bbfiles_layer.append(newpath)
-
- if bbfiles_layer:
- # Check that all important layer files match BBFILES
- for root, dirs, files in os.walk(outputdir):
- for f1 in files:
- ext = os.path.splitext(f1)[1]
- if ext in ['.bb', '.bbappend']:
- f1full = os.sep.join([root, f1])
- entry_found = False
- for item in bbfiles_layer:
- if fnmatch.fnmatch(f1full, item):
- entry_found = True
- break
- if not entry_found:
- 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):
- 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.bbhandler.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 get_layer_name(self, layerdir):
- return os.path.basename(layerdir.rstrip(os.sep))
-
- def apply_append(self, appendname, recipename):
- with open(appendname, 'r') as appendfile:
- with open(recipename, 'a') as recipefile:
- recipefile.write('\n')
- recipefile.write('##### bbappended from %s #####\n' % self.get_file_layer(appendname))
- recipefile.writelines(appendfile.readlines())
-
- 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.
-"""
- self.init_bbhandler()
-
- logger.plain('=== Appended recipes ===')
-
- pnlist = list(self.bbhandler.cooker_data.pkg_pn.keys())
- pnlist.sort()
- appends = False
- for pn in pnlist:
- if self.show_appends_for_pn(pn):
- appends = True
-
- if 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.bbhandler.cooker_data.pkg_pn[pn]
-
- best = bb.providers.findBestProvider(pn,
- self.bbhandler.config_data,
- self.bbhandler.cooker_data,
- self.bbhandler.cooker_data.pkg_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.bbhandler.cooker.skiplist.iterkeys()]
- 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.warn('%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.Cache.virtualfn2realfn(filename)
- if cls:
- continue
-
- basename = os.path.basename(filename)
- appends = self.bbhandler.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(',')
-
- self.init_bbhandler()
-
- pkg_fn = self.bbhandler.cooker_data.pkg_fn
- bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
- 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.bbhandler.config_data.getVar('INHERIT', True) or "").split()
-
- # The bb's DEPENDS and RDEPENDS
- for f in pkg_fn:
- f = bb.cache.Cache.virtualfn2realfn(f)[0]
- # Get the layername that the file is in
- layername = self.get_file_layer(f)
-
- # The DEPENDS
- deps = self.bbhandler.cooker_data.deps[f]
- for pn in deps:
- if pn in self.bbhandler.cooker_data.pkg_pn:
- best = bb.providers.findBestProvider(pn,
- self.bbhandler.config_data,
- self.bbhandler.cooker_data,
- self.bbhandler.cooker_data.pkg_pn)
- self.check_cross_depends("DEPENDS", layername, f, best[3], args.filenames, ignore_layers)
-
- # The RDPENDS
- all_rdeps = self.bbhandler.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 = bb.providers.getRuntimeProviders(self.bbhandler.cooker_data, rdep)
- if all_p:
- if f in all_p:
- # The recipe provides this one itself, ignore
- continue
- best = bb.providers.filterProvidersRunTime(all_p, rdep,
- self.bbhandler.config_data,
- self.bbhandler.cooker_data)[0][0]
- self.check_cross_depends("RDEPENDS", layername, f, best, args.filenames, ignore_layers)
-
- # The RRECOMMENDS
- all_rrecs = self.bbhandler.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 = bb.providers.getRuntimeProviders(self.bbhandler.cooker_data, rrec)
- if all_p:
- if f in all_p:
- # The recipe provides this one itself, ignore
- continue
- best = bb.providers.filterProvidersRunTime(all_p, rrec,
- self.bbhandler.config_data,
- self.bbhandler.cooker_data)[0][0]
- self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)
-
- # The inherit class
- cls_re = re.compile('classes/')
- if f in self.bbhandler.cooker_data.inherits:
- inherits = self.bbhandler.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.bbhandler.cooker_data.pkg_pepvpr:
- pv = self.bbhandler.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.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))
+logger = logger_create('bitbake-layers', sys.stdout)
def main():
-
- cmds = Commands()
-
- def add_command(cmdname, function, *args, **kwargs):
- # Convert docstring for function to help (one-liner shown in main --help) and description (shown in subcommand --help)
- docsplit = function.__doc__.splitlines()
- help = docsplit[0]
- if len(docsplit) > 1:
- desc = '\n'.join(docsplit[1:])
- else:
- desc = help
- subparser = subparsers.add_parser(cmdname, *args, help=help, description=desc, formatter_class=argparse.RawTextHelpFormatter, **kwargs)
- subparser.set_defaults(func=function)
- return subparser
-
- parser = argparse.ArgumentParser(description="BitBake layers utility",
- epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
+ parser = argparse.ArgumentParser(
+ description="BitBake layers utility",
+ epilog="Use %(prog)s <subcommand> --help to get help on a specific command",
+ add_help=False)
parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
- subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
-
- parser_show_layers = add_command('show-layers', cmds.do_show_layers)
+ parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
- parser_add_layer = add_command('add-layer', cmds.do_add_layer)
- parser_add_layer.add_argument('layerdir', help='Layer directory to add')
+ global_args, unparsed_args = parser.parse_known_args()
- parser_remove_layer = add_command('remove-layer', cmds.do_remove_layer)
- parser_remove_layer.add_argument('layerdir', help='Layer directory to remove (wildcards allowed, enclose in quotes to avoid shell expansion)')
- parser_remove_layer.set_defaults(func=cmds.do_remove_layer)
-
- parser_show_overlayed = add_command('show-overlayed', cmds.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 = add_command('show-recipes', cmds.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', 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 = add_command('show-appends', cmds.do_show_appends)
+ # Help is added here rather than via add_help=True, as we don't want it to
+ # be handled by parse_known_args()
+ parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
+ help='show this help message and exit')
+ subparsers = parser.add_subparsers(title='subcommands', metavar='<subcommand>')
+ subparsers.required = True
- parser_flatten = add_command('flatten', cmds.do_flatten)
- parser_flatten.add_argument('layer', nargs='*', help='Optional layer(s) to flatten (otherwise all are flattened)')
- parser_flatten.add_argument('outputdir', help='Output directory')
+ if global_args.debug:
+ logger.setLevel(logging.DEBUG)
+ elif global_args.quiet:
+ logger.setLevel(logging.ERROR)
- parser_show_cross_depends = add_command('show-cross-depends', cmds.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')
+ logger_setup_color(logger, global_args.color)
- parser_layerindex_fetch = add_command('layerindex-fetch', cmds.do_layerindex_fetch)
- parser_layerindex_fetch.add_argument('-n', '--show-only', help='show dependencies and do nothing else', action='store_true')
- parser_layerindex_fetch.add_argument('-b', '--branch', help='branch name to fetch (default %(default)s)', default='master')
- parser_layerindex_fetch.add_argument('-i', '--ignore', help='assume the specified layers do not need to be fetched/added (separate multiple layers with commas, no spaces)', metavar='LAYER')
- parser_layerindex_fetch.add_argument('layername', nargs='+', help='layer to fetch')
+ plugins = []
+ tinfoil = tinfoil_init(False)
+ try:
+ for path in ([topdir] +
+ tinfoil.config_data.getVar('BBPATH', True).split(':')):
+ pluginpath = os.path.join(path, 'lib', 'bblayers')
+ bb.utils.load_plugins(logger, plugins, pluginpath)
- parser_layerindex_show_depends = add_command('layerindex-show-depends', cmds.do_layerindex_show_depends)
- parser_layerindex_show_depends.add_argument('-b', '--branch', help='branch name to fetch (default %(default)s)', default='master')
- parser_layerindex_show_depends.add_argument('layername', nargs='+', help='layer to query')
+ registered = False
+ for plugin in plugins:
+ if hasattr(plugin, 'register_commands'):
+ registered = True
+ plugin.register_commands(subparsers)
+ if hasattr(plugin, 'tinfoil_init'):
+ plugin.tinfoil_init(tinfoil)
- args = parser.parse_args()
+ if not registered:
+ logger.error("No commands registered - missing plugins?")
+ sys.exit(1)
- if args.debug:
- logger.setLevel(logging.DEBUG)
- elif args.quiet:
- logger.setLevel(logging.ERROR)
+ args = parser.parse_args(unparsed_args, namespace=global_args)
- try:
- ret = args.func(args)
- except UserError as err:
- logger.error(str(err))
- ret = 1
+ if getattr(args, 'parserecipes', False):
+ tinfoil.config_data.disableTracking()
+ tinfoil.parseRecipes()
+ tinfoil.config_data.enableTracking()
- return ret
+ return args.func(args)
+ finally:
+ tinfoil.shutdown()
if __name__ == "__main__":
try:
ret = main()
+ except bb.BBHandledException:
+ ret = 1
except Exception:
ret = 1
import traceback
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-prserv b/import-layers/yocto-poky/bitbake/bin/bitbake-prserv
index 03821446b..f38d2dd88 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-prserv
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-prserv
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import os
import sys,logging
import optparse
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-selftest b/import-layers/yocto-poky/bitbake/bin/bitbake-selftest
index 462eb1b2b..380e00361 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-selftest
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-selftest
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# Copyright (C) 2012 Richard Purdie
#
@@ -25,31 +25,48 @@ try:
except RuntimeError as exc:
sys.exit(str(exc))
-def usage():
- print('usage: [BB_SKIP_NETTESTS=yes] %s [-v] [testname1 [testname2]...]' % os.path.basename(sys.argv[0]))
-
-verbosity = 1
-
-tests = sys.argv[1:]
-if '-v' in sys.argv:
- tests.remove('-v')
- verbosity = 2
-
-if tests:
- if '--help' in sys.argv[1:]:
- usage()
- sys.exit(0)
-else:
- tests = ["bb.tests.codeparser",
- "bb.tests.cow",
- "bb.tests.data",
- "bb.tests.fetch",
- "bb.tests.parse",
- "bb.tests.utils"]
+tests = ["bb.tests.codeparser",
+ "bb.tests.cow",
+ "bb.tests.data",
+ "bb.tests.fetch",
+ "bb.tests.parse",
+ "bb.tests.utils"]
for t in tests:
t = '.'.join(t.split('.')[:3])
__import__(t)
-unittest.main(argv=["bitbake-selftest"] + tests, verbosity=verbosity)
+# Set-up logging
+class StdoutStreamHandler(logging.StreamHandler):
+ """Special handler so that unittest is able to capture stdout"""
+ def __init__(self):
+ # Override __init__() because we don't want to set self.stream here
+ logging.Handler.__init__(self)
+
+ @property
+ def stream(self):
+ # We want to dynamically write wherever sys.stdout is pointing to
+ return sys.stdout
+
+
+handler = StdoutStreamHandler()
+bb.logger.addHandler(handler)
+bb.logger.setLevel(logging.DEBUG)
+
+
+ENV_HELP = """\
+Environment variables:
+ BB_SKIP_NETTESTS set to 'yes' in order to skip tests using network
+ connection
+ BB_TMPDIR_NOCLEAN set to 'yes' to preserve test tmp directories
+"""
+
+class main(unittest.main):
+ def _print_help(self, *args, **kwargs):
+ super(main, self)._print_help(*args, **kwargs)
+ print(ENV_HELP)
+
+
+if __name__ == '__main__':
+ main(defaultTest=tests, buffer=True)
diff --git a/import-layers/yocto-poky/bitbake/bin/bitbake-worker b/import-layers/yocto-poky/bitbake/bin/bitbake-worker
index 767a1c033..500f2ad16 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitbake-worker
+++ b/import-layers/yocto-poky/bitbake/bin/bitbake-worker
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import os
import sys
@@ -10,8 +10,12 @@ import bb
import select
import errno
import signal
+import pickle
from multiprocessing import Lock
+if sys.getfilesystemencoding() != "utf-8":
+ sys.exit("Please use a locale setting which supports utf-8.\nPython can't change the filesystem locale after loading so we need a utf-8 when python starts or things won't work.")
+
# Users shouldn't be running this code directly
if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"):
print("bitbake-worker is meant for internal execution by bitbake itself, please don't use it standalone.")
@@ -30,19 +34,16 @@ if sys.argv[1].startswith("decafbadbad"):
# updates to log files for use with tail
try:
if sys.stdout.name == '<stdout>':
- sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+ import fcntl
+ fl = fcntl.fcntl(sys.stdout.fileno(), fcntl.F_GETFL)
+ fl |= os.O_SYNC
+ fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, fl)
+ #sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
except:
pass
logger = logging.getLogger("BitBake")
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
- bb.msg.note(1, bb.msg.domain.Cache, "Importing cPickle failed. Falling back to a very slow implementation.")
-
-
worker_pipe = sys.stdout.fileno()
bb.utils.nonblockingfd(worker_pipe)
# Need to guard against multiprocessing being used in child processes
@@ -62,10 +63,10 @@ if 0:
consolelog.setFormatter(conlogformat)
logger.addHandler(consolelog)
-worker_queue = ""
+worker_queue = b""
def worker_fire(event, d):
- data = "<event>" + pickle.dumps(event) + "</event>"
+ data = b"<event>" + pickle.dumps(event) + b"</event>"
worker_fire_prepickled(data)
def worker_fire_prepickled(event):
@@ -91,7 +92,7 @@ def worker_child_fire(event, d):
global worker_pipe
global worker_pipe_lock
- data = "<event>" + pickle.dumps(event) + "</event>"
+ data = b"<event>" + pickle.dumps(event) + b"</event>"
try:
worker_pipe_lock.acquire()
worker_pipe.write(data)
@@ -114,7 +115,7 @@ def sigterm_handler(signum, frame):
os.killpg(0, signal.SIGTERM)
sys.exit()
-def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdata, quieterrors=False):
+def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, appends, taskdepdata, quieterrors=False):
# We need to setup the environment BEFORE the fork, since
# a fork() or exec*() activates PSEUDO...
@@ -159,7 +160,8 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
pipeout = os.fdopen(pipeout, 'wb', 0)
pid = os.fork()
except OSError as e:
- bb.msg.fatal("RunQueue", "fork failed: %d (%s)" % (e.errno, e.strerror))
+ logger.critical("fork failed: %d (%s)" % (e.errno, e.strerror))
+ sys.exit(1)
if pid == 0:
def child():
@@ -191,15 +193,19 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
if umask:
os.umask(umask)
- data.setVar("BB_WORKERCONTEXT", "1")
- data.setVar("BB_TASKDEPDATA", taskdepdata)
- data.setVar("BUILDNAME", workerdata["buildname"])
- data.setVar("DATE", workerdata["date"])
- data.setVar("TIME", workerdata["time"])
- bb.parse.siggen.set_taskdata(workerdata["sigdata"])
- ret = 0
try:
- the_data = bb.cache.Cache.loadDataFull(fn, appends, data)
+ bb_cache = bb.cache.NoCache(databuilder)
+ (realfn, virtual, mc) = bb.cache.virtualfn2realfn(fn)
+ the_data = databuilder.mcdata[mc]
+ the_data.setVar("BB_WORKERCONTEXT", "1")
+ the_data.setVar("BB_TASKDEPDATA", taskdepdata)
+ the_data.setVar("BUILDNAME", workerdata["buildname"])
+ the_data.setVar("DATE", workerdata["date"])
+ the_data.setVar("TIME", workerdata["time"])
+ bb.parse.siggen.set_taskdata(workerdata["sigdata"])
+ ret = 0
+
+ the_data = bb_cache.loadDataFull(fn, appends)
the_data.setVar('BB_TASKHASH', workerdata["runq_hash"][task])
bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN", True), taskname.replace("do_", "")))
@@ -207,14 +213,24 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
# exported_vars() returns a generator which *cannot* be passed to os.environ.update()
# successfully. We also need to unset anything from the environment which shouldn't be there
exports = bb.data.exported_vars(the_data)
+
bb.utils.empty_environment()
for e, v in exports:
os.environ[e] = v
+
for e in fakeenv:
os.environ[e] = fakeenv[e]
the_data.setVar(e, fakeenv[e])
the_data.setVarFlag(e, 'export', "1")
+ task_exports = the_data.getVarFlag(taskname, 'exports', True)
+ if task_exports:
+ for e in task_exports.split():
+ the_data.setVarFlag(e, 'export', '1')
+ v = the_data.getVar(e, True)
+ if v is not None:
+ os.environ[e] = v
+
if quieterrors:
the_data.setVarFlag(taskname, "quieterrors", "1")
@@ -240,7 +256,7 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
bb.utils.process_profilelog(profname)
os._exit(ret)
else:
- for key, value in envbackup.iteritems():
+ for key, value in iter(envbackup.items()):
if value is None:
del os.environ[key]
else:
@@ -257,22 +273,22 @@ class runQueueWorkerPipe():
if pipeout:
pipeout.close()
bb.utils.nonblockingfd(self.input)
- self.queue = ""
+ self.queue = b""
def read(self):
start = len(self.queue)
try:
- self.queue = self.queue + self.input.read(102400)
+ self.queue = self.queue + (self.input.read(102400) or b"")
except (OSError, IOError) as e:
if e.errno != errno.EAGAIN:
raise
end = len(self.queue)
- index = self.queue.find("</event>")
+ index = self.queue.find(b"</event>")
while index != -1:
worker_fire_prepickled(self.queue[:index+8])
self.queue = self.queue[index+8:]
- index = self.queue.find("</event>")
+ index = self.queue.find(b"</event>")
return (end > start)
def close(self):
@@ -288,7 +304,7 @@ class BitbakeWorker(object):
def __init__(self, din):
self.input = din
bb.utils.nonblockingfd(self.input)
- self.queue = ""
+ self.queue = b""
self.cookercfg = None
self.databuilder = None
self.data = None
@@ -325,12 +341,12 @@ class BitbakeWorker(object):
except (OSError, IOError):
pass
if len(self.queue):
- self.handle_item("cookerconfig", self.handle_cookercfg)
- self.handle_item("workerdata", self.handle_workerdata)
- self.handle_item("runtask", self.handle_runtask)
- self.handle_item("finishnow", self.handle_finishnow)
- self.handle_item("ping", self.handle_ping)
- self.handle_item("quit", self.handle_quit)
+ self.handle_item(b"cookerconfig", self.handle_cookercfg)
+ self.handle_item(b"workerdata", self.handle_workerdata)
+ self.handle_item(b"runtask", self.handle_runtask)
+ self.handle_item(b"finishnow", self.handle_finishnow)
+ self.handle_item(b"ping", self.handle_ping)
+ self.handle_item(b"quit", self.handle_quit)
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
@@ -340,12 +356,12 @@ class BitbakeWorker(object):
def handle_item(self, item, func):
- if self.queue.startswith("<" + item + ">"):
- index = self.queue.find("</" + item + ">")
+ if self.queue.startswith(b"<" + item + b">"):
+ index = self.queue.find(b"</" + item + b">")
while index != -1:
func(self.queue[(len(item) + 2):index])
self.queue = self.queue[(index + len(item) + 3):]
- index = self.queue.find("</" + item + ">")
+ index = self.queue.find(b"</" + item + b">")
def handle_cookercfg(self, data):
self.cookercfg = pickle.loads(data)
@@ -359,12 +375,13 @@ class BitbakeWorker(object):
bb.msg.loggerDefaultVerbose = self.workerdata["logdefaultverbose"]
bb.msg.loggerVerboseLogs = self.workerdata["logdefaultverboselogs"]
bb.msg.loggerDefaultDomains = self.workerdata["logdefaultdomain"]
- self.data.setVar("PRSERV_HOST", self.workerdata["prhost"])
+ for mc in self.databuilder.mcdata:
+ self.databuilder.mcdata[mc].setVar("PRSERV_HOST", self.workerdata["prhost"])
def handle_ping(self, _):
workerlog_write("Handling ping\n")
- logger.warn("Pong from bitbake-worker!")
+ logger.warning("Pong from bitbake-worker!")
def handle_quit(self, data):
workerlog_write("Handling quit\n")
@@ -377,7 +394,7 @@ class BitbakeWorker(object):
fn, task, taskname, quieterrors, appends, taskdepdata = pickle.loads(data)
workerlog_write("Handling runtask %s %s %s\n" % (task, fn, taskname))
- pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.workerdata, fn, task, taskname, appends, taskdepdata, quieterrors)
+ pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.databuilder, self.workerdata, fn, task, taskname, appends, taskdepdata, quieterrors)
self.build_pids[pid] = task
self.build_pipes[pid] = runQueueWorkerPipe(pipein, pipeout)
@@ -409,12 +426,12 @@ class BitbakeWorker(object):
self.build_pipes[pid].close()
del self.build_pipes[pid]
- worker_fire_prepickled("<exitcode>" + pickle.dumps((task, status)) + "</exitcode>")
+ worker_fire_prepickled(b"<exitcode>" + pickle.dumps((task, status)) + b"</exitcode>")
def handle_finishnow(self, _):
if self.build_pids:
logger.info("Sending SIGTERM to remaining %s tasks", len(self.build_pids))
- for k, v in self.build_pids.iteritems():
+ for k, v in iter(self.build_pids.items()):
try:
os.kill(-k, signal.SIGTERM)
os.waitpid(-1, 0)
@@ -424,7 +441,7 @@ class BitbakeWorker(object):
self.build_pipes[pipe].read()
try:
- worker = BitbakeWorker(sys.stdin)
+ worker = BitbakeWorker(os.fdopen(sys.stdin.fileno(), 'rb'))
if not profiling:
worker.serve()
else:
diff --git a/import-layers/yocto-poky/bitbake/bin/bitdoc b/import-layers/yocto-poky/bitbake/bin/bitdoc
index defb3dd37..274467882 100755
--- a/import-layers/yocto-poky/bitbake/bin/bitdoc
+++ b/import-layers/yocto-poky/bitbake/bin/bitdoc
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
diff --git a/import-layers/yocto-poky/bitbake/bin/image-writer b/import-layers/yocto-poky/bitbake/bin/image-writer
deleted file mode 100755
index e30ab45e3..000000000
--- a/import-layers/yocto-poky/bitbake/bin/image-writer
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2012 Wind River Systems, Inc.
-#
-# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-import os
-import sys
-sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname( \
- os.path.abspath(__file__))), 'lib'))
-try:
- import bb
-except RuntimeError as exc:
- sys.exit(str(exc))
-
-import gtk
-import optparse
-import pygtk
-
-from bb.ui.crumbs.hobwidget import HobAltButton, HobButton
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.deployimagedialog import DeployImageDialog
-from bb.ui.crumbs.hig.imageselectiondialog import ImageSelectionDialog
-
-# I put all the fs bitbake supported here. Need more test.
-DEPLOYABLE_IMAGE_TYPES = ["jffs2", "cramfs", "ext2", "ext3", "ext4", "btrfs", "squashfs", "ubi", "vmdk"]
-Title = "USB Image Writer"
-
-class DeployWindow(gtk.Window):
- def __init__(self, image_path=''):
- super(DeployWindow, self).__init__()
-
- if len(image_path) > 0:
- valid = True
- if not os.path.exists(image_path):
- valid = False
- lbl = "<b>Invalid image file path: %s.</b>\nPress <b>Select Image</b> to select an image." % image_path
- else:
- image_path = os.path.abspath(image_path)
- extend_name = os.path.splitext(image_path)[1][1:]
- if extend_name not in DEPLOYABLE_IMAGE_TYPES:
- valid = False
- lbl = "<b>Undeployable imge type: %s</b>\nPress <b>Select Image</b> to select an image." % extend_name
-
- if not valid:
- image_path = ''
- crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
- button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- crumbs_dialog.run()
- crumbs_dialog.destroy()
-
- self.deploy_dialog = DeployImageDialog(Title, image_path, self,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR, None, standalone=True)
- close_button = self.deploy_dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(close_button)
- close_button.connect('clicked', gtk.main_quit)
-
- write_button = self.deploy_dialog.add_button("Write USB image", gtk.RESPONSE_YES)
- HobAltButton.style_button(write_button)
-
- self.deploy_dialog.connect('select_image_clicked', self.select_image_clicked_cb)
- self.deploy_dialog.connect('destroy', gtk.main_quit)
- response = self.deploy_dialog.show()
-
- def select_image_clicked_cb(self, dialog):
- cwd = os.getcwd()
- dialog = ImageSelectionDialog(cwd, DEPLOYABLE_IMAGE_TYPES, Title, self, gtk.FILE_CHOOSER_ACTION_SAVE )
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Open", gtk.RESPONSE_YES)
- HobAltButton.style_button(button)
- response = dialog.run()
-
- if response == gtk.RESPONSE_YES:
- if not dialog.image_names:
- lbl = "<b>No selections made</b>\nClicked the radio button to select a image."
- crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
- button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- crumbs_dialog.run()
- crumbs_dialog.destroy()
- dialog.destroy()
- return
-
- # get the full path of image
- image_path = os.path.join(dialog.image_folder, dialog.image_names[0])
- self.deploy_dialog.set_image_text_buffer(image_path)
- self.deploy_dialog.set_image_path(image_path)
-
- dialog.destroy()
-
-def main():
- parser = optparse.OptionParser(
- usage = """%prog [-h] [image_file]
-
-%prog writes bootable images to USB devices. You can
-provide the image file on the command line or select it using the GUI.""")
-
- options, args = parser.parse_args(sys.argv)
- image_file = args[1] if len(args) > 1 else ''
- dw = DeployWindow(image_file)
-
-if __name__ == '__main__':
- try:
- main()
- gtk.main()
- except Exception:
- import traceback
- traceback.print_exc()
diff --git a/import-layers/yocto-poky/bitbake/bin/toaster b/import-layers/yocto-poky/bitbake/bin/toaster
index 70c66d2c2..f92d38eca 100755
--- a/import-layers/yocto-poky/bitbake/bin/toaster
+++ b/import-layers/yocto-poky/bitbake/bin/toaster
@@ -17,10 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
-# Usage: source toaster [start|stop]
-# [webport=<port>] [noui] [noweb]
-
-# Helper function to kill a background toaster development server
+HELP="
+Usage: source toaster start|stop [webport=<address:port>] [noweb]
+ Optional arguments:
+ [noweb] Setup the environment for building with toaster but don't start the development server
+ [webport] Set the development server (default: localhost:8000)
+"
webserverKillAll()
{
@@ -31,9 +33,6 @@ webserverKillAll()
while kill -0 $pid 2>/dev/null; do
kill -SIGTERM -$pid 2>/dev/null
sleep 1
- # Kill processes if they are still running - may happen
- # in interactive shells
- ps fux | grep "python.*manage.py runserver" | awk '{print $2}' | xargs kill
done
rm ${pidfile}
fi
@@ -57,7 +56,8 @@ webserverStartAll()
echo "Failed migrations, aborting system start" 1>&2
return $retval
fi
-
+ # Make sure that checksettings can pick up any value for TEMPLATECONF
+ export TEMPLATECONF
$MANAGE checksettings --traceback || retval=1
if [ $retval -eq 1 ]; then
@@ -67,7 +67,7 @@ webserverStartAll()
echo "Starting webserver..."
- $MANAGE runserver "0.0.0.0:$WEB_PORT" \
+ $MANAGE runserver "$ADDR_PORT" \
</dev/null >>${BUILDDIR}/toaster_web.log 2>&1 \
& echo $! >${BUILDDIR}/.toastermain.pid
@@ -77,7 +77,8 @@ webserverStartAll()
retval=1
rm "${BUILDDIR}/.toastermain.pid"
else
- echo "Webserver address: http://0.0.0.0:$WEB_PORT/"
+ echo "Toaster development webserver started at http://$ADDR_PORT"
+ echo -e "\nYou can now run 'bitbake <target>' on the command line and monitor your build in Toaster.\nYou can also use a Toaster project to configure and run a build.\n"
fi
return $retval
@@ -91,14 +92,8 @@ stop_system()
# prevent reentry
if [ $INSTOPSYSTEM -eq 1 ]; then return; fi
INSTOPSYSTEM=1
- if [ -f ${BUILDDIR}/.toasterui.pid ]; then
- kill `cat ${BUILDDIR}/.toasterui.pid` 2>/dev/null
- rm ${BUILDDIR}/.toasterui.pid
- fi
webserverKillAll
# unset exported variables
- unset DATABASE_URL
- unset TOASTER_CONF
unset TOASTER_DIR
unset BITBAKE_UI
unset BBBASEDIR
@@ -109,11 +104,11 @@ stop_system()
verify_prereq() {
# Verify Django version
- reqfile=$(python -c "import os; print os.path.realpath('$BBBASEDIR/toaster-requirements.txt')")
+ reqfile=$(python3 -c "import os; print(os.path.realpath('$BBBASEDIR/toaster-requirements.txt'))")
exp='s/Django\([><=]\+\)\([^,]\+\),\([><=]\+\)\(.\+\)/'
exp=$exp'import sys,django;version=django.get_version().split(".");'
exp=$exp'sys.exit(not (version \1 "\2".split(".") and version \3 "\4".split(".")))/p'
- if ! sed -n "$exp" $reqfile | python - ; then
+ if ! sed -n "$exp" $reqfile | python3 - ; then
req=`grep ^Django $reqfile`
echo "This program needs $req"
echo "Please install with pip install -r $reqfile"
@@ -133,8 +128,8 @@ else
fi
export BBBASEDIR=`dirname $TOASTER`/..
-MANAGE=$BBBASEDIR/lib/toaster/manage.py
-OEROOT=`dirname $TOASTER`/../..
+MANAGE="python3 $BBBASEDIR/lib/toaster/manage.py"
+OE_ROOT=`dirname $TOASTER`/../..
# this is the configuraton file we are using for toaster
# we are using the same logic that oe-setup-builddir uses
@@ -144,29 +139,17 @@ OEROOT=`dirname $TOASTER`/../..
# in the local layers that currently make using an arbitrary
# toasterconf.json difficult.
-. $OEROOT/.templateconf
+. $OE_ROOT/.templateconf
if [ -n "$TEMPLATECONF" ]; then
if [ ! -d "$TEMPLATECONF" ]; then
# Allow TEMPLATECONF=meta-xyz/conf as a shortcut
- if [ -d "$OEROOT/$TEMPLATECONF" ]; then
- TEMPLATECONF="$OEROOT/$TEMPLATECONF"
- fi
- if [ ! -d "$TEMPLATECONF" ]; then
- echo >&2 "Error: '$TEMPLATECONF' must be a directory containing toasterconf.json"
- return 1
+ if [ -d "$OE_ROOT/$TEMPLATECONF" ]; then
+ TEMPLATECONF="$OE_ROOT/$TEMPLATECONF"
fi
fi
fi
-if [ "$TOASTER_CONF" = "" ]; then
- TOASTER_CONF="$TEMPLATECONF/toasterconf.json"
- export TOASTER_CONF=$(python -c "import os; print os.path.realpath('$TOASTER_CONF')")
-fi
-
-if [ ! -f $TOASTER_CONF ]; then
- echo "$TOASTER_CONF configuration file not found. Set TOASTER_CONF to specify file or fix .templateconf"
- return 1
-fi
+unset OE_ROOT
# this defines the dir toaster will use for
# 1) clones of layers (in _toaster_clones )
@@ -178,7 +161,7 @@ fi
export TOASTER_DIR=`pwd`
WEBSERVER=1
-WEB_PORT="8000"
+ADDR_PORT="localhost:8000"
unset CMD
for param in $*; do
case $param in
@@ -192,7 +175,24 @@ for param in $*; do
CMD=$param
;;
webport=*)
- WEB_PORT="${param#*=}"
+ ADDR_PORT="${param#*=}"
+ # Split the addr:port string
+ ADDR=`echo $ADDR_PORT | cut -f 1 -d ':'`
+ PORT=`echo $ADDR_PORT | cut -f 2 -d ':'`
+ # If only a port has been speified then set address to localhost.
+ if [ $ADDR = $PORT ] ; then
+ ADDR_PORT="localhost:$PORT"
+ fi
+ ;;
+ --help)
+ echo "$HELP"
+ return 0
+ ;;
+ *)
+ echo "$HELP"
+ return 1
+ ;;
+
esac
done
@@ -226,11 +226,9 @@ if [ "$CMD" = "start" ] ; then
return 1
fi
elif [ "$CMD" = "" ]; then
- if [ -z "$BBSERVER" ]; then
- CMD="start"
- else
- CMD="stop"
- fi
+ echo "No command specified"
+ echo "$HELP"
+ return 1
fi
echo "The system will $CMD."
@@ -241,15 +239,9 @@ case $CMD in
start )
# check if addr:port is not in use
if [ "$CMD" == 'start' ]; then
- $MANAGE checksocket "0.0.0.0:$WEB_PORT" || return 1
- fi
-
- # kill Toaster web server if it's alive
- if [ -e $BUILDDIR/.toastermain.pid ] && kill -0 `cat $BUILDDIR/.toastermain.pid`; then
- echo "Warning: bitbake appears to be dead, but the Toaster web server is running." 1>&2
- echo " Something fishy is going on." 1>&2
- echo "Cleaning up the web server to start from a clean slate."
- webserverKillAll
+ if [ $WEBSERVER -gt 0 ]; then
+ $MANAGE checksocket "$ADDR_PORT" || return 1
+ fi
fi
# Create configuration file
@@ -262,7 +254,6 @@ case $CMD in
return 4
fi
export BITBAKE_UI='toasterui'
- export DATABASE_URL=`$MANAGE get-dburl`
$MANAGE runbuilds & echo $! >${BUILDDIR}/.runbuilds.pid
# set fail safe stop system on terminal exit
trap stop_system SIGHUP
diff --git a/import-layers/yocto-poky/bitbake/bin/toaster-eventreplay b/import-layers/yocto-poky/bitbake/bin/toaster-eventreplay
index 615a7aed1..80967a093 100755
--- a/import-layers/yocto-poky/bitbake/bin/toaster-eventreplay
+++ b/import-layers/yocto-poky/bitbake/bin/toaster-eventreplay
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
@@ -21,154 +21,106 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+"""
+This command takes a filename as a single parameter. The filename is read
+as a build eventlog, and the ToasterUI is used to process events in the file
+and log data in the database
+"""
-# This command takes a filename as a single parameter. The filename is read
-# as a build eventlog, and the ToasterUI is used to process events in the file
-# and log data in the database
-
-from __future__ import print_function
import os
-import sys, logging
+import sys
+import json
+import pickle
+import codecs
-# mangle syspath to allow easy import of modules
-sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
- 'lib'))
+from collections import namedtuple
+# mangle syspath to allow easy import of modules
+from os.path import join, dirname, abspath
+sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib'))
import bb.cooker
from bb.ui import toasterui
-import sys
-import logging
-import json, pickle
-
-
-class FileReadEventsServerConnection():
- """ Emulates a connection to a bitbake server that feeds
- events coming actually read from a saved log file.
- """
-
- class MockConnection():
- """ fill-in for the proxy to the server. we just return generic data
+class EventPlayer:
+ """Emulate a connection to a bitbake server."""
+
+ def __init__(self, eventfile, variables):
+ self.eventfile = eventfile
+ self.variables = variables
+ self.eventmask = []
+
+ def waitEvent(self, _timeout):
+ """Read event from the file."""
+ line = self.eventfile.readline().strip()
+ if not line:
+ return
+ try:
+ event_str = json.loads(line)['vars'].encode('utf-8')
+ event = pickle.loads(codecs.decode(event_str, 'base64'))
+ event_name = "%s.%s" % (event.__module__, event.__class__.__name__)
+ if event_name not in self.eventmask:
+ return
+ return event
+ except ValueError as err:
+ print("Failed loading ", line)
+ raise err
+
+ def runCommand(self, command_line):
+ """Emulate running a command on the server."""
+ name = command_line[0]
+
+ if name == "getVariable":
+ var_name = command_line[1]
+ variable = self.variables.get(var_name)
+ if variable:
+ return variable['v'], None
+ return None, "Missing variable %s" % var_name
+
+ elif name == "getAllKeysWithFlags":
+ dump = {}
+ flaglist = command_line[1]
+ for key, val in self.variables.items():
+ try:
+ if not key.startswith("__"):
+ dump[key] = {
+ 'v': val['v'],
+ 'history' : val['history'],
+ }
+ for flag in flaglist:
+ dump[key][flag] = val[flag]
+ except Exception as err:
+ print(err)
+ return (dump, None)
+
+ elif name == 'setEventMask':
+ self.eventmask = command_line[-1]
+ return True, None
+
+ else:
+ raise Exception("Command %s not implemented" % command_line[0])
+
+ def getEventHandle(self):
"""
- def __init__(self, sc):
- self._sc = sc
-
- def runCommand(self, commandArray):
- """ emulates running a command on the server; only read-only commands are accepted """
- command_name = commandArray[0]
-
- if command_name == "getVariable":
- if commandArray[1] in self._sc._variables:
- return (self._sc._variables[commandArray[1]]['v'], None)
- return (None, "Missing variable")
-
- elif command_name == "getAllKeysWithFlags":
- dump = {}
- flaglist = commandArray[1]
- for k in self._sc._variables.keys():
- try:
- if not k.startswith("__"):
- v = self._sc._variables[k]['v']
- dump[k] = {
- 'v' : v ,
- 'history' : self._sc._variables[k]['history'],
- }
- for d in flaglist:
- dump[k][d] = self._sc._variables[k][d]
- except Exception as e:
- print(e)
- return (dump, None)
- else:
- raise Exception("Command %s not implemented" % commandArray[0])
-
- def terminateServer(self):
- """ do not do anything """
- pass
-
-
-
- class EventReader():
- def __init__(self, sc):
- self._sc = sc
- self.firstraise = 0
-
- def _create_event(self, line):
- def _import_class(name):
- assert len(name) > 0
- assert "." in name, name
-
- components = name.strip().split(".")
- modulename = ".".join(components[:-1])
- moduleklass = components[-1]
-
- module = __import__(modulename, fromlist=[str(moduleklass)])
- return getattr(module, moduleklass)
-
- # we build a toaster event out of current event log line
- try:
- event_data = json.loads(line.strip())
- event_class = _import_class(event_data['class'])
- event_object = pickle.loads(json.loads(event_data['vars']))
- except ValueError as e:
- print("Failed loading ", line)
- raise e
-
- if not isinstance(event_object, event_class):
- raise Exception("Error loading objects %s class %s ", event_object, event_class)
-
- return event_object
-
- def waitEvent(self, timeout):
-
- nextline = self._sc._eventfile.readline()
- if len(nextline) == 0:
- # the build data ended, while toasterui still waits for events.
- # this happens when the server was abruptly stopped, so we simulate this
- self.firstraise += 1
- if self.firstraise == 1:
- raise KeyboardInterrupt()
- else:
- return None
- else:
- self._sc.lineno += 1
- return self._create_event(nextline)
-
-
- def _readVariables(self, variableline):
- self._variables = json.loads(variableline.strip())['allvariables']
-
-
- def __init__(self, file_name):
- self.connection = FileReadEventsServerConnection.MockConnection(self)
- self._eventfile = open(file_name, "r")
-
- # we expect to have the variable dump at the start of the file
- self.lineno = 1
- self._readVariables(self._eventfile.readline())
-
- self.events = FileReadEventsServerConnection.EventReader(self)
-
-
-
+ This method is called by toasterui.
+ The return value is passed to self.runCommand but not used there.
+ """
+ pass
+def main(argv):
+ with open(argv[-1]) as eventfile:
+ # load variables from the first line
+ variables = json.loads(eventfile.readline().strip())['allvariables']
-class MockConfigParameters():
- """ stand-in for cookerdata.ConfigParameters; as we don't really config a cooker, this
- serves just to supply needed interfaces for the toaster ui to work """
- def __init__(self):
- self.observe_only = True # we can only read files
+ params = namedtuple('ConfigParams', ['observe_only'])(True)
+ player = EventPlayer(eventfile, variables)
+ return toasterui.main(player, player, params)
# run toaster ui on our mock bitbake class
if __name__ == "__main__":
- if len(sys.argv) < 2:
- print("Usage: %s event.log " % sys.argv[0])
+ if len(sys.argv) != 2:
+ print("Usage: %s <event file>" % os.path.basename(sys.argv[0]))
sys.exit(1)
- file_name = sys.argv[-1]
- mock_connection = FileReadEventsServerConnection(file_name)
- configParams = MockConfigParameters()
-
- # run the main program and set exit code to the returned value
- sys.exit(toasterui.main(mock_connection.connection, mock_connection.events, configParams))
+ sys.exit(main(sys.argv))
OpenPOWER on IntegriCloud