summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Kanavin <alex.kanavin@gmail.com>2023-12-18 09:43:57 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-01-10 16:32:13 +0000
commit67e3f243339131741271c58abc987aef33f6b76c (patch)
tree3894cadca3e6ac6ec85a0584dbf2f95f21613bc8
parent98c5c96dd3902cdc4a455a9ed46591037ab3f676 (diff)
downloadpoky-67e3f243339131741271c58abc987aef33f6b76c.tar.gz
bitbake: bitbake/runqueue: rework 'bitbake -S printdiff' logic
Previously printdiff code would iterate over tasks that were reported as invalid or absent, trying to follow dependency chains that would reach the most basic invalid items in the tree. While this works in tightly controlled local builds, it can lead to bizarre reports against industrial-sized sstate caches, as the code would not consider whether the overall target can be fulfilled from valid sstate objects, and instead report missing sstate signature files that perhaps were never even created due to hash equivalency providing shortcuts in builds. This commit reworks the logic in two ways: - start the iteration over final targets rather than missing objects and try to recursively arrive at the root of the invalid object dependency. A previous version of this patch relied relies on finding the most 'recent' signature in stamps or sstate in a different function later, and recursively comparing that to the current signature, which is unreliable on real world caches. - if a given object can be fulfilled from sstate, recurse only into its setscene dependencies; bitbake wouldn't care if dependencies for the actual task are absent, and neither should printdiff I wrote a recursive function for following dependencies, as doing recursive algorithms non-recursively can result in write-only code, as was the case here. [YOCTO #15289] (Bitbake rev: aadeca63da5d96160ce4d6d71da556e2e033f9b7) Signed-off-by: Alexander Kanavin <alex@linutronix.de> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/runqueue.py41
1 files changed, 26 insertions, 15 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 5a45943e3a..9e3a87c0e8 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -1685,6 +1685,17 @@ class RunQueue:
1685 return 1685 return
1686 1686
1687 def print_diffscenetasks(self): 1687 def print_diffscenetasks(self):
1688 def get_root_invalid_tasks(task, taskdepends, valid, noexec, visited_invalid):
1689 invalidtasks = []
1690 for t in taskdepends[task].depends:
1691 if t not in valid and t not in visited_invalid:
1692 invalidtasks.extend(get_root_invalid_tasks(t, taskdepends, valid, noexec, visited_invalid))
1693 visited_invalid.add(t)
1694
1695 direct_invalid = [t for t in taskdepends[task].depends if t not in valid]
1696 if not direct_invalid and task not in noexec:
1697 invalidtasks = [task]
1698 return invalidtasks
1688 1699
1689 noexec = [] 1700 noexec = []
1690 tocheck = set() 1701 tocheck = set()
@@ -1718,35 +1729,35 @@ class RunQueue:
1718 valid_new.add(dep) 1729 valid_new.add(dep)
1719 1730
1720 invalidtasks = set() 1731 invalidtasks = set()
1721 for tid in self.rqdata.runtaskentries:
1722 if tid not in valid_new and tid not in noexec:
1723 invalidtasks.add(tid)
1724 1732
1725 found = set() 1733 toptasks = set(["{}:{}".format(t[3], t[2]) for t in self.rqdata.targets])
1726 processed = set() 1734 for tid in toptasks:
1727 for tid in invalidtasks:
1728 toprocess = set([tid]) 1735 toprocess = set([tid])
1729 while toprocess: 1736 while toprocess:
1730 next = set() 1737 next = set()
1738 visited_invalid = set()
1731 for t in toprocess: 1739 for t in toprocess:
1732 for dep in self.rqdata.runtaskentries[t].depends: 1740 if t not in valid_new and t not in noexec:
1733 if dep in invalidtasks: 1741 invalidtasks.update(get_root_invalid_tasks(t, self.rqdata.runtaskentries, valid_new, noexec, visited_invalid))
1734 found.add(tid) 1742 continue
1735 if dep not in processed: 1743 if t in self.rqdata.runq_setscene_tids:
1736 processed.add(dep) 1744 for dep in self.rqexe.sqdata.sq_deps[t]:
1737 next.add(dep) 1745 next.add(dep)
1746 continue
1747
1748 for dep in self.rqdata.runtaskentries[t].depends:
1749 next.add(dep)
1750
1738 toprocess = next 1751 toprocess = next
1739 if tid in found:
1740 toprocess = set()
1741 1752
1742 tasklist = [] 1753 tasklist = []
1743 for tid in invalidtasks.difference(found): 1754 for tid in invalidtasks:
1744 tasklist.append(tid) 1755 tasklist.append(tid)
1745 1756
1746 if tasklist: 1757 if tasklist:
1747 bb.plain("The differences between the current build and any cached tasks start at the following tasks:\n" + "\n".join(tasklist)) 1758 bb.plain("The differences between the current build and any cached tasks start at the following tasks:\n" + "\n".join(tasklist))
1748 1759
1749 return invalidtasks.difference(found) 1760 return invalidtasks
1750 1761
1751 def write_diffscenetasks(self, invalidtasks): 1762 def write_diffscenetasks(self, invalidtasks):
1752 bb.siggen.check_siggen_version(bb.siggen) 1763 bb.siggen.check_siggen_version(bb.siggen)