diff options
| -rw-r--r-- | bitbake/lib/bb/runqueue.py | 134 |
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 | ||
| 77 | def tid_replacetask(tid, taskname): | ||
| 78 | return tid.rsplit(":", 1)[0] + ":" + taskname | ||
| 79 | |||
| 80 | class RunQueueStats: | 77 | class 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 | ||
