summaryrefslogtreecommitdiff
path: root/yocto-poky/bitbake/lib/bb/cooker.py
diff options
context:
space:
mode:
Diffstat (limited to 'yocto-poky/bitbake/lib/bb/cooker.py')
-rw-r--r--yocto-poky/bitbake/lib/bb/cooker.py141
1 files changed, 84 insertions, 57 deletions
diff --git a/yocto-poky/bitbake/lib/bb/cooker.py b/yocto-poky/bitbake/lib/bb/cooker.py
index 4df88818f..9b565fc37 100644
--- a/yocto-poky/bitbake/lib/bb/cooker.py
+++ b/yocto-poky/bitbake/lib/bb/cooker.py
@@ -67,6 +67,14 @@ class CollectionError(bb.BBHandledException):
class state:
initial, parsing, running, shutdown, forceshutdown, stopped, error = range(7)
+ @classmethod
+ def get_name(cls, code):
+ for name in dir(cls):
+ value = getattr(cls, name)
+ if type(value) == type(cls.initial) and value == code:
+ return name
+ raise ValueError("Invalid status code: %s" % code)
+
class SkippedPackage:
def __init__(self, info = None, reason = None):
@@ -136,6 +144,10 @@ class BBCooker:
self.watcher.bbwatchedfiles = []
self.notifier = pyinotify.Notifier(self.watcher, self.notifications)
+ # If being called by something like tinfoil, we need to clean cached data
+ # which may now be invalid
+ bb.parse.__mtime_cache = {}
+ bb.parse.BBHandler.cached_statements = {}
self.initConfigurationData()
@@ -189,13 +201,13 @@ class BBCooker:
def config_notifications(self, event):
if not event.pathname in self.configwatcher.bbwatchedfiles:
return
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.baseconfig_valid = False
def notifications(self, event):
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.parsecache_valid = False
def add_filewatch(self, deps, watcher=None):
@@ -234,9 +246,9 @@ class BBCooker:
def sigterm_exception(self, signum, stackframe):
if signum == signal.SIGTERM:
- bb.warn("Cooker recieved SIGTERM, shutting down...")
+ bb.warn("Cooker received SIGTERM, shutting down...")
elif signum == signal.SIGHUP:
- bb.warn("Cooker recieved SIGHUP, shutting down...")
+ bb.warn("Cooker received SIGHUP, shutting down...")
self.state = state.forceshutdown
def setFeatures(self, features):
@@ -645,7 +657,7 @@ class BBCooker:
data.expandKeys(envdata)
for e in envdata.keys():
if data.getVarFlag( e, 'python', envdata ):
- logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, True))
+ logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, False))
def buildTaskData(self, pkgs_to_build, task, abort, allowincomplete=False):
@@ -717,8 +729,15 @@ class BBCooker:
depend_tree["packages"] = {}
depend_tree["rdepends-pkg"] = {}
depend_tree["rrecs-pkg"] = {}
+ depend_tree['providermap'] = {}
depend_tree["layer-priorities"] = self.recipecache.bbfile_config_priorities
+ for name, fn in taskdata.get_providermap().iteritems():
+ pn = self.recipecache.pkg_fn[fn]
+ if name != pn:
+ version = "%s:%s-%s" % self.recipecache.pkg_pepvpr[fn]
+ depend_tree['providermap'][name] = (pn, version)
+
for task in xrange(len(rq.rqdata.runq_fnid)):
taskname = rq.rqdata.runq_task[task]
fnid = rq.rqdata.runq_fnid[task]
@@ -893,7 +912,7 @@ class BBCooker:
logger.info("PN build list saved to 'pn-buildlist'")
for pn in depgraph["depends"]:
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (pn, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (pn, depend), file=depends_file)
for pn in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][pn]:
print('"%s" -> "%s" [style=dashed]' % (pn, rdepend), file=depends_file)
@@ -911,13 +930,13 @@ class BBCooker:
else:
print('"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn), file=depends_file)
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (package, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (package, depend), file=depends_file)
for package in depgraph["rdepends-pkg"]:
for rdepend in depgraph["rdepends-pkg"][package]:
print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
for package in depgraph["rrecs-pkg"]:
for rdepend in depgraph["rrecs-pkg"][package]:
- print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
+ print('"%s" -> "%s" [style=dotted]' % (package, rdepend), file=depends_file)
print("}", file=depends_file)
logger.info("Package dependencies saved to 'package-depends.dot'")
@@ -1019,22 +1038,21 @@ class BBCooker:
def findFilesMatchingInDir(self, filepattern, directory):
"""
- Searches for files matching the regex 'pattern' which are children of
+ Searches for files containing the substring 'filepattern' which are children of
'directory' in each BBPATH. i.e. to find all rootfs package classes available
to BitBake one could call findFilesMatchingInDir(self, 'rootfs_', 'classes')
or to find all machine configuration files one could call:
- findFilesMatchingInDir(self, 'conf/machines', 'conf')
+ findFilesMatchingInDir(self, '.conf', 'conf/machine')
"""
matches = []
- p = re.compile(re.escape(filepattern))
bbpaths = self.data.getVar('BBPATH', True).split(':')
for path in bbpaths:
dirpath = os.path.join(path, directory)
if os.path.exists(dirpath):
for root, dirs, files in os.walk(dirpath):
for f in files:
- if p.search(f):
+ if filepattern in f:
matches.append(f)
if matches:
@@ -1072,7 +1090,7 @@ class BBCooker:
for pfn in self.recipecache.pkg_fn:
inherits = self.recipecache.inherits.get(pfn, None)
- if inherits and inherits.count(klass) > 0:
+ if inherits and klass in inherits:
pkg_list.append(self.recipecache.pkg_fn[pfn])
return pkg_list
@@ -1095,28 +1113,6 @@ class BBCooker:
tree = self.generatePkgDepTreeData(pkgs, 'build')
bb.event.fire(bb.event.TargetsTreeGenerated(tree), self.data)
- def buildWorldTargetList(self):
- """
- Build package list for "bitbake world"
- """
- parselog.debug(1, "collating packages for \"world\"")
- for f in self.recipecache.possible_world:
- terminal = True
- pn = self.recipecache.pkg_fn[f]
-
- for p in self.recipecache.pn_provides[pn]:
- if p.startswith('virtual/'):
- parselog.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
- terminal = False
- break
- for pf in self.recipecache.providers[p]:
- if self.recipecache.pkg_fn[pf] != pn:
- parselog.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
- terminal = False
- break
- if terminal:
- self.recipecache.world_target.add(pn)
-
def interactiveMode( self ):
"""Drop off into a shell"""
try:
@@ -1353,7 +1349,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1389,7 +1385,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1437,14 +1433,21 @@ class BBCooker:
dump = {}
for k in self.data.keys():
try:
- v = self.data.getVar(k, True)
+ expand = True
+ flags = self.data.getVarFlags(k)
+ if flags and "func" in flags and "python" in flags:
+ expand = False
+ v = self.data.getVar(k, expand)
if not k.startswith("__") and not isinstance(v, bb.data_smart.DataSmart):
dump[k] = {
'v' : v ,
'history' : self.data.varhistory.variable(k),
}
for d in flaglist:
- dump[k][d] = self.data.getVarFlag(k, d)
+ if flags and d in flags:
+ dump[k][d] = flags[d]
+ else:
+ dump[k][d] = None
except Exception as e:
print(e)
return dump
@@ -1506,6 +1509,8 @@ class BBCooker:
# reload files for which we got notifications
for p in self.inotify_modified_files:
bb.parse.update_cache(p)
+ if p in bb.parse.BBHandler.cached_statements:
+ del bb.parse.BBHandler.cached_statements[p]
self.inotify_modified_files = []
if not self.baseconfig_valid:
@@ -1577,7 +1582,7 @@ class BBCooker:
parselog.warn("Explicit target \"%s\" is in ASSUME_PROVIDED, ignoring" % pkg)
if 'world' in pkgs_to_build:
- self.buildWorldTargetList()
+ bb.providers.buildWorldTargetList(self.recipecache)
pkgs_to_build.remove('world')
for t in self.recipecache.world_target:
pkgs_to_build.append(t)
@@ -1643,6 +1648,9 @@ class BBCooker:
else:
self.state = state.shutdown
+ if self.parser:
+ self.parser.shutdown(clean=not force, force=force)
+
def finishcommand(self):
self.state = state.initial
@@ -1760,18 +1768,32 @@ class CookerCollectFiles(object):
globbed = glob.glob(f)
if not globbed and os.path.exists(f):
globbed = [f]
- for g in globbed:
+ # glob gives files in order on disk. Sort to be deterministic.
+ for g in sorted(globbed):
if g not in newfiles:
newfiles.append(g)
bbmask = config.getVar('BBMASK', True)
if bbmask:
+ # First validate the individual regular expressions and ignore any
+ # that do not compile
+ bbmasks = []
+ for mask in bbmask.split():
+ try:
+ re.compile(mask)
+ bbmasks.append(mask)
+ except sre_constants.error:
+ collectlog.critical("BBMASK contains an invalid regular expression, ignoring: %s" % mask)
+
+ # Then validate the combined regular expressions. This should never
+ # fail, but better safe than sorry...
+ bbmask = "|".join(bbmasks)
try:
bbmask_compiled = re.compile(bbmask)
except sre_constants.error:
- collectlog.critical("BBMASK is not a valid regular expression, ignoring.")
- return list(newfiles), 0
+ collectlog.critical("BBMASK is not a valid regular expression, ignoring: %s" % bbmask)
+ bbmask = None
bbfiles = []
bbappend = []
@@ -1948,9 +1970,17 @@ class Parser(multiprocessing.Process):
def parse(self, filename, appends, caches_array):
try:
+ # Record the filename we're parsing into any events generated
+ def parse_filter(self, record):
+ record.taskpid = bb.event.worker_pid
+ record.fn = filename
+ return True
+
# Reset our environment and handlers to the original settings
bb.utils.set_context(self.context.copy())
bb.event.set_class_handlers(self.handlers.copy())
+ bb.event.LogHandler.filter = parse_filter
+
return True, bb.cache.Cache.parse(filename, appends, self.cfg, caches_array)
except Exception as exc:
tb = sys.exc_info()[2]
@@ -1981,8 +2011,6 @@ class CookerParser(object):
self.total = len(filelist)
self.current = 0
- self.num_processes = int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
- multiprocessing.cpu_count())
self.process_names = []
self.bb_cache = bb.cache.Cache(self.cfgdata, self.cfghash, cooker.caches_array)
@@ -1997,6 +2025,9 @@ class CookerParser(object):
self.toparse = self.total - len(self.fromcache)
self.progress_chunk = max(self.toparse / 100, 1)
+ self.num_processes = min(int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
+ multiprocessing.cpu_count()), len(self.willparse))
+
self.start()
self.haveshutdown = False
@@ -2007,8 +2038,9 @@ class CookerParser(object):
bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata)
def init():
Parser.cfg = self.cfgdata
- multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cfgdata,), exitpriority=1)
- multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, args=(self.cfgdata,), exitpriority=1)
+ bb.utils.set_process_name(multiprocessing.current_process().name)
+ multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, exitpriority=1)
+ multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, exitpriority=1)
self.feeder_quit = multiprocessing.Queue(maxsize=1)
self.parser_quit = multiprocessing.Queue(maxsize=self.num_processes)
@@ -2040,7 +2072,7 @@ class CookerParser(object):
bb.event.fire(event, self.cfgdata)
self.feeder_quit.put(None)
for process in self.processes:
- self.jobs.put(None)
+ self.parser_quit.put(None)
else:
self.feeder_quit.put('cancel')
@@ -2061,8 +2093,8 @@ class CookerParser(object):
sync = threading.Thread(target=self.bb_cache.sync)
sync.start()
multiprocessing.util.Finalize(None, sync.join, exitpriority=-100)
- bb.codeparser.parser_cache_savemerge(self.cooker.data)
- bb.fetch.fetcher_parse_done(self.cooker.data)
+ bb.codeparser.parser_cache_savemerge()
+ bb.fetch.fetcher_parse_done()
if self.cooker.configuration.profile:
profiles = []
for i in self.process_names:
@@ -2125,11 +2157,6 @@ class CookerParser(object):
logger.error('ExpansionError during parsing %s: %s', value.recipe, str(exc))
self.shutdown(clean=False)
return False
- except SyntaxError as exc:
- self.error += 1
- logger.error('Unable to parse %s', exc.recipe)
- self.shutdown(clean=False)
- return False
except Exception as exc:
self.error += 1
etype, value, tb = sys.exc_info()