|
@@ -317,6 +317,7 @@ class RunQueue:
|
|
|
|
|
|
depends = []
|
|
|
runq_build = []
|
|
|
+ recursive_tdepends = {}
|
|
|
|
|
|
taskData = self.taskData
|
|
|
|
|
@@ -382,14 +383,45 @@ class RunQueue:
|
|
|
# e.g. do_sometask[depends] = "targetname:do_someothertask"
|
|
|
# (makes sure sometask runs after targetname's someothertask)
|
|
|
idepends = taskData.tasks_idepends[task]
|
|
|
- for idepend in idepends:
|
|
|
- depid = int(idepend.split(":")[0])
|
|
|
+ for (depid, idependtask) in idepends:
|
|
|
if depid in taskData.build_targets:
|
|
|
# Won't be in build_targets if ASSUME_PROVIDED
|
|
|
depdata = taskData.build_targets[depid][0]
|
|
|
if depdata is not None:
|
|
|
dep = taskData.fn_index[depdata]
|
|
|
- depends.append(taskData.gettask_id(dep, idepend.split(":")[1]))
|
|
|
+ depends.append(taskData.gettask_id(dep, idependtask))
|
|
|
+
|
|
|
+ # Create a list of recursive dependent tasks (from tdepends) and cache
|
|
|
+ def get_recursive_tdepends(task):
|
|
|
+ if not task:
|
|
|
+ return []
|
|
|
+ if task in recursive_tdepends:
|
|
|
+ return recursive_tdepends[task]
|
|
|
+ rectdepends = [task]
|
|
|
+ nextdeps = [task]
|
|
|
+ while len(nextdeps) != 0:
|
|
|
+ newdeps = []
|
|
|
+ for nextdep in nextdeps:
|
|
|
+ for tdepend in taskData.tasks_tdepends[nextdep]:
|
|
|
+ if tdepend not in rectdepends:
|
|
|
+ rectdepends.append(tdepend)
|
|
|
+ newdeps.append(tdepend)
|
|
|
+ nextdeps = newdeps
|
|
|
+ recursive_tdepends[task] = rectdepends
|
|
|
+ return rectdepends
|
|
|
+
|
|
|
+ # Using the list of tdepends for this task create a list of
|
|
|
+ # the recursive idepends we have
|
|
|
+ def get_recursive_idepends(task):
|
|
|
+ if not task:
|
|
|
+ return []
|
|
|
+ rectdepends = get_recursive_tdepends(task)
|
|
|
+
|
|
|
+ recidepends = []
|
|
|
+ for tdepend in rectdepends:
|
|
|
+ for idepend in taskData.tasks_idepends[tdepend]:
|
|
|
+ recidepends.append(idepend)
|
|
|
+ return recidepends
|
|
|
|
|
|
def add_recursive_build(depid, depfnid):
|
|
|
"""
|
|
@@ -404,13 +436,11 @@ class RunQueue:
|
|
|
depdata = taskData.build_targets[depid][0]
|
|
|
if depdata is not None:
|
|
|
dep = taskData.fn_index[depdata]
|
|
|
- idepends = []
|
|
|
# Need to avoid creating new tasks here
|
|
|
taskid = taskData.gettask_id(dep, taskname, False)
|
|
|
if taskid is not None:
|
|
|
depends.append(taskid)
|
|
|
fnid = taskData.tasks_fnid[taskid]
|
|
|
- idepends = taskData.tasks_idepends[taskid]
|
|
|
#print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
|
|
|
else:
|
|
|
fnid = taskData.getfn_id(dep)
|
|
@@ -420,10 +450,9 @@ class RunQueue:
|
|
|
for nextdepid in taskData.rdepids[fnid]:
|
|
|
if nextdepid not in rdep_seen:
|
|
|
add_recursive_run(nextdepid, fnid)
|
|
|
- for idepend in idepends:
|
|
|
- nextdepid = int(idepend.split(":")[0])
|
|
|
- if nextdepid not in dep_seen:
|
|
|
- add_recursive_build(nextdepid, fnid)
|
|
|
+ for (idependid, idependtask) in get_recursive_idepends(taskid):
|
|
|
+ if idependid not in dep_seen:
|
|
|
+ add_recursive_build(idependid, fnid)
|
|
|
|
|
|
def add_recursive_run(rdepid, depfnid):
|
|
|
"""
|
|
@@ -438,13 +467,11 @@ class RunQueue:
|
|
|
depdata = taskData.run_targets[rdepid][0]
|
|
|
if depdata is not None:
|
|
|
dep = taskData.fn_index[depdata]
|
|
|
- idepends = []
|
|
|
# Need to avoid creating new tasks here
|
|
|
taskid = taskData.gettask_id(dep, taskname, False)
|
|
|
if taskid is not None:
|
|
|
depends.append(taskid)
|
|
|
fnid = taskData.tasks_fnid[taskid]
|
|
|
- idepends = taskData.tasks_idepends[taskid]
|
|
|
#print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
|
|
|
else:
|
|
|
fnid = taskData.getfn_id(dep)
|
|
@@ -454,10 +481,9 @@ class RunQueue:
|
|
|
for nextdepid in taskData.rdepids[fnid]:
|
|
|
if nextdepid not in rdep_seen:
|
|
|
add_recursive_run(nextdepid, fnid)
|
|
|
- for idepend in idepends:
|
|
|
- nextdepid = int(idepend.split(":")[0])
|
|
|
- if nextdepid not in dep_seen:
|
|
|
- add_recursive_build(nextdepid, fnid)
|
|
|
+ for (idependid, idependtask) in get_recursive_idepends(taskid):
|
|
|
+ if idependid not in dep_seen:
|
|
|
+ add_recursive_build(idependid, fnid)
|
|
|
|
|
|
# Resolve recursive 'recrdeptask' dependencies
|
|
|
#
|
|
@@ -472,9 +498,9 @@ class RunQueue:
|
|
|
add_recursive_build(depid, fnid)
|
|
|
for rdepid in taskData.rdepids[fnid]:
|
|
|
add_recursive_run(rdepid, fnid)
|
|
|
- for idepend in idepends:
|
|
|
- depid = int(idepend.split(":")[0])
|
|
|
- add_recursive_build(depid, fnid)
|
|
|
+ deptaskid = taskData.gettask_id(fn, taskname, False)
|
|
|
+ for (idependid, idependtask) in get_recursive_idepends(deptaskid):
|
|
|
+ add_recursive_build(idependid, fnid)
|
|
|
|
|
|
# Rmove all self references
|
|
|
if task in depends:
|
|
@@ -659,6 +685,16 @@ class RunQueue:
|
|
|
if len(self.runq_depends[task]) == 0:
|
|
|
buildable.append(task)
|
|
|
|
|
|
+ def check_buildable(self, task, buildable):
|
|
|
+ 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:
|
|
|
+ buildable.append(revdep)
|
|
|
+
|
|
|
for task in range(len(self.runq_fnid)):
|
|
|
if task not in unchecked:
|
|
|
continue
|
|
@@ -669,12 +705,14 @@ class RunQueue:
|
|
|
if not os.access(stampfile, os.F_OK):
|
|
|
del unchecked[task]
|
|
|
notcurrent.append(task)
|
|
|
+ check_buildable(self, task, buildable)
|
|
|
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)
|
|
|
+ check_buildable(self, task, buildable)
|
|
|
continue
|
|
|
|
|
|
while (len(buildable) > 0):
|
|
@@ -705,14 +743,7 @@ class RunQueue:
|
|
|
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)
|
|
|
+ check_buildable(self, task, nextbuildable)
|
|
|
|
|
|
buildable = nextbuildable
|
|
|
|
|
@@ -729,6 +760,40 @@ class RunQueue:
|
|
|
bb.fatal("check_stamps fatal internal error")
|
|
|
return current
|
|
|
|
|
|
+ def check_stamp(self, task):
|
|
|
+
|
|
|
+ if self.stamppolicy == "perfile":
|
|
|
+ fulldeptree = False
|
|
|
+ else:
|
|
|
+ fulldeptree = True
|
|
|
+
|
|
|
+ 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):
|
|
|
+ return False
|
|
|
+ # If its a 'nostamp' task, it's not current
|
|
|
+ taskdep = self.dataCache.task_deps[fn]
|
|
|
+ if 'nostamp' in taskdep and task in taskdep['nostamp']:
|
|
|
+ return False
|
|
|
+
|
|
|
+ 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:
|
|
|
+ try:
|
|
|
+ t2 = os.stat(stampfile2)[stat.ST_MTIME]
|
|
|
+ if t1 < t2:
|
|
|
+ iscurrent = False
|
|
|
+ except:
|
|
|
+ iscurrent = False
|
|
|
+
|
|
|
+ return iscurrent
|
|
|
|
|
|
def execute_runqueue(self):
|
|
|
"""
|
|
@@ -817,25 +882,18 @@ class RunQueue:
|
|
|
|
|
|
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()
|
|
|
if task is not None:
|
|
|
fn = self.taskData.fn_index[self.runq_fnid[task]]
|
|
|
|
|
|
taskname = self.runq_task[task]
|
|
|
- if task in currentstamps:
|
|
|
- #if bb.build.stamp_is_current(taskname, self.dataCache, fn):
|
|
|
+ if self.check_stamp(task):
|
|
|
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)))
|