summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/lib/bb/runqueue.py134
1 files changed, 83 insertions, 51 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index bbfe9eeee0..d7acfabef4 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -74,9 +74,6 @@ def build_tid(mc, fn, taskname):
74 return "multiconfig:" + mc + ":" + fn + ":" + taskname 74 return "multiconfig:" + mc + ":" + fn + ":" + taskname
75 return fn + ":" + taskname 75 return fn + ":" + taskname
76 76
77def tid_replacetask(tid, taskname):
78 return tid.rsplit(":", 1)[0] + ":" + taskname
79
80class RunQueueStats: 77class RunQueueStats:
81 """ 78 """
82 Holds statistics on the tasks handled by the associated runQueue 79 Holds statistics on the tasks handled by the associated runQueue
@@ -670,71 +667,106 @@ class RunQueueData:
670 recursiveitasks[tid].append(newdep) 667 recursiveitasks[tid].append(newdep)
671 668
672 self.runtaskentries[tid].depends = depends 669 self.runtaskentries[tid].depends = depends
670 # Remove all self references
671 self.runtaskentries[tid].depends.discard(tid)
673 672
674 #self.dump_data() 673 #self.dump_data()
675 674
675 self.init_progress_reporter.next_stage()
676
676 # Resolve recursive 'recrdeptask' dependencies (Part B) 677 # Resolve recursive 'recrdeptask' dependencies (Part B)
677 # 678 #
678 # e.g. do_sometask[recrdeptask] = "do_someothertask" 679 # e.g. do_sometask[recrdeptask] = "do_someothertask"
679 # (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively) 680 # (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
680 # We need to do this separately since we need all of runtaskentries[*].depends to be complete before this is processed 681 # We need to do this separately since we need all of runtaskentries[*].depends to be complete before this is processed
681 self.init_progress_reporter.next_stage() 682
682 extradeps = True 683 # Generating/interating recursive lists of dependencies is painful and potentially slow
684 # Precompute recursive task dependencies here by:
685 # a) create a temp list of reverse dependencies (revdeps)
686 # b) walk up the ends of the chains (when a given task no longer has dependencies i.e. len(deps) == 0)
687 # c) combine the total list of dependencies in cumulativedeps
688 # d) optimise by pre-truncating 'task' off the items in cumulativedeps (keeps items in sets lower)
689
690
691 revdeps = {}
692 deps = {}
693 cumulativedeps = {}
694 for tid in self.runtaskentries:
695 deps[tid] = set(self.runtaskentries[tid].depends)
696 revdeps[tid] = set()
697 cumulativedeps[tid] = set()
698 # Generate a temp list of reverse dependencies
699 for tid in self.runtaskentries:
700 for dep in self.runtaskentries[tid].depends:
701 revdeps[dep].add(tid)
702 # Find the dependency chain endpoints
703 endpoints = set()
704 for tid in self.runtaskentries:
705 if len(deps[tid]) == 0:
706 endpoints.add(tid)
707 # Iterate the chains collating dependencies
708 while endpoints:
709 next = set()
710 for tid in endpoints:
711 for dep in revdeps[tid]:
712 cumulativedeps[dep].add(fn_from_tid(tid))
713 cumulativedeps[dep].update(cumulativedeps[tid])
714 if tid in deps[dep]:
715 deps[dep].remove(tid)
716 if len(deps[dep]) == 0:
717 next.add(dep)
718 endpoints = next
719 #for tid in deps:
720 # if len(deps[tid]) != 0:
721 # bb.warn("Sanity test failure, dependencies left for %s (%s)" % (tid, deps[tid]))
722
683 # Loop here since recrdeptasks can depend upon other recrdeptasks and we have to 723 # Loop here since recrdeptasks can depend upon other recrdeptasks and we have to
684 # resolve these recursively until we aren't adding any further extra dependencies 724 # resolve these recursively until we aren't adding any further extra dependencies
725 extradeps = True
685 while extradeps: 726 while extradeps:
686 extradeps = {} 727 extradeps = 0
687 728 for tid in recursivetasks:
688 for taskcounter, tid in enumerate(recursivetasks):
689 extradeps[tid] = set()
690
691 tasknames = recursivetasks[tid] 729 tasknames = recursivetasks[tid]
692 seendeps = set()
693 seenbasedeps = set()
694
695 def generate_recdeps(t):
696 newdeps = set()
697 basetid = fn_from_tid(t)
698 if basetid not in seenbasedeps:
699 for taskname in tasknames:
700 newtid = tid_replacetask(t, taskname)
701 if newtid in self.runtaskentries and newtid not in seendeps:
702 newdeps.add(newtid)
703 extradeps[tid].add(newtid)
704 seenbasedeps.add(basetid)
705 seendeps.add(t)
706 newdeps.add(t)
707 for i in newdeps:
708 if i not in self.runtaskentries:
709 # Not all recipes might have the recrdeptask task as a task
710 continue
711 for n in self.runtaskentries[i].depends:
712 if n not in seendeps:
713 generate_recdeps(n)
714 generate_recdeps(tid)
715 730
731 totaldeps = set(self.runtaskentries[tid].depends)
716 if tid in recursiveitasks: 732 if tid in recursiveitasks:
733 totaldeps.update(recursiveitasks[tid])
717 for dep in recursiveitasks[tid]: 734 for dep in recursiveitasks[tid]:
718 generate_recdeps(dep) 735 if dep not in self.runtaskentries:
736 continue
737 totaldeps.update(self.runtaskentries[dep].depends)
719 738
720 for tid in self.runtaskentries: 739 deps = set()
721 # Add in extra dependencies 740 for dep in totaldeps:
722 if tid in extradeps: 741 if dep in cumulativedeps:
723 extradeps[tid].difference_update(self.runtaskentries[tid].depends) 742 deps.update(cumulativedeps[dep])
724 self.runtaskentries[tid].depends.update(extradeps[tid]) 743
725 # Remove circular references so that do_a[recrdeptask] = "do_a do_b" can work 744 for t in deps:
726 self.runtaskentries[tid].depends.difference_update(recursivetasksselfref) 745 for taskname in tasknames:
727 extradeps[tid].difference_update(recursivetasksselfref) 746 newtid = t + ":" + taskname
728 if not len(extradeps[tid]): 747 if newtid == tid:
729 del extradeps[tid] 748 continue
730 if tid not in recursivetasks: 749 if newtid in self.runtaskentries and newtid not in self.runtaskentries[tid].depends:
731 bb.warn(tid) 750 extradeps += 1
732 # Remove all self references 751 self.runtaskentries[tid].depends.add(newtid)
733 if tid in self.runtaskentries[tid].depends:
734 logger.debug(2, "Task %s contains self reference!", tid)
735 self.runtaskentries[tid].depends.remove(tid)
736 752
737 bb.debug(1, "Added %s recursive dependencies in this loop" % len(extradeps)) 753 # Handle recursive tasks which depend upon other recursive tasks
754 deps = set()
755 for dep in self.runtaskentries[tid].depends.intersection(recursivetasks):
756 deps.update(self.runtaskentries[dep].depends.difference(self.runtaskentries[tid].depends))
757 for newtid in deps:
758 for taskname in tasknames:
759 if not newtid.endswith(":" + taskname):
760 continue
761 if newtid in self.runtaskentries:
762 extradeps += 1
763 self.runtaskentries[tid].depends.add(newtid)
764
765 bb.debug(1, "Added %s recursive dependencies in this loop" % extradeps)
766
767 # Remove recrdeptask circular references so that do_a[recrdeptask] = "do_a do_b" can work
768 for tid in self.runtaskentries:
769 self.runtaskentries[tid].depends.difference_update(recursivetasksselfref)
738 770
739 self.init_progress_reporter.next_stage() 771 self.init_progress_reporter.next_stage()
740 772