summaryrefslogtreecommitdiff
path: root/bitbake/lib/bb/cooker.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/cooker.py')
-rw-r--r--bitbake/lib/bb/cooker.py182
1 files changed, 108 insertions, 74 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 2406dfe95..488bc610d 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -22,11 +22,13 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-import sys, os, getopt, glob, copy, os.path, re, time
+from __future__ import print_function
+import sys, os, glob, os.path, re, time
+import sre_constants
+from cStringIO import StringIO
+from contextlib import closing
import bb
-from bb import utils, data, parse, event, cache, providers, taskdata, runqueue
-from bb import command
-import itertools, sre_constants
+from bb import utils, data, parse, event, cache, providers, taskdata, command, runqueue
class MultipleMatches(Exception):
"""
@@ -121,11 +123,11 @@ class BBCooker:
self.commandlineAction = None
if 'world' in self.configuration.pkgs_to_build:
- bb.error("'world' is not a valid target for --environment.")
+ bb.msg.error(bb.msg.domain.Build, "'world' is not a valid target for --environment.")
elif len(self.configuration.pkgs_to_build) > 1:
- bb.error("Only one target can be used with the --environment option.")
+ bb.msg.error(bb.msg.domain.Build, "Only one target can be used with the --environment option.")
elif self.configuration.buildfile and len(self.configuration.pkgs_to_build) > 0:
- bb.error("No target should be used with the --environment and --buildfile options.")
+ bb.msg.error(bb.msg.domain.Build, "No target should be used with the --environment and --buildfile options.")
elif len(self.configuration.pkgs_to_build) > 0:
self.commandlineAction = ["showEnvironmentTarget", self.configuration.pkgs_to_build]
else:
@@ -138,21 +140,18 @@ class BBCooker:
self.commandlineAction = ["showVersions"]
elif self.configuration.parse_only:
self.commandlineAction = ["parseFiles"]
- # FIXME - implement
- #elif self.configuration.interactive:
- # self.interactiveMode()
elif self.configuration.dot_graph:
if self.configuration.pkgs_to_build:
self.commandlineAction = ["generateDotGraph", self.configuration.pkgs_to_build, self.configuration.cmd]
else:
self.commandlineAction = None
- bb.error("Please specify a package name for dependency graph generation.")
+ bb.msg.error(bb.msg.domain.Build, "Please specify a package name for dependency graph generation.")
else:
if self.configuration.pkgs_to_build:
self.commandlineAction = ["buildTargets", self.configuration.pkgs_to_build, self.configuration.cmd]
else:
self.commandlineAction = None
- bb.error("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
+ bb.msg.error(bb.msg.domain.Build, "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
def runCommands(self, server, data, abort):
"""
@@ -174,14 +173,14 @@ class BBCooker:
except bb.build.FuncFailed:
bb.msg.error(bb.msg.domain.Build, "task stack execution failed")
raise
- except bb.build.EventException, e:
+ except bb.build.EventException as e:
event = e.args[1]
bb.msg.error(bb.msg.domain.Build, "%s event exception, aborting" % bb.event.getName(event))
raise
def tryBuild(self, fn, task):
"""
- Build a provider and its dependencies.
+ Build a provider and its dependencies.
build_depends is a list of previous build dependencies (not runtime)
If build_depends is empty, we're dealing with a runtime depends
"""
@@ -206,7 +205,7 @@ class BBCooker:
# Sort by priority
for pn in pkg_pn:
- (last_ver,last_file,pref_ver,pref_file) = bb.providers.findBestProvider(pn, self.configuration.data, self.status)
+ (last_ver, last_file, pref_ver, pref_file) = bb.providers.findBestProvider(pn, self.configuration.data, self.status)
preferred_versions[pn] = (pref_ver, pref_file)
latest_versions[pn] = (last_ver, last_file)
@@ -260,27 +259,22 @@ class BBCooker:
if fn:
try:
envdata = self.bb_cache.loadDataFull(fn, self.configuration.data)
- except IOError, e:
+ except IOError as e:
bb.msg.error(bb.msg.domain.Parsing, "Unable to read %s: %s" % (fn, e))
raise
- except Exception, e:
+ except Exception as e:
bb.msg.error(bb.msg.domain.Parsing, "%s" % e)
raise
- class dummywrite:
- def __init__(self):
- self.writebuf = ""
- def write(self, output):
- self.writebuf = self.writebuf + output
-
# emit variables and shell functions
try:
data.update_data(envdata)
- wb = dummywrite()
- data.emit_env(wb, envdata, True)
- bb.msg.plain(wb.writebuf)
- except Exception, e:
+ with closing(StringIO()) as env:
+ data.emit_env(env, envdata, True)
+ bb.msg.plain(env.getvalue())
+ except Exception as e:
bb.msg.fatal(bb.msg.domain.Parsing, "%s" % e)
+
# emit the metadata which isnt valid shell
data.expandKeys(envdata)
for e in envdata.keys():
@@ -315,7 +309,7 @@ class BBCooker:
rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist)
rq.prepare_runqueue()
- seen_fnids = []
+ seen_fnids = []
depend_tree = {}
depend_tree["depends"] = {}
depend_tree["tdepends"] = {}
@@ -352,7 +346,7 @@ class BBCooker:
depend_tree["rdepends-pn"][pn] = []
for rdep in taskdata.rdepids[fnid]:
- depend_tree["rdepends-pn"][pn].append(taskdata.run_names_index[rdep])
+ depend_tree["rdepends-pn"][pn].append(taskdata.run_names_index[rdep])
rdepends = self.status.rundeps[fn]
for package in rdepends:
@@ -397,51 +391,51 @@ class BBCooker:
# Prints a flattened form of package-depends below where subpackages of a package are merged into the main pn
depends_file = file('pn-depends.dot', 'w' )
- print >> depends_file, "digraph depends {"
+ print("digraph depends {", file=depends_file)
for pn in depgraph["pn"]:
fn = depgraph["pn"][pn]["filename"]
version = depgraph["pn"][pn]["version"]
- print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn)
+ print('"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn), file=depends_file)
for pn in depgraph["depends"]:
for depend in depgraph["depends"][pn]:
- print >> depends_file, '"%s" -> "%s"' % (pn, depend)
+ print('"%s" -> "%s"' % (pn, depend), file=depends_file)
for pn in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][pn]:
- print >> depends_file, '"%s" -> "%s" [style=dashed]' % (pn, rdepend)
- print >> depends_file, "}"
+ print('"%s" -> "%s" [style=dashed]' % (pn, rdepend), file=depends_file)
+ print("}", file=depends_file)
bb.msg.plain("PN dependencies saved to 'pn-depends.dot'")
depends_file = file('package-depends.dot', 'w' )
- print >> depends_file, "digraph depends {"
+ print("digraph depends {", file=depends_file)
for package in depgraph["packages"]:
pn = depgraph["packages"][package]["pn"]
fn = depgraph["packages"][package]["filename"]
version = depgraph["packages"][package]["version"]
if package == pn:
- print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn)
+ print('"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn), file=depends_file)
else:
- print >> depends_file, '"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn)
+ print('"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn), file=depends_file)
for depend in depgraph["depends"][pn]:
- print >> depends_file, '"%s" -> "%s"' % (package, depend)
+ print('"%s" -> "%s"' % (package, depend), file=depends_file)
for package in depgraph["rdepends-pkg"]:
for rdepend in depgraph["rdepends-pkg"][package]:
- print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend)
+ print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
for package in depgraph["rrecs-pkg"]:
for rdepend in depgraph["rrecs-pkg"][package]:
- print >> depends_file, '"%s" -> "%s" [style=dashed]' % (package, rdepend)
- print >> depends_file, "}"
+ print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
+ print("}", file=depends_file)
bb.msg.plain("Package dependencies saved to 'package-depends.dot'")
tdepends_file = file('task-depends.dot', 'w' )
- print >> tdepends_file, "digraph depends {"
+ print("digraph depends {", file=tdepends_file)
for task in depgraph["tdepends"]:
(pn, taskname) = task.rsplit(".", 1)
fn = depgraph["pn"][pn]["filename"]
version = depgraph["pn"][pn]["version"]
- print >> tdepends_file, '"%s.%s" [label="%s %s\\n%s\\n%s"]' % (pn, taskname, pn, taskname, version, fn)
+ print('"%s.%s" [label="%s %s\\n%s\\n%s"]' % (pn, taskname, pn, taskname, version, fn), file=tdepends_file)
for dep in depgraph["tdepends"][task]:
- print >> tdepends_file, '"%s" -> "%s"' % (task, dep)
- print >> tdepends_file, "}"
+ print('"%s" -> "%s"' % (task, dep), file=tdepends_file)
+ print("}", file=tdepends_file)
bb.msg.plain("Task dependencies saved to 'task-depends.dot'")
def buildDepgraph( self ):
@@ -452,9 +446,12 @@ class BBCooker:
bb.data.update_data(localdata)
bb.data.expandKeys(localdata)
+ matched = set()
def calc_bbfile_priority(filename):
- for (regex, pri) in self.status.bbfile_config_priorities:
+ for _, _, regex, pri in self.status.bbfile_config_priorities:
if regex.match(filename):
+ if not regex in matched:
+ matched.add(regex)
return pri
return 0
@@ -473,6 +470,11 @@ class BBCooker:
for p in self.status.pkg_fn:
self.status.bbfile_priority[p] = calc_bbfile_priority(p)
+ for collection, pattern, regex, _ in self.status.bbfile_config_priorities:
+ if not regex in matched:
+ bb.msg.warn(bb.msg.domain.Provider, "No bb files matched BBFILE_PATTERN_%s '%s'" %
+ (collection, pattern))
+
def buildWorldTargetList(self):
"""
Build package list for "bitbake world"
@@ -505,31 +507,57 @@ class BBCooker:
"""Drop off into a shell"""
try:
from bb import shell
- except ImportError, details:
+ except ImportError as details:
bb.msg.fatal(bb.msg.domain.Parsing, "Sorry, shell not available (%s)" % details )
else:
shell.start( self )
+ def _findLayerConf(self):
+ path = os.getcwd()
+ while path != "/":
+ bblayers = os.path.join(path, "conf", "bblayers.conf")
+ if os.path.exists(bblayers):
+ return bblayers
+
+ path, _ = os.path.split(path)
+
def parseConfigurationFiles(self, files):
try:
data = self.configuration.data
for f in files:
data = bb.parse.handle(f, data)
- layerconf = os.path.join(os.getcwd(), "conf", "bblayers.conf")
- if os.path.exists(layerconf):
+ layerconf = self._findLayerConf()
+ if layerconf:
bb.msg.debug(2, bb.msg.domain.Parsing, "Found bblayers.conf (%s)" % layerconf)
data = bb.parse.handle(layerconf, data)
layers = (bb.data.getVar('BBLAYERS', data, True) or "").split()
+ data = bb.data.createCopy(data)
for layer in layers:
bb.msg.debug(2, bb.msg.domain.Parsing, "Adding layer %s" % layer)
bb.data.setVar('LAYERDIR', layer, data)
data = bb.parse.handle(os.path.join(layer, "conf", "layer.conf"), data)
+ # XXX: Hack, relies on the local keys of the datasmart
+ # instance being stored in the 'dict' attribute and makes
+ # assumptions about how variable expansion works, but
+ # there's no better way to force an expansion of a single
+ # variable across the datastore today, and this at least
+ # lets us reference LAYERDIR without having to immediately
+ # eval all our variables that use it.
+ for key in data.dict:
+ if key != "_data":
+ value = data.getVar(key, False)
+ if value and "${LAYERDIR}" in value:
+ data.setVar(key, value.replace("${LAYERDIR}", layer))
+
bb.data.delVar('LAYERDIR', data)
+ if not data.getVar("BBPATH", True):
+ bb.fatal("The BBPATH variable is not set")
+
data = bb.parse.handle(os.path.join("conf", "bitbake.conf"), data)
self.configuration.data = data
@@ -541,16 +569,17 @@ class BBCooker:
# Nomally we only register event handlers at the end of parsing .bb files
# We register any handlers we've found so far here...
- for var in data.getVar('__BBHANDLERS', self.configuration.data) or []:
- bb.event.register(var,bb.data.getVar(var, self.configuration.data))
+ for var in bb.data.getVar('__BBHANDLERS', self.configuration.data) or []:
+ bb.event.register(var, bb.data.getVar(var, self.configuration.data))
bb.fetch.fetcher_init(self.configuration.data)
bb.event.fire(bb.event.ConfigParsed(), self.configuration.data)
- except IOError, e:
+
+ except IOError as e:
bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (files, str(e)))
- except bb.parse.ParseError, details:
+ except bb.parse.ParseError as details:
bb.msg.fatal(bb.msg.domain.Parsing, "Unable to parse %s (%s)" % (files, details) )
def handleCollections( self, collections ):
@@ -573,7 +602,7 @@ class BBCooker:
continue
try:
pri = int(priority)
- self.status.bbfile_config_priorities.append((cre, pri))
+ self.status.bbfile_config_priorities.append((c, regex, cre, pri))
except ValueError:
bb.msg.error(bb.msg.domain.Parsing, "invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
@@ -582,8 +611,8 @@ class BBCooker:
Setup any variables needed before starting a build
"""
if not bb.data.getVar("BUILDNAME", self.configuration.data):
- bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data)
- bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()), self.configuration.data)
+ bb.data.setVar("BUILDNAME", time.strftime('%Y%m%d%H%M'), self.configuration.data)
+ bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S', time.gmtime()), self.configuration.data)
def matchFiles(self, buildfile):
"""
@@ -630,13 +659,19 @@ class BBCooker:
if (task == None):
task = self.configuration.cmd
- fn = self.matchFile(buildfile)
+ self.bb_cache = bb.cache.init(self)
+ self.status = bb.cache.CacheData()
+
+ (fn, cls) = self.bb_cache.virtualfn2realfn(buildfile)
+ buildfile = self.matchFile(fn)
+ fn = self.bb_cache.realfn2virtual(buildfile, cls)
+
self.buildSetVars()
# Load data into the cache for fn and parse the loaded cache data
- self.bb_cache = bb.cache.init(self)
- self.status = bb.cache.CacheData()
- self.bb_cache.loadData(fn, self.configuration.data, self.status)
+ the_data = self.bb_cache.loadDataFull(fn, self.configuration.data)
+ self.bb_cache.setData(fn, buildfile, the_data)
+ self.bb_cache.handle_data(fn, self.status)
# Tweak some variables
item = self.bb_cache.getVar('PN', fn, True)
@@ -675,8 +710,8 @@ class BBCooker:
failures = 0
try:
retval = rq.execute_runqueue()
- except runqueue.TaskFailure, fnids:
- for fnid in fnids:
+ except runqueue.TaskFailure as exc:
+ for fnid in exc.args:
bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid])
failures = failures + 1
retval = False
@@ -711,8 +746,8 @@ class BBCooker:
failures = 0
try:
retval = rq.execute_runqueue()
- except runqueue.TaskFailure, fnids:
- for fnid in fnids:
+ except runqueue.TaskFailure as exc:
+ for fnid in exc.args:
bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid])
failures = failures + 1
retval = False
@@ -769,10 +804,10 @@ class BBCooker:
ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
self.status.ignored_dependencies = set(ignore.split())
-
+
for dep in self.configuration.extra_assume_provided:
self.status.ignored_dependencies.add(dep)
-
+
self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
@@ -810,7 +845,7 @@ class BBCooker:
for f in contents:
(root, ext) = os.path.splitext(f)
if ext == ".bb":
- bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
+ bbfiles.append(os.path.abspath(os.path.join(os.getcwd(), f)))
return bbfiles
def find_bbfiles( self, path ):
@@ -822,7 +857,7 @@ class BBCooker:
for ignored in ('SCCS', 'CVS', '.svn'):
if ignored in dirs:
dirs.remove(ignored)
- found += [join(dir,f) for f in files if f.endswith('.bb')]
+ found += [join(dir, f) for f in files if f.endswith('.bb')]
return found
@@ -906,9 +941,9 @@ class BBCooker:
pout.close()
else:
self.server.serve_forever()
-
+
bb.event.fire(CookerExit(), self.configuration.event_data)
-
+
class CookerExit(bb.event.Event):
"""
Notify clients of the Cooker shutdown
@@ -937,9 +972,9 @@ class CookerParser:
self.pointer = 0
def parse_next(self):
+ cooker = self.cooker
if self.pointer < len(self.filelist):
f = self.filelist[self.pointer]
- cooker = self.cooker
try:
fromCache, skipped, virtuals = cooker.bb_cache.loadData(f, cooker.configuration.data, cooker.status)
@@ -951,7 +986,7 @@ class CookerParser:
self.skipped += skipped
self.virtuals += virtuals
- except IOError, e:
+ except IOError as e:
self.error += 1
cooker.bb_cache.remove(f)
bb.msg.error(bb.msg.domain.Collection, "opening %s: %s" % (f, e))
@@ -960,7 +995,7 @@ class CookerParser:
cooker.bb_cache.remove(f)
cooker.bb_cache.sync()
raise
- except Exception, e:
+ except Exception as e:
self.error += 1
cooker.bb_cache.remove(f)
bb.msg.error(bb.msg.domain.Collection, "%s while parsing %s" % (e, f))
@@ -978,4 +1013,3 @@ class CookerParser:
raise ParsingErrorsFound
return False
return True
-