summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Purdie <richard@openedhand.com>2008-03-03 22:01:45 +0000
committerRichard Purdie <richard@openedhand.com>2008-03-03 22:01:45 +0000
commitab191d21e2e5e1609206146d238af6ec0b3f0554 (patch)
tree728fa74dbf00f6b11964aa53b8427a0d221d6e91
parente88b4753781d54dc2625c3260c611d30ad76dbed (diff)
downloadopenembedded-core-ab191d21e2e5e1609206146d238af6ec0b3f0554.tar.gz
openembedded-core-ab191d21e2e5e1609206146d238af6ec0b3f0554.tar.bz2
openembedded-core-ab191d21e2e5e1609206146d238af6ec0b3f0554.zip
bitbake: Update to bitbake 1.8 branch head
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@3892 311d38ba-8fff-0310-9ca6-ca027cbcb966
-rw-r--r--bitbake/ChangeLog20
-rw-r--r--bitbake/lib/bb/__init__.py179
-rw-r--r--bitbake/lib/bb/build.py208
-rw-r--r--bitbake/lib/bb/cache.py63
-rw-r--r--bitbake/lib/bb/cooker.py97
-rw-r--r--bitbake/lib/bb/data_smart.py4
-rw-r--r--bitbake/lib/bb/event.py17
-rw-r--r--bitbake/lib/bb/fetch/__init__.py12
-rw-r--r--bitbake/lib/bb/parse/parse_py/BBHandler.py51
-rw-r--r--bitbake/lib/bb/runqueue.py142
-rw-r--r--bitbake/lib/bb/shell.py23
-rw-r--r--bitbake/lib/bb/taskdata.py5
-rw-r--r--bitbake/lib/bb/utils.py8
13 files changed, 359 insertions, 470 deletions
diff --git a/bitbake/ChangeLog b/bitbake/ChangeLog
index 7e6b7b26a4..d074a5e239 100644
--- a/bitbake/ChangeLog
+++ b/bitbake/ChangeLog
@@ -1,6 +1,26 @@
Changes in BitBake 1.8.x:
- Fix exit code for build failures in --continue mode
- Fix git branch tags fetching
+ - Change parseConfigurationFile so it works on real data, not a copy
+ - Handle 'base' inherit and all other INHERITs from parseConfigurationFile
+ instead of BBHandler
+ - Fix getVarFlags bug in data_smart
+ - Optmise cache handling by more quickly detecting an invalid cache, only
+ saving the cache when its changed, moving the cache validity check into
+ the parsing loop and factoring some getVar calls outside a for loop
+ - Cooker: Remove a debug message from the parsing loop to lower overhead
+ - Convert build.py exec_task to use getVarFlags
+ - Update shell to use cooker.buildFile
+ - Add StampUpdate event
+ - Convert -b option to use taskdata/runqueue
+ - Remove digraph and switch to new stamp checking code. exec_task no longer
+ honours dependencies
+ - Make fetcher timestamp updating non-fatal when permissions don't allow
+ updates
+ - Add BB_SCHEDULER variable/option ("completion" or "speed") controlling
+ the way bitbake schedules tasks
+ - Add BB_STAMP_POLICY variable/option ("perfile" or "full") controlling
+ how extensively stamps are looked at for validity
Changes in BitBake 1.8.10:
- Psyco is available only for x86 - do not use it on other architectures.
diff --git a/bitbake/lib/bb/__init__.py b/bitbake/lib/bb/__init__.py
index a126c17693..c452d529c1 100644
--- a/bitbake/lib/bb/__init__.py
+++ b/bitbake/lib/bb/__init__.py
@@ -46,7 +46,6 @@ __all__ = [
"pkgcmp",
"dep_parenreduce",
"dep_opconvert",
- "digraph",
# fetch
"decodeurl",
@@ -1128,184 +1127,6 @@ def dep_opconvert(mysplit, myuse):
mypos += 1
return newsplit
-class digraph:
- """beautiful directed graph object"""
-
- def __init__(self):
- self.dict={}
- #okeys = keys, in order they were added (to optimize firstzero() ordering)
- self.okeys=[]
- self.__callback_cache=[]
-
- def __str__(self):
- str = ""
- for key in self.okeys:
- str += "%s:\t%s\n" % (key, self.dict[key][1])
- return str
-
- def addnode(self,mykey,myparent):
- if not mykey in self.dict:
- self.okeys.append(mykey)
- if myparent==None:
- self.dict[mykey]=[0,[]]
- else:
- self.dict[mykey]=[0,[myparent]]
- self.dict[myparent][0]=self.dict[myparent][0]+1
- return
- if myparent and (not myparent in self.dict[mykey][1]):
- self.dict[mykey][1].append(myparent)
- self.dict[myparent][0]=self.dict[myparent][0]+1
-
- def delnode(self,mykey, ref = 1):
- """Delete a node
-
- If ref is 1, remove references to this node from other nodes.
- If ref is 2, remove nodes that reference this node."""
- if not mykey in self.dict:
- return
- for x in self.dict[mykey][1]:
- self.dict[x][0]=self.dict[x][0]-1
- del self.dict[mykey]
- while 1:
- try:
- self.okeys.remove(mykey)
- except ValueError:
- break
- if ref:
- __kill = []
- for k in self.okeys:
- if mykey in self.dict[k][1]:
- if ref == 1 or ref == 2:
- self.dict[k][1].remove(mykey)
- if ref == 2:
- __kill.append(k)
- for l in __kill:
- self.delnode(l, ref)
-
- def allnodes(self):
- "returns all nodes in the dictionary"
- keys = self.dict.keys()
- ret = []
- for key in keys:
- ret.append(key)
- ret.sort()
- return ret
-
- def firstzero(self):
- "returns first node with zero references, or NULL if no such node exists"
- for x in self.okeys:
- if self.dict[x][0]==0:
- return x
- return None
-
- def firstnonzero(self):
- "returns first node with nonzero references, or NULL if no such node exists"
- for x in self.okeys:
- if self.dict[x][0]!=0:
- return x
- return None
-
-
- def allzeros(self):
- "returns all nodes with zero references, or NULL if no such node exists"
- zerolist = []
- for x in self.dict.keys():
- if self.dict[x][0]==0:
- zerolist.append(x)
- return zerolist
-
- def hasallzeros(self):
- "returns 0/1, Are all nodes zeros? 1 : 0"
- zerolist = []
- for x in self.dict.keys():
- if self.dict[x][0]!=0:
- return 0
- return 1
-
- def empty(self):
- if len(self.dict)==0:
- return 1
- return 0
-
- def hasnode(self,mynode):
- return mynode in self.dict
-
- def getparents(self, item):
- if not self.hasnode(item):
- return []
- parents = self.dict[item][1]
- ret = []
- for parent in parents:
- ret.append(parent)
- ret.sort()
- return ret
-
- def getchildren(self, item):
- if not self.hasnode(item):
- return []
- children = [i for i in self.okeys if item in self.getparents(i)]
- return children
-
- def walkdown(self, item, callback, debug = None, usecache = False):
- if not self.hasnode(item):
- return 0
-
- if usecache:
- if self.__callback_cache.count(item):
- if debug:
- print "hit cache for item: %s" % item
- return 1
-
- parents = self.getparents(item)
- children = self.getchildren(item)
- for p in parents:
- if p in children:
-# print "%s is both parent and child of %s" % (p, item)
- if usecache:
- self.__callback_cache.append(p)
- ret = callback(self, p)
- if ret == 0:
- return 0
- continue
- if item == p:
- print "eek, i'm my own parent!"
- return 0
- if debug:
- print "item: %s, p: %s" % (item, p)
- ret = self.walkdown(p, callback, debug, usecache)
- if ret == 0:
- return 0
- if usecache:
- self.__callback_cache.append(item)
- return callback(self, item)
-
- def walkup(self, item, callback):
- if not self.hasnode(item):
- return 0
-
- parents = self.getparents(item)
- children = self.getchildren(item)
- for c in children:
- if c in parents:
- ret = callback(self, item)
- if ret == 0:
- return 0
- continue
- if item == c:
- print "eek, i'm my own child!"
- return 0
- ret = self.walkup(c, callback)
- if ret == 0:
- return 0
- return callback(self, item)
-
- def copy(self):
- mygraph=digraph()
- for x in self.dict.keys():
- mygraph.dict[x]=self.dict[x][:]
- mygraph.okeys=self.okeys[:]
- return mygraph
-
if __name__ == "__main__":
import doctest, bb
doctest.testmod(bb)
diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py
index 1c015fe9a3..25c03a0a4e 100644
--- a/bitbake/lib/bb/build.py
+++ b/bitbake/lib/bb/build.py
@@ -74,12 +74,21 @@ def exec_func(func, d, dirs = None):
if not body:
return
- cleandirs = (data.expand(data.getVarFlag(func, 'cleandirs', d), d) or "").split()
+ flags = data.getVarFlags(func, d)
+ for item in ['deps', 'check', 'interactive', 'python', 'cleandirs', 'dirs', 'lockfiles', 'fakeroot']:
+ if not item in flags:
+ flags[item] = None
+
+ ispython = flags['python']
+
+ cleandirs = (data.expand(flags['cleandirs'], d) or "").split()
for cdir in cleandirs:
os.system("rm -rf %s" % cdir)
- if not dirs:
- dirs = (data.expand(data.getVarFlag(func, 'dirs', d), d) or "").split()
+ if dirs:
+ dirs = data.expand(dirs, d)
+ else:
+ dirs = (data.expand(flags['dirs'], d) or "").split()
for adir in dirs:
mkdirhier(adir)
@@ -88,24 +97,22 @@ def exec_func(func, d, dirs = None):
else:
adir = data.getVar('B', d, 1)
- adir = data.expand(adir, d)
-
try:
prevdir = os.getcwd()
except OSError:
- prevdir = data.expand('${TOPDIR}', d)
+ prevdir = data.getVar('TOPDIR', d, True)
if adir and os.access(adir, os.F_OK):
os.chdir(adir)
locks = []
- lockfiles = (data.expand(data.getVarFlag(func, 'lockfiles', d), d) or "").split()
+ lockfiles = (data.expand(flags['lockfiles'], d) or "").split()
for lock in lockfiles:
locks.append(bb.utils.lockfile(lock))
- if data.getVarFlag(func, "python", d):
+ if flags['python']:
exec_func_python(func, d)
else:
- exec_func_shell(func, d)
+ exec_func_shell(func, d, flags)
for lock in locks:
bb.utils.unlockfile(lock)
@@ -117,19 +124,20 @@ def exec_func_python(func, d):
"""Execute a python BB 'function'"""
import re, os
+ bbfile = bb.data.getVar('FILE', d, 1)
tmp = "def " + func + "():\n%s" % data.getVar(func, d)
tmp += '\n' + func + '()'
- comp = utils.better_compile(tmp, func, bb.data.getVar('FILE', d, 1) )
+ comp = utils.better_compile(tmp, func, bbfile)
prevdir = os.getcwd()
g = {} # globals
g['bb'] = bb
g['os'] = os
g['d'] = d
- utils.better_exec(comp,g,tmp, bb.data.getVar('FILE',d,1))
+ utils.better_exec(comp, g, tmp, bbfile)
if os.path.exists(prevdir):
os.chdir(prevdir)
-def exec_func_shell(func, d):
+def exec_func_shell(func, d, flags):
"""Execute a shell BB 'function' Returns true if execution was successful.
For this, it creates a bash shell script in the tmp dectory, writes the local
@@ -141,9 +149,9 @@ def exec_func_shell(func, d):
"""
import sys
- deps = data.getVarFlag(func, 'deps', d)
- check = data.getVarFlag(func, 'check', d)
- interact = data.getVarFlag(func, 'interactive', d)
+ deps = flags['deps']
+ check = flags['check']
+ interact = flags['interactive']
if check in globals():
if globals()[check](func, deps):
return
@@ -195,7 +203,7 @@ def exec_func_shell(func, d):
# execute function
prevdir = os.getcwd()
- if data.getVarFlag(func, "fakeroot", d):
+ if flags['fakeroot']:
maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1)
else:
maybe_fakeroot = ''
@@ -255,72 +263,29 @@ def exec_task(task, d):
a function is that a task exists in the task digraph, and therefore
has dependencies amongst other tasks."""
- # check if the task is in the graph..
- task_graph = data.getVar('_task_graph', d)
- if not task_graph:
- task_graph = bb.digraph()
- data.setVar('_task_graph', task_graph, d)
- task_cache = data.getVar('_task_cache', d)
- if not task_cache:
- task_cache = []
- data.setVar('_task_cache', task_cache, d)
- if not task_graph.hasnode(task):
- raise EventException("Missing node in task graph", InvalidTask(task, d))
-
- # check whether this task needs executing..
- if stamp_is_current(task, d):
- return 1
-
- # follow digraph path up, then execute our way back down
- def execute(graph, item):
- if data.getVarFlag(item, 'task', d):
- if item in task_cache:
- return 1
-
- if task != item:
- # deeper than toplevel, exec w/ deps
- exec_task(item, d)
- return 1
-
- try:
- bb.msg.debug(1, bb.msg.domain.Build, "Executing task %s" % item)
- old_overrides = data.getVar('OVERRIDES', d, 0)
- localdata = data.createCopy(d)
- data.setVar('OVERRIDES', 'task_%s:%s' % (item, old_overrides), localdata)
- data.update_data(localdata)
- event.fire(TaskStarted(item, localdata))
- exec_func(item, localdata)
- event.fire(TaskSucceeded(item, localdata))
- task_cache.append(item)
- data.setVar('_task_cache', task_cache, d)
- except FuncFailed, reason:
- bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % reason )
- failedevent = TaskFailed(item, d)
- event.fire(failedevent)
- raise EventException("Function failed in task: %s" % reason, failedevent)
-
- if data.getVarFlag(task, 'dontrundeps', d):
- execute(None, task)
- else:
- task_graph.walkdown(task, execute)
+ # Check whther this is a valid task
+ if not data.getVarFlag(task, 'task', d):
+ raise EventException("No such task", InvalidTask(task, d))
+
+ try:
+ bb.msg.debug(1, bb.msg.domain.Build, "Executing task %s" % task)
+ old_overrides = data.getVar('OVERRIDES', d, 0)
+ localdata = data.createCopy(d)
+ data.setVar('OVERRIDES', 'task_%s:%s' % (task, old_overrides), localdata)
+ data.update_data(localdata)
+ event.fire(TaskStarted(task, localdata))
+ exec_func(task, localdata)
+ event.fire(TaskSucceeded(task, localdata))
+ except FuncFailed, reason:
+ bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % reason )
+ failedevent = TaskFailed(task, d)
+ event.fire(failedevent)
+ raise EventException("Function failed in task: %s" % reason, failedevent)
# make stamp, or cause event and raise exception
if not data.getVarFlag(task, 'nostamp', d) and not data.getVarFlag(task, 'selfstamp', d):
make_stamp(task, d)
-def extract_stamp_data(d, fn):
- """
- Extracts stamp data from d which is either a data dictonary (fn unset)
- or a dataCache entry (fn set).
- """
- if fn:
- return (d.task_queues[fn], d.stamp[fn], d.task_deps[fn])
- task_graph = data.getVar('_task_graph', d)
- if not task_graph:
- task_graph = bb.digraph()
- data.setVar('_task_graph', task_graph, d)
- return (task_graph, data.getVar('STAMP', d, 1), None)
-
def extract_stamp(d, fn):
"""
Extracts stamp format which is either a data dictonary (fn unset)
@@ -330,49 +295,6 @@ def extract_stamp(d, fn):
return d.stamp[fn]
return data.getVar('STAMP', d, 1)
-def stamp_is_current(task, d, file_name = None, checkdeps = 1):
- """
- Check status of a given task's stamp.
- Returns 0 if it is not current and needs updating.
- (d can be a data dict or dataCache)
- """
-
- (task_graph, stampfn, taskdep) = extract_stamp_data(d, file_name)
-
- if not stampfn:
- return 0
-
- stampfile = "%s.%s" % (stampfn, task)
- if not os.access(stampfile, os.F_OK):
- return 0
-
- if checkdeps == 0:
- return 1
-
- import stat
- tasktime = os.stat(stampfile)[stat.ST_MTIME]
-
- _deps = []
- def checkStamp(graph, task):
- # check for existance
- if file_name:
- if 'nostamp' in taskdep and task in taskdep['nostamp']:
- return 1
- else:
- if data.getVarFlag(task, 'nostamp', d):
- return 1
-
- if not stamp_is_current(task, d, file_name, 0 ):
- return 0
-
- depfile = "%s.%s" % (stampfn, task)
- deptime = os.stat(depfile)[stat.ST_MTIME]
- if deptime > tasktime:
- return 0
- return 1
-
- return task_graph.walkdown(task, checkStamp)
-
def stamp_internal(task, d, file_name):
"""
Internal stamp helper function
@@ -409,40 +331,39 @@ def del_stamp(task, d, file_name = None):
stamp_internal(task, d, file_name)
def add_tasks(tasklist, d):
- task_graph = data.getVar('_task_graph', d)
task_deps = data.getVar('_task_deps', d)
- if not task_graph:
- task_graph = bb.digraph()
if not task_deps:
task_deps = {}
+ if not 'tasks' in task_deps:
+ task_deps['tasks'] = []
+ if not 'parents' in task_deps:
+ task_deps['parents'] = {}
for task in tasklist:
- deps = tasklist[task]
task = data.expand(task, d)
-
data.setVarFlag(task, 'task', 1, d)
- task_graph.addnode(task, None)
- for dep in deps:
- dep = data.expand(dep, d)
- if not task_graph.hasnode(dep):
- task_graph.addnode(dep, None)
- task_graph.addnode(task, dep)
+
+ if not task in task_deps['tasks']:
+ task_deps['tasks'].append(task)
flags = data.getVarFlags(task, d)
def getTask(name):
+ if not name in task_deps:
+ task_deps[name] = {}
if name in flags:
deptask = data.expand(flags[name], d)
- if not name in task_deps:
- task_deps[name] = {}
task_deps[name][task] = deptask
getTask('depends')
getTask('deptask')
getTask('rdeptask')
getTask('recrdeptask')
getTask('nostamp')
+ task_deps['parents'][task] = []
+ for dep in flags['deps']:
+ dep = data.expand(dep, d)
+ task_deps['parents'][task].append(dep)
# don't assume holding a reference
- data.setVar('_task_graph', task_graph, d)
data.setVar('_task_deps', task_deps, d)
def remove_task(task, kill, d):
@@ -450,22 +371,5 @@ def remove_task(task, kill, d):
If kill is 1, also remove tasks that depend on this task."""
- task_graph = data.getVar('_task_graph', d)
- if not task_graph:
- task_graph = bb.digraph()
- if not task_graph.hasnode(task):
- return
-
data.delVarFlag(task, 'task', d)
- ref = 1
- if kill == 1:
- ref = 2
- task_graph.delnode(task, ref)
- data.setVar('_task_graph', task_graph, d)
-
-def task_exists(task, d):
- task_graph = data.getVar('_task_graph', d)
- if not task_graph:
- task_graph = bb.digraph()
- data.setVar('_task_graph', task_graph, d)
- return task_graph.hasnode(task)
+
diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py
index 7d7e66ebd2..dad82a9b36 100644
--- a/bitbake/lib/bb/cache.py
+++ b/bitbake/lib/bb/cache.py
@@ -39,7 +39,7 @@ except ImportError:
import pickle
bb.msg.note(1, bb.msg.domain.Cache, "Importing cPickle failed. Falling back to a very slow implementation.")
-__cache_version__ = "127"
+__cache_version__ = "128"
class Cache:
"""
@@ -50,9 +50,11 @@ class Cache:
self.cachedir = bb.data.getVar("CACHE", cooker.configuration.data, True)
self.clean = {}
+ self.checked = {}
self.depends_cache = {}
self.data = None
self.data_fn = None
+ self.cacheclean = True
if self.cachedir in [None, '']:
self.has_cache = False
@@ -67,9 +69,20 @@ class Cache:
except OSError:
bb.mkdirhier( self.cachedir )
- if self.has_cache and (self.mtime(self.cachefile)):
+ if not self.has_cache:
+ return
+
+ # If any of configuration.data's dependencies are newer than the
+ # cache there isn't even any point in loading it...
+ newest_mtime = 0
+ deps = bb.data.getVar("__depends", cooker.configuration.data, True)
+ for f,old_mtime in deps:
+ if old_mtime > newest_mtime:
+ newest_mtime = old_mtime
+
+ if self.mtime(self.cachefile) >= newest_mtime:
try:
- p = pickle.Unpickler( file(self.cachefile,"rb"))
+ p = pickle.Unpickler(file(self.cachefile, "rb"))
self.depends_cache, version_data = p.load()
if version_data['CACHE_VER'] != __cache_version__:
raise ValueError, 'Cache Version Mismatch'
@@ -81,11 +94,8 @@ class Cache:
except (ValueError, KeyError):
bb.msg.note(1, bb.msg.domain.Cache, "Invalid cache found, rebuilding...")
self.depends_cache = {}
-
- if self.depends_cache:
- for fn in self.depends_cache.keys():
- self.clean[fn] = ""
- self.cacheValidUpdate(fn)
+ else:
+ bb.msg.note(1, bb.msg.domain.Cache, "Out of date cache found, rebuilding...")
def getVar(self, var, fn, exp = 0):
"""
@@ -97,7 +107,6 @@ class Cache:
2. We're learning what data to cache - serve from data
backend but add a copy of the data to the cache.
"""
-
if fn in self.clean:
return self.depends_cache[fn][var]
@@ -109,6 +118,7 @@ class Cache:
# yet setData hasn't been called to setup the right access. Very bad.
bb.msg.error(bb.msg.domain.Cache, "Parsing error data_fn %s and fn %s don't match" % (self.data_fn, fn))
+ self.cacheclean = False
result = bb.data.getVar(var, self.data, exp)
self.depends_cache[fn][var] = result
return result
@@ -131,6 +141,8 @@ class Cache:
Return a complete set of data for fn.
To do this, we need to parse the file.
"""
+ bb.msg.debug(1, bb.msg.domain.Cache, "Parsing %s (full)" % fn)
+
bb_data, skipped = self.load_bbfile(fn, cfgData)
return bb_data
@@ -142,11 +154,15 @@ class Cache:
to record the variables accessed.
Return the cache status and whether the file was skipped when parsed
"""
+ if fn not in self.checked:
+ self.cacheValidUpdate(fn)
if self.cacheValid(fn):
if "SKIPPED" in self.depends_cache[fn]:
return True, True
return True, False
+ bb.msg.debug(1, bb.msg.domain.Cache, "Parsing %s" % fn)
+
bb_data, skipped = self.load_bbfile(fn, cfgData)
self.setData(fn, bb_data)
return False, skipped
@@ -172,11 +188,10 @@ class Cache:
if not self.has_cache:
return False
- # Check file still exists
- if self.mtime(fn) == 0:
- bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s not longer exists" % fn)
- self.remove(fn)
- return False
+ self.checked[fn] = ""
+
+ # Pretend we're clean so getVar works
+ self.clean[fn] = ""
# File isn't in depends_cache
if not fn in self.depends_cache:
@@ -184,6 +199,12 @@ class Cache:
self.remove(fn)
return False
+ # Check file still exists
+ if self.mtime(fn) == 0:
+ bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s not longer exists" % fn)
+ self.remove(fn)
+ return False
+
# Check the file's timestamp
if bb.parse.cached_mtime(fn) > self.getVar("CACHETIMESTAMP", fn, True):
bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s changed" % fn)
@@ -195,6 +216,7 @@ class Cache:
for f,old_mtime in depends:
# Check if file still exists
if self.mtime(f) == 0:
+ self.remove(fn)
return False
new_mtime = bb.parse.cached_mtime(f)
@@ -203,7 +225,7 @@ class Cache:
self.remove(fn)
return False
- bb.msg.debug(2, bb.msg.domain.Cache, "Depends Cache: %s is clean" % fn)
+ #bb.msg.debug(2, bb.msg.domain.Cache, "Depends Cache: %s is clean" % fn)
if not fn in self.clean:
self.clean[fn] = ""
@@ -238,6 +260,10 @@ class Cache:
if not self.has_cache:
return
+ if self.cacheclean:
+ bb.msg.note(1, bb.msg.domain.Cache, "Cache is clean, not saving.")
+ return
+
version_data = {}
version_data['CACHE_VER'] = __cache_version__
version_data['BITBAKE_VER'] = bb.__version__
@@ -264,7 +290,6 @@ class Cache:
packages_dynamic = (self.getVar('PACKAGES_DYNAMIC', file_name, True) or "").split()
rprovides = (self.getVar("RPROVIDES", file_name, True) or "").split()
- cacheData.task_queues[file_name] = self.getVar("_task_graph", file_name, True)
cacheData.task_deps[file_name] = self.getVar("_task_deps", file_name, True)
# build PackageName to FileName lookup table
@@ -328,14 +353,16 @@ class Cache:
if not file_name in cacheData.runrecs:
cacheData.runrecs[file_name] = {}
+ rdepends = bb.utils.explode_deps(self.getVar('RDEPENDS', file_name, True) or "")
+ rrecommends = bb.utils.explode_deps(self.getVar('RRECOMMENDS', file_name, True) or "")
for package in packages + [pn]:
if not package in cacheData.rundeps[file_name]:
cacheData.rundeps[file_name][package] = {}
if not package in cacheData.runrecs[file_name]:
cacheData.runrecs[file_name][package] = {}
- add_dep(cacheData.rundeps[file_name][package], bb.utils.explode_deps(self.getVar('RDEPENDS', file_name, True) or ""))
- add_dep(cacheData.runrecs[file_name][package], bb.utils.explode_deps(self.getVar('RRECOMMENDS', file_name, True) or ""))
+ add_dep(cacheData.rundeps[file_name][package], rdepends)
+ add_dep(cacheData.runrecs[file_name][package], rrecommends)
add_dep(cacheData.rundeps[file_name][package], bb.utils.explode_deps(self.getVar("RDEPENDS_%s" % package, file_name, True) or ""))
add_dep(cacheData.runrecs[file_name][package], bb.utils.explode_deps(self.getVar("RRECOMMENDS_%s" % package, file_name, True) or ""))
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 2c091b6522..38a8209760 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -97,14 +97,12 @@ class BBCooker:
bb.msg.note(2, bb.msg.domain.Build, "Renice to %s " % os.nice(nice))
- def tryBuildPackage(self, fn, item, task, the_data, build_depends):
+ def tryBuildPackage(self, fn, item, task, the_data):
"""
Build one task of a package, optionally build following task depends
"""
bb.event.fire(bb.event.PkgStarted(item, the_data))
try:
- if not build_depends:
- bb.data.setVarFlag('do_%s' % task, 'dontrundeps', 1, the_data)
if not self.configuration.dry_run:
bb.build.exec_task('do_%s' % task, the_data)
bb.event.fire(bb.event.PkgSucceeded(item, the_data))
@@ -119,21 +117,20 @@ class BBCooker:
bb.event.fire(bb.event.PkgFailed(item, the_data))
raise
- def tryBuild( self, fn, build_depends):
+ def tryBuild(self, fn):
"""
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
"""
-
the_data = self.bb_cache.loadDataFull(fn, self.configuration.data)
item = self.status.pkg_fn[fn]
- if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data):
- return True
+ #if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data):
+ # return True
- return self.tryBuildPackage(fn, item, self.configuration.cmd, the_data, build_depends)
+ return self.tryBuildPackage(fn, item, self.configuration.cmd, the_data)
def showVersions(self):
pkg_pn = self.status.pkg_pn
@@ -184,6 +181,8 @@ class BBCooker:
self.cb = None
self.bb_cache = bb.cache.init(self)
fn = self.matchFile(buildfile)
+ if not fn:
+ sys.exit(1)
elif len(pkgs_to_build) == 1:
self.updateCache()
@@ -220,7 +219,7 @@ class BBCooker:
except Exception, e:
bb.msg.fatal(bb.msg.domain.Parsing, "%s" % e)
# emit the metadata which isnt valid shell
- data.expandKeys( envdata )
+ data.expandKeys( envdata )
for e in envdata.keys():
if data.getVarFlag( e, 'python', envdata ):
sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, envdata, 1)))
@@ -273,7 +272,7 @@ class BBCooker:
if fnid not in seen_fnids:
seen_fnids.append(fnid)
packages = []
- print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn)
+ print >> depends_file, '"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn)
for depend in self.status.deps[fn]:
print >> depends_file, '"%s" -> "%s"' % (pn, depend)
rdepends = self.status.rundeps[fn]
@@ -387,19 +386,15 @@ class BBCooker:
try:
self.configuration.data = bb.parse.handle( afile, self.configuration.data )
- # Add the handlers we inherited by INHERIT
- # we need to do this manually as it is not guranteed
- # we will pick up these classes... as we only INHERIT
- # on .inc and .bb files but not on .conf
- data = bb.data.createCopy( self.configuration.data )
- inherits = ["base"] + (bb.data.getVar('INHERIT', data, True ) or "").split()
+ # Handle any INHERITs and inherit the base class
+ inherits = ["base"] + (bb.data.getVar('INHERIT', self.configuration.data, True ) or "").split()
for inherit in inherits:
- data = bb.parse.handle( os.path.join('classes', '%s.bbclass' % inherit ), data, True )
+ self.configuration.data = bb.parse.handle(os.path.join('classes', '%s.bbclass' % inherit), self.configuration.data, True )
- # FIXME: This assumes that we included at least one .inc file
- for var in bb.data.keys(data):
- if bb.data.getVarFlag(var, 'handler', data):
- bb.event.register(var,bb.data.getVar(var, data))
+ # 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))
bb.fetch.fetcher_init(self.configuration.data)
@@ -463,30 +458,62 @@ class BBCooker:
bb.msg.error(bb.msg.domain.Parsing, "Unable to match %s (%s matches found):" % (buildfile, len(matches)))
for f in matches:
bb.msg.error(bb.msg.domain.Parsing, " %s" % f)
- sys.exit(1)
- return matches[0]
+ return False
+ return matches[0]
def buildFile(self, buildfile):
"""
Build the file matching regexp buildfile
"""
- bf = self.matchFile(buildfile)
+ # Make sure our target is a fully qualified filename
+ fn = self.matchFile(buildfile)
+ if not fn:
+ return False
- bbfile_data = bb.parse.handle(bf, self.configuration.data)
+ # Load data into the cache for fn
+ self.bb_cache = bb.cache.init(self)
+ self.bb_cache.loadData(fn, self.configuration.data)
+
+ # Parse the loaded cache data
+ self.status = bb.cache.CacheData()
+ self.bb_cache.handle_data(fn, self.status)
+
+ # Tweak some variables
+ item = self.bb_cache.getVar('PN', fn, True)
+ self.status.ignored_dependencies = Set()
+ self.status.bbfile_priority[fn] = 1
+
+ # Remove external dependencies
+ self.status.task_deps[fn]['depends'] = {}
+ self.status.deps[fn] = []
+ self.status.rundeps[fn] = []
+ self.status.runrecs[fn] = []
# Remove stamp for target if force mode active
if self.configuration.force:
- bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, bf))
+ bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, fn))
bb.build.del_stamp('do_%s' % self.configuration.cmd, bbfile_data)
- item = bb.data.getVar('PN', bbfile_data, 1)
- try:
- self.tryBuildPackage(bf, item, self.configuration.cmd, bbfile_data, True)
- except bb.build.EventException:
- bb.msg.error(bb.msg.domain.Build, "Build of '%s' failed" % item )
+ # Setup taskdata structure
+ taskdata = bb.taskdata.TaskData(self.configuration.abort)
+ taskdata.add_provider(self.configuration.data, self.status, item)
- sys.exit(0)
+ buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
+ bb.event.fire(bb.event.BuildStarted(buildname, [item], self.configuration.event_data))
+
+ # Execute the runqueue
+ runlist = [[item, "do_%s" % self.configuration.cmd]]
+ rq = bb.runqueue.RunQueue(self, self.configuration.data, self.status, taskdata, runlist)
+ rq.prepare_runqueue()
+ try:
+ failures = rq.execute_runqueue()
+ except runqueue.TaskFailure, fnids:
+ for fnid in fnids:
+ bb.msg.error(bb.msg.domain.Build, "'%s' failed" % taskdata.fn_index[fnid])
+ return False
+ bb.event.fire(bb.event.BuildCompleted(buildname, [item], self.configuration.event_data, failures))
+ return True
def buildTargets(self, targets):
"""
@@ -568,7 +595,9 @@ class BBCooker:
self.interactiveMode()
if self.configuration.buildfile is not None:
- return self.buildFile(self.configuration.buildfile)
+ if not self.buildFile(self.configuration.buildfile):
+ sys.exit(1)
+ sys.exit(0)
# initialise the parsing status now we know we will need deps
self.updateCache()
@@ -676,7 +705,7 @@ class BBCooker:
for i in xrange( len( filelist ) ):
f = filelist[i]
- bb.msg.debug(1, bb.msg.domain.Collection, "parsing %s" % f)
+ #bb.msg.debug(1, bb.msg.domain.Collection, "parsing %s" % f)
# read a file's metadata
try:
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py
index e879343f5d..b3a51b0edf 100644
--- a/bitbake/lib/bb/data_smart.py
+++ b/bitbake/lib/bb/data_smart.py
@@ -232,10 +232,10 @@ class DataSmart:
flags = {}
if local_var:
- for i in self.dict[var].keys():
+ for i in local_var.keys():
if i == "content":
continue
- flags[i] = self.dict[var][i]
+ flags[i] = local_var[i]
if len(flags) == 0:
return None
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
index 7148a2b7d6..c0a59e6120 100644
--- a/bitbake/lib/bb/event.py
+++ b/bitbake/lib/bb/event.py
@@ -127,6 +127,23 @@ def getName(e):
class ConfigParsed(Event):
"""Configuration Parsing Complete"""
+class StampUpdate(Event):
+ """Trigger for any adjustment of the stamp files to happen"""
+
+ def __init__(self, targets, stampfns, d):
+ self._targets = targets
+ self._stampfns = stampfns
+ Event.__init__(self, d)
+
+ def getStampPrefix(self):
+ return self._stampfns
+
+ def getTargets(self):
+ return self._targets
+
+ stampPrefix = property(getStampPrefix)
+ targets = property(getTargets)
+
class PkgBase(Event):
"""Base class for package events"""
diff --git a/bitbake/lib/bb/fetch/__init__.py b/bitbake/lib/bb/fetch/__init__.py
index 700efcb4ac..4919b9d473 100644
--- a/bitbake/lib/bb/fetch/__init__.py
+++ b/bitbake/lib/bb/fetch/__init__.py
@@ -139,13 +139,21 @@ def go(d):
if not m.forcefetch(u, ud, d) and os.path.exists(ud.md5):
# File already present along with md5 stamp file
# Touch md5 file to show activity
- os.utime(ud.md5, None)
+ try:
+ os.utime(ud.md5, None)
+ except:
+ # Errors aren't fatal here
+ pass
continue
lf = bb.utils.lockfile(ud.lockfile)
if not m.forcefetch(u, ud, d) and os.path.exists(ud.md5):
# If someone else fetched this before we got the lock,
# notice and don't try again
- os.utime(ud.md5, None)
+ try:
+ os.utime(ud.md5, None)
+ except:
+ # Errors aren't fatal here
+ pass
bb.utils.unlockfile(lf)
continue
m.go(u, ud, d)
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index 2a30e5895a..d7bf6d4f37 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -95,6 +95,10 @@ def handle(fn, d, include = 0):
if ext == ".bbclass":
__classname__ = root
classes.append(__classname__)
+ __inherit_cache = data.getVar('__inherit_cache', d) or []
+ if not fn in __inherit_cache:
+ __inherit_cache.append(fn)
+ data.setVar('__inherit_cache', __inherit_cache, d)
if include != 0:
oldfile = data.getVar('FILE', d)
@@ -126,10 +130,6 @@ def handle(fn, d, include = 0):
if ext != ".bbclass":
data.setVar('FILE', fn, d)
- i = (data.getVar("INHERIT", d, 1) or "").split()
- if not "base" in i and __classname__ != "base":
- i[0:0] = ["base"]
- inherit(i, d)
lineno = 0
while 1:
@@ -171,33 +171,12 @@ def handle(fn, d, include = 0):
all_handlers = {}
for var in data.getVar('__BBHANDLERS', d) or []:
# try to add the handler
- # if we added it remember the choiche
handler = data.getVar(var,d)
- if bb.event.register(var,handler) == bb.event.Registered:
- all_handlers[var] = handler
-
- tasklist = {}
- for var in data.getVar('__BBTASKS', d) or []:
- if var not in tasklist:
- tasklist[var] = []
- deps = data.getVarFlag(var, 'deps', d) or []
- for p in deps:
- if p not in tasklist[var]:
- tasklist[var].append(p)
-
- postdeps = data.getVarFlag(var, 'postdeps', d) or []
- for p in postdeps:
- if p not in tasklist:
- tasklist[p] = []
- if var not in tasklist[p]:
- tasklist[p].append(var)
+ bb.event.register(var, handler)
+ tasklist = data.getVar('__BBTASKS', d) or []
bb.build.add_tasks(tasklist, d)
- # now add the handlers
- if not len(all_handlers) == 0:
- data.setVar('__all_handlers__', all_handlers, d)
-
bbpath.pop(0)
if oldfile:
bb.data.setVar("FILE", oldfile, d)
@@ -342,15 +321,23 @@ def feeder(lineno, s, fn, root, d):
data.setVarFlag(var, "task", 1, d)
bbtasks = data.getVar('__BBTASKS', d) or []
- bbtasks.append(var)
+ if not var in bbtasks:
+ bbtasks.append(var)
data.setVar('__BBTASKS', bbtasks, d)
+ existing = data.getVarFlag(var, "deps", d) or []
if after is not None:
-# set up deps for function
- data.setVarFlag(var, "deps", after.split(), d)
+ # set up deps for function
+ for entry in after.split():
+ if entry not in existing:
+ existing.append(entry)
+ data.setVarFlag(var, "deps", existing, d)
if before is not None:
-# set up things that depend on this func
- data.setVarFlag(var, "postdeps", before.split(), d)
+ # set up things that depend on this func
+ for entry in before.split():
+ existing = data.getVarFlag(entry, "deps", d) or []
+ if var not in existing:
+ data.setVarFlag(entry, "deps", [var] + existing, d)
return
m = __addhandler_regexp__.match(s)
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 9d72d92fac..2765343a3e 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -26,6 +26,7 @@ from bb import msg, data, event, mkdirhier, utils
from sets import Set
import bb, os, sys
import signal
+import stat
class TaskFailure(Exception):
"""Exception raised when a task in a runqueue fails"""
@@ -45,11 +46,11 @@ class RunQueueStats:
def taskFailed(self):
self.failed = self.failed + 1
- def taskCompleted(self):
- self.completed = self.completed + 1
+ def taskCompleted(self, number = 1):
+ self.completed = self.completed + number
- def taskSkipped(self):
- self.skipped = self.skipped + 1
+ def taskSkipped(self, number = 1):
+ self.skipped = self.skipped + number
class RunQueueScheduler:
"""
@@ -144,8 +145,11 @@ class RunQueue:
self.taskData = taskData
self.targets = targets
- self.number_tasks = int(bb.data.getVar("BB_NUMBER_THREADS", cfgData) or 1)
- self.multi_provider_whitelist = (bb.data.getVar("MULTI_PROVIDER_WHITELIST", cfgData) or "").split()
+ self.cfgdata = cfgData
+ self.number_tasks = int(bb.data.getVar("BB_NUMBER_THREADS", cfgData, 1) or 1)
+ self.multi_provider_whitelist = (bb.data.getVar("MULTI_PROVIDER_WHITELIST", cfgData, 1) or "").split()
+ self.scheduler = bb.data.getVar("BB_SCHEDULER", cfgData, 1) or "speed"
+ self.stamppolicy = bb.data.getVar("BB_STAMP_POLICY", cfgData, 1) or "perfile"
def reset_runqueue(self):
@@ -512,6 +516,7 @@ class RunQueue:
for depend in depends:
mark_active(depend, depth+1)
+ self.target_pairs = []
for target in self.targets:
targetid = taskData.getbuild_id(target[0])
@@ -522,10 +527,11 @@ class RunQueue:
continue
fnid = taskData.build_targets[targetid][0]
+ fn = taskData.fn_index[fnid]
+ self.target_pairs.append((fn, target[1]))
# Remove stamps for targets if force mode active
if self.cooker.configuration.force:
- fn = taskData.fn_index[fnid]
bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (target[1], fn))
bb.build.del_stamp(target[1], self.dataCache, fn)
@@ -608,10 +614,11 @@ class RunQueue:
self.runq_weight = self.calculate_task_weights(endpoints)
# Decide what order to execute the tasks in, pick a scheduler
- # FIXME - Allow user selection
#self.sched = RunQueueScheduler(self)
- self.sched = RunQueueSchedulerSpeed(self)
- #self.sched = RunQueueSchedulerCompletion(self)
+ if self.scheduler == "completion":
+ self.sched = RunQueueSchedulerCompletion(self)
+ else:
+ self.sched = RunQueueSchedulerSpeed(self)
# Sanity Check - Check for multiple tasks building the same provider
prov_list = {}
@@ -636,6 +643,93 @@ class RunQueue:
#self.dump_data(taskData)
+ def check_stamps(self):
+ unchecked = {}
+ current = []
+ notcurrent = []
+ buildable = []
+
+ if self.stamppolicy == "perfile":
+ fulldeptree = False
+ else:
+ fulldeptree = True
+
+ for task in range(len(self.runq_fnid)):
+ unchecked[task] = ""
+ if len(self.runq_depends[task]) == 0:
+ buildable.append(task)
+
+ for task in range(len(self.runq_fnid)):
+ if task not in unchecked:
+ continue
+ fn = self.taskData.fn_index[self.runq_fnid[task]]
+ taskname = self.runq_task[task]
+ stampfile = "%s.%s" % (self.dataCache.stamp[fn], taskname)
+ # If the stamp is missing its not current
+ if not os.access(stampfile, os.F_OK):
+ del unchecked[task]
+ notcurrent.append(task)
+ continue
+ # If its a 'nostamp' task, it's not current
+ taskdep = self.dataCache.task_deps[fn]
+ if 'nostamp' in taskdep and task in taskdep['nostamp']:
+ del unchecked[task]
+ notcurrent.append(task)
+ continue
+
+ while (len(buildable) > 0):
+ nextbuildable = []
+ for task in buildable:
+ if task in unchecked:
+ fn = self.taskData.fn_index[self.runq_fnid[task]]
+ taskname = self.runq_task[task]
+ stampfile = "%s.%s" % (self.dataCache.stamp[fn], taskname)
+ iscurrent = True
+
+ t1 = os.stat(stampfile)[stat.ST_MTIME]
+ for dep in self.runq_depends[task]:
+ if iscurrent:
+ fn2 = self.taskData.fn_index[self.runq_fnid[dep]]
+ taskname2 = self.runq_task[dep]
+ stampfile2 = "%s.%s" % (self.dataCache.stamp[fn2], taskname2)
+ if fulldeptree or fn == fn2:
+ if dep in notcurrent:
+ iscurrent = False
+ else:
+ t2 = os.stat(stampfile2)[stat.ST_MTIME]
+ if t1 < t2:
+ iscurrent = False
+ del unchecked[task]
+ if iscurrent:
+ current.append(task)
+ else:
+ notcurrent.append(task)
+
+ for revdep in self.runq_revdeps[task]:
+ alldeps = 1
+ for dep in self.runq_depends[revdep]:
+ if dep in unchecked:
+ alldeps = 0
+ if alldeps == 1:
+ if revdep in unchecked:
+ nextbuildable.append(revdep)
+
+ buildable = nextbuildable
+
+ #for task in range(len(self.runq_fnid)):
+ # fn = self.taskData.fn_index[self.runq_fnid[task]]
+ # taskname = self.runq_task[task]
+ # print "%s %s.%s" % (task, taskname, fn)
+
+ #print "Unchecked: %s" % unchecked
+ #print "Current: %s" % current
+ #print "Not current: %s" % notcurrent
+
+ if len(unchecked) > 0:
+ bb.fatal("check_stamps fatal internal error")
+ return current
+
+
def execute_runqueue(self):
"""
Run the tasks in a queue prepared by prepare_runqueue
@@ -721,18 +815,13 @@ class RunQueue:
def sigint_handler(signum, frame):
raise KeyboardInterrupt
- # RP - this code allows tasks to run out of the correct order - disabled, FIXME
- # Find any tasks with current stamps and remove them from the queue
- #for task1 in range(len(self.runq_fnid)):
- # task = self.prio_map[task1]
- # fn = self.taskData.fn_index[self.runq_fnid[task]]
- # taskname = self.runq_task[task]
- # if bb.build.stamp_is_current(taskname, self.dataCache, fn):
- # bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task)))
- # self.runq_running[task] = 1
- # self.task_complete(task)
- # self.stats.taskCompleted()
- # self.stats.taskSkipped()
+ event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgdata))
+
+ # Find out which tasks have current stamps which we can skip when the
+ # time comes
+ currentstamps = self.check_stamps()
+ self.stats.taskSkipped(len(currentstamps))
+ self.stats.taskCompleted(len(currentstamps))
while True:
task = self.sched.next()
@@ -740,12 +829,13 @@ class RunQueue:
fn = self.taskData.fn_index[self.runq_fnid[task]]
taskname = self.runq_task[task]
- if bb.build.stamp_is_current(taskname, self.dataCache, fn):
+ if task in currentstamps:
+ #if bb.build.stamp_is_current(taskname, self.dataCache, fn):
bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task)))
self.runq_running[task] = 1
self.task_complete(task)
- self.stats.taskCompleted()
- self.stats.taskSkipped()
+ #self.stats.taskCompleted()
+ #self.stats.taskSkipped()
continue
bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task)))
@@ -764,7 +854,7 @@ class RunQueue:
os.dup2(newsi, sys.stdin.fileno())
self.cooker.configuration.cmd = taskname[3:]
try:
- self.cooker.tryBuild(fn, False)
+ self.cooker.tryBuild(fn)
except bb.build.EventException:
bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
sys.exit(1)
diff --git a/bitbake/lib/bb/shell.py b/bitbake/lib/bb/shell.py
index 745091fb7d..feba3f2b44 100644
--- a/bitbake/lib/bb/shell.py
+++ b/bitbake/lib/bb/shell.py
@@ -243,27 +243,13 @@ class BitBakeShellCommands:
oldcmd = cooker.configuration.cmd
cooker.configuration.cmd = cmd
- thisdata = data.createCopy(cooker.configuration.data)
- data.update_data(thisdata)
- data.expandKeys(thisdata)
-
try:
- bbfile_data = parse.handle( bf, thisdata )
+ cooker.buildFile(bf)
except parse.ParseError:
print "ERROR: Unable to open or parse '%s'" % bf
- else:
- # Remove stamp for target if force mode active
- if cooker.configuration.force:
- bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (cmd, bf))
- bb.build.del_stamp('do_%s' % cmd, bbfile_data)
-
- item = data.getVar('PN', bbfile_data, 1)
- data.setVar( "_task_cache", [], bbfile_data ) # force
- try:
- cooker.tryBuildPackage( os.path.abspath( bf ), item, cmd, bbfile_data, True )
- except build.EventException, e:
- print "ERROR: Couldn't build '%s'" % name
- last_exception = e
+ except build.EventException, e:
+ print "ERROR: Couldn't build '%s'" % name
+ last_exception = e
cooker.configuration.cmd = oldcmd
fileBuild.usage = "<bbfile>"
@@ -586,6 +572,7 @@ SRC_URI = ""
def completeFilePath( bbfile ):
"""Get the complete bbfile path"""
+ if not cooker.status: return bbfile
if not cooker.status.pkg_fn: return bbfile
for key in cooker.status.pkg_fn.keys():
if key.endswith( bbfile ):
diff --git a/bitbake/lib/bb/taskdata.py b/bitbake/lib/bb/taskdata.py
index 3dac6c26af..4a79e7a56d 100644
--- a/bitbake/lib/bb/taskdata.py
+++ b/bitbake/lib/bb/taskdata.py
@@ -124,7 +124,6 @@ class TaskData:
Add tasks for a given fn to the database
"""
- task_graph = dataCache.task_queues[fn]
task_deps = dataCache.task_deps[fn]
fnid = self.getfn_id(fn)
@@ -136,11 +135,11 @@ class TaskData:
if fnid in self.tasks_fnid:
return
- for task in task_graph.allnodes():
+ for task in task_deps['tasks']:
# Work out task dependencies
parentids = []
- for dep in task_graph.getparents(task):
+ for dep in task_deps['parents'][task]:
parentid = self.gettask_id(fn, dep)
parentids.append(parentid)
taskid = self.gettask_id(fn, task)
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py
index a2a5ff6cfd..9702c8c204 100644
--- a/bitbake/lib/bb/utils.py
+++ b/bitbake/lib/bb/utils.py
@@ -85,11 +85,11 @@ def explode_deps(s):
for i in l:
if i[0] == '(':
flag = True
- j = []
- if flag:
- j.append(i)
- else:
+ #j = []
+ if not flag:
r.append(i)
+ #else:
+ # j.append(i)
if flag and i.endswith(')'):
flag = False
# Ignore version