diff options
Diffstat (limited to 'bitbake')
-rw-r--r-- | bitbake/lib/bb/runqueue.py | 60 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass | 19 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf | 9 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf | 1 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf | 1 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/runqueue.py | 19 |
6 files changed, 98 insertions, 11 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py index 00c71070d2..fa848326d8 100644 --- a/bitbake/lib/bb/runqueue.py +++ b/bitbake/lib/bb/runqueue.py | |||
@@ -68,6 +68,14 @@ def build_tid(mc, fn, taskname): | |||
68 | return "mc:" + mc + ":" + fn + ":" + taskname | 68 | return "mc:" + mc + ":" + fn + ":" + taskname |
69 | return fn + ":" + taskname | 69 | return fn + ":" + taskname |
70 | 70 | ||
71 | # Index used to pair up potentially matching multiconfig tasks | ||
72 | # We match on PN, taskname and hash being equal | ||
73 | def pending_hash_index(tid, rqdata): | ||
74 | (mc, fn, taskname, taskfn) = split_tid_mcfn(tid) | ||
75 | pn = rqdata.dataCaches[mc].pkg_fn[taskfn] | ||
76 | h = rqdata.runtaskentries[tid].hash | ||
77 | return pn + ":" + "taskname" + h | ||
78 | |||
71 | class RunQueueStats: | 79 | class RunQueueStats: |
72 | """ | 80 | """ |
73 | Holds statistics on the tasks handled by the associated runQueue | 81 | Holds statistics on the tasks handled by the associated runQueue |
@@ -1717,6 +1725,7 @@ class RunQueueExecute: | |||
1717 | self.build_stamps = {} | 1725 | self.build_stamps = {} |
1718 | self.build_stamps2 = [] | 1726 | self.build_stamps2 = [] |
1719 | self.failed_tids = [] | 1727 | self.failed_tids = [] |
1728 | self.sq_deferred = {} | ||
1720 | 1729 | ||
1721 | self.stampcache = {} | 1730 | self.stampcache = {} |
1722 | 1731 | ||
@@ -1921,17 +1930,32 @@ class RunQueueExecute: | |||
1921 | # Find the next setscene to run | 1930 | # Find the next setscene to run |
1922 | for nexttask in self.rqdata.runq_setscene_tids: | 1931 | for nexttask in self.rqdata.runq_setscene_tids: |
1923 | if nexttask in self.sq_buildable and nexttask not in self.sq_running and self.sqdata.stamps[nexttask] not in self.build_stamps.values(): | 1932 | if nexttask in self.sq_buildable and nexttask not in self.sq_running and self.sqdata.stamps[nexttask] not in self.build_stamps.values(): |
1924 | if nexttask in self.sqdata.unskippable: | ||
1925 | logger.debug(2, "Setscene task %s is unskippable" % nexttask) | ||
1926 | if nexttask not in self.sqdata.unskippable and len(self.sqdata.sq_revdeps[nexttask]) > 0 and self.sqdata.sq_revdeps[nexttask].issubset(self.scenequeue_covered) and self.check_dependencies(nexttask, self.sqdata.sq_revdeps[nexttask]): | 1933 | if nexttask not in self.sqdata.unskippable and len(self.sqdata.sq_revdeps[nexttask]) > 0 and self.sqdata.sq_revdeps[nexttask].issubset(self.scenequeue_covered) and self.check_dependencies(nexttask, self.sqdata.sq_revdeps[nexttask]): |
1927 | if nexttask not in self.rqdata.target_tids: | 1934 | if nexttask not in self.rqdata.target_tids: |
1928 | logger.debug(2, "Skipping setscene for task %s" % nexttask) | 1935 | logger.debug(2, "Skipping setscene for task %s" % nexttask) |
1929 | self.sq_task_skip(nexttask) | 1936 | self.sq_task_skip(nexttask) |
1930 | self.scenequeue_notneeded.add(nexttask) | 1937 | self.scenequeue_notneeded.add(nexttask) |
1938 | if nexttask in self.sq_deferred: | ||
1939 | del self.sq_deferred[nexttask] | ||
1940 | return True | ||
1941 | if nexttask in self.sq_deferred: | ||
1942 | if self.sq_deferred[nexttask] not in self.runq_complete: | ||
1943 | continue | ||
1944 | logger.debug(1, "Task %s no longer deferred" % nexttask) | ||
1945 | del self.sq_deferred[nexttask] | ||
1946 | valid = self.rq.validate_hashes(set([nexttask]), self.cooker.data, None, False) | ||
1947 | if not valid: | ||
1948 | logger.debug(1, "%s didn't become valid, skipping setscene" % nexttask) | ||
1949 | self.sq_task_failoutright(nexttask) | ||
1931 | return True | 1950 | return True |
1951 | else: | ||
1952 | self.sqdata.outrightfail.remove(nexttask) | ||
1932 | if nexttask in self.sqdata.outrightfail: | 1953 | if nexttask in self.sqdata.outrightfail: |
1954 | logger.debug(2, 'No package found, so skipping setscene task %s', nexttask) | ||
1933 | self.sq_task_failoutright(nexttask) | 1955 | self.sq_task_failoutright(nexttask) |
1934 | return True | 1956 | return True |
1957 | if nexttask in self.sqdata.unskippable: | ||
1958 | logger.debug(2, "Setscene task %s is unskippable" % nexttask) | ||
1935 | task = nexttask | 1959 | task = nexttask |
1936 | break | 1960 | break |
1937 | if task is not None: | 1961 | if task is not None: |
@@ -1982,7 +2006,7 @@ class RunQueueExecute: | |||
1982 | if self.can_start_task(): | 2006 | if self.can_start_task(): |
1983 | return True | 2007 | return True |
1984 | 2008 | ||
1985 | if not self.sq_live and not self.sqdone: | 2009 | if not self.sq_live and not self.sqdone and not self.sq_deferred: |
1986 | logger.info("Setscene tasks completed") | 2010 | logger.info("Setscene tasks completed") |
1987 | logger.debug(1, 'We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered))) | 2011 | logger.debug(1, 'We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered))) |
1988 | 2012 | ||
@@ -2083,6 +2107,13 @@ class RunQueueExecute: | |||
2083 | self.rq.read_workers() | 2107 | self.rq.read_workers() |
2084 | return self.rq.active_fds() | 2108 | return self.rq.active_fds() |
2085 | 2109 | ||
2110 | # No more tasks can be run. If we have deferred setscene tasks we should run them. | ||
2111 | if self.sq_deferred: | ||
2112 | tid = self.sq_deferred.pop(list(self.sq_deferred.keys())[0]) | ||
2113 | logger.warning("Runqeueue deadlocked on deferred tasks, forcing task %s" % tid) | ||
2114 | self.sq_task_failoutright(tid) | ||
2115 | return True | ||
2116 | |||
2086 | if len(self.failed_tids) != 0: | 2117 | if len(self.failed_tids) != 0: |
2087 | self.rq.state = runQueueFailed | 2118 | self.rq.state = runQueueFailed |
2088 | return True | 2119 | return True |
@@ -2347,7 +2378,7 @@ class SQData(object): | |||
2347 | # Setscene tasks directly depended upon by the build | 2378 | # Setscene tasks directly depended upon by the build |
2348 | self.unskippable = set() | 2379 | self.unskippable = set() |
2349 | # List of setscene tasks which aren't present | 2380 | # List of setscene tasks which aren't present |
2350 | self.outrightfail = [] | 2381 | self.outrightfail = set() |
2351 | # A list of normal tasks a setscene task covers | 2382 | # A list of normal tasks a setscene task covers |
2352 | self.sq_covered_tasks = {} | 2383 | self.sq_covered_tasks = {} |
2353 | 2384 | ||
@@ -2510,7 +2541,9 @@ def build_scenequeue_data(sqdata, rqdata, rq, cooker, stampcache, sqrq): | |||
2510 | 2541 | ||
2511 | rqdata.init_progress_reporter.next_stage() | 2542 | rqdata.init_progress_reporter.next_stage() |
2512 | 2543 | ||
2544 | multiconfigs = set() | ||
2513 | for tid in sqdata.sq_revdeps: | 2545 | for tid in sqdata.sq_revdeps: |
2546 | multiconfigs.add(mc_from_tid(tid)) | ||
2514 | if len(sqdata.sq_revdeps[tid]) == 0: | 2547 | if len(sqdata.sq_revdeps[tid]) == 0: |
2515 | sqrq.sq_buildable.add(tid) | 2548 | sqrq.sq_buildable.add(tid) |
2516 | 2549 | ||
@@ -2552,10 +2585,21 @@ def build_scenequeue_data(sqdata, rqdata, rq, cooker, stampcache, sqrq): | |||
2552 | for v in valid: | 2585 | for v in valid: |
2553 | valid_new.append(v) | 2586 | valid_new.append(v) |
2554 | 2587 | ||
2555 | for tid in sqdata.sq_revdeps: | 2588 | hashes = {} |
2556 | if tid not in valid_new and tid not in noexec: | 2589 | for mc in sorted(multiconfigs): |
2557 | logger.debug(2, 'No package found, so skipping setscene task %s', tid) | 2590 | for tid in sqdata.sq_revdeps: |
2558 | sqdata.outrightfail.append(tid) | 2591 | if mc_from_tid(tid) != mc: |
2592 | continue | ||
2593 | if tid not in valid_new and tid not in noexec and tid not in sqrq.scenequeue_notcovered: | ||
2594 | sqdata.outrightfail.add(tid) | ||
2595 | |||
2596 | h = pending_hash_index(tid, rqdata) | ||
2597 | if h not in hashes: | ||
2598 | hashes[h] = tid | ||
2599 | else: | ||
2600 | sqrq.sq_deferred[tid] = hashes[h] | ||
2601 | bb.warn("Deferring %s after %s" % (tid, hashes[h])) | ||
2602 | |||
2559 | 2603 | ||
2560 | class TaskFailure(Exception): | 2604 | class TaskFailure(Exception): |
2561 | """ | 2605 | """ |
diff --git a/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass b/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass index e174c02dd6..cf38d09224 100644 --- a/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass +++ b/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass | |||
@@ -4,7 +4,9 @@ SSTATEVALID ??= "" | |||
4 | def stamptask(d): | 4 | def stamptask(d): |
5 | import time | 5 | import time |
6 | 6 | ||
7 | thistask = d.expand("${PN}:${BB_CURRENTTASK}") | 7 | thistask = d.expand("${PN}:${BB_CURRENTTASK}") |
8 | if d.getVar("BB_CURRENT_MC") != "default": | ||
9 | thistask = d.expand("${BB_CURRENT_MC}:${PN}:${BB_CURRENTTASK}") | ||
8 | if thistask in d.getVar("SLOWTASKS").split(): | 10 | if thistask in d.getVar("SLOWTASKS").split(): |
9 | bb.note("Slowing task %s" % thistask) | 11 | bb.note("Slowing task %s" % thistask) |
10 | time.sleep(0.5) | 12 | time.sleep(0.5) |
@@ -13,48 +15,63 @@ def stamptask(d): | |||
13 | f.write(thistask + "\n") | 15 | f.write(thistask + "\n") |
14 | 16 | ||
15 | python do_fetch() { | 17 | python do_fetch() { |
18 | # fetch | ||
16 | stamptask(d) | 19 | stamptask(d) |
17 | } | 20 | } |
18 | python do_unpack() { | 21 | python do_unpack() { |
22 | # unpack | ||
19 | stamptask(d) | 23 | stamptask(d) |
20 | } | 24 | } |
21 | python do_patch() { | 25 | python do_patch() { |
26 | # patch | ||
22 | stamptask(d) | 27 | stamptask(d) |
23 | } | 28 | } |
24 | python do_populate_lic() { | 29 | python do_populate_lic() { |
30 | # populate_lic | ||
25 | stamptask(d) | 31 | stamptask(d) |
26 | } | 32 | } |
27 | python do_prepare_recipe_sysroot() { | 33 | python do_prepare_recipe_sysroot() { |
34 | # prepare_recipe_sysroot | ||
28 | stamptask(d) | 35 | stamptask(d) |
29 | } | 36 | } |
30 | python do_configure() { | 37 | python do_configure() { |
38 | # configure | ||
31 | stamptask(d) | 39 | stamptask(d) |
32 | } | 40 | } |
33 | python do_compile() { | 41 | python do_compile() { |
42 | # compile | ||
34 | stamptask(d) | 43 | stamptask(d) |
35 | } | 44 | } |
36 | python do_install() { | 45 | python do_install() { |
46 | # install | ||
37 | stamptask(d) | 47 | stamptask(d) |
38 | } | 48 | } |
39 | python do_populate_sysroot() { | 49 | python do_populate_sysroot() { |
50 | # populate_sysroot | ||
40 | stamptask(d) | 51 | stamptask(d) |
41 | } | 52 | } |
42 | python do_package() { | 53 | python do_package() { |
54 | # package | ||
43 | stamptask(d) | 55 | stamptask(d) |
44 | } | 56 | } |
45 | python do_package_write_ipk() { | 57 | python do_package_write_ipk() { |
58 | # package_write_ipk | ||
46 | stamptask(d) | 59 | stamptask(d) |
47 | } | 60 | } |
48 | python do_package_write_rpm() { | 61 | python do_package_write_rpm() { |
62 | # package_write_rpm | ||
49 | stamptask(d) | 63 | stamptask(d) |
50 | } | 64 | } |
51 | python do_packagedata() { | 65 | python do_packagedata() { |
66 | # packagedata | ||
52 | stamptask(d) | 67 | stamptask(d) |
53 | } | 68 | } |
54 | python do_package_qa() { | 69 | python do_package_qa() { |
70 | # package_qa | ||
55 | stamptask(d) | 71 | stamptask(d) |
56 | } | 72 | } |
57 | python do_build() { | 73 | python do_build() { |
74 | # build | ||
58 | stamptask(d) | 75 | stamptask(d) |
59 | } | 76 | } |
60 | do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot" | 77 | do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot" |
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf index 8c7b754dab..96ee1cd5ec 100644 --- a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf | |||
@@ -6,6 +6,11 @@ PROVIDES = "${PN}" | |||
6 | PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0]}" | 6 | PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0]}" |
7 | PF = "${BB_CURRENT_MC}:${PN}" | 7 | PF = "${BB_CURRENT_MC}:${PN}" |
8 | export PATH | 8 | export PATH |
9 | STAMP = "${TOPDIR}/stamps/${PN}" | 9 | TMPDIR ??= "${TOPDIR}" |
10 | T = "${TOPDIR}/workdir/${PN}/temp" | 10 | STAMP = "${TMPDIR}/stamps/${PN}" |
11 | T = "${TMPDIR}/workdir/${PN}/temp" | ||
11 | BB_NUMBER_THREADS = "4" | 12 | BB_NUMBER_THREADS = "4" |
13 | |||
14 | BB_HASHBASE_WHITELIST = "BB_CURRENT_MC" | ||
15 | |||
16 | include conf/multiconfig/${BB_CURRENT_MC}.conf | ||
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf new file mode 100644 index 0000000000..ecf23e1c73 --- /dev/null +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf | |||
@@ -0,0 +1 @@ | |||
TMPDIR = "${TOPDIR}/mc1/" | |||
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf new file mode 100644 index 0000000000..eef338e4cc --- /dev/null +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf | |||
@@ -0,0 +1 @@ | |||
TMPDIR = "${TOPDIR}/mc2/" | |||
diff --git a/bitbake/lib/bb/tests/runqueue.py b/bitbake/lib/bb/tests/runqueue.py index 4a65b5b6e7..f0cea6483f 100644 --- a/bitbake/lib/bb/tests/runqueue.py +++ b/bitbake/lib/bb/tests/runqueue.py | |||
@@ -198,3 +198,22 @@ class RunQueueTests(unittest.TestCase): | |||
198 | 'b1:packagedata_setscene', 'b1:package_qa_setscene', 'b1:populate_sysroot_setscene'] | 198 | 'b1:packagedata_setscene', 'b1:package_qa_setscene', 'b1:populate_sysroot_setscene'] |
199 | self.assertEqual(set(tasks), set(expected)) | 199 | self.assertEqual(set(tasks), set(expected)) |
200 | 200 | ||
201 | def test_multiconfig_setscene_optimise(self): | ||
202 | with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: | ||
203 | extraenv = { | ||
204 | "BBMULTICONFIG" : "mc1 mc2", | ||
205 | "BB_SIGNATURE_HANDLER" : "basic" | ||
206 | } | ||
207 | cmd = ["bitbake", "b1", "mc:mc1:b1", "mc:mc2:b1"] | ||
208 | setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', | ||
209 | 'populate_sysroot_setscene', 'package_qa_setscene'] | ||
210 | sstatevalid = "" | ||
211 | tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv) | ||
212 | expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + \ | ||
213 | ['mc1:b1:' + x for x in setscenetasks] + ['mc1:a1:' + x for x in setscenetasks] + \ | ||
214 | ['mc2:b1:' + x for x in setscenetasks] + ['mc2:a1:' + x for x in setscenetasks] + \ | ||
215 | ['mc1:b1:build', 'mc2:b1:build'] | ||
216 | for x in ['mc1:a1:package_qa_setscene', 'mc2:a1:package_qa_setscene', 'a1:build', 'a1:package_qa']: | ||
217 | expected.remove(x) | ||
218 | self.assertEqual(set(tasks), set(expected)) | ||
219 | |||