diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-06-12 23:55:48 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-06-15 08:35:07 +0100 |
commit | af04a52bf7d7ae94c187e85028a80dee6d7853f0 (patch) | |
tree | d0c65de172d7ded2e1ba28f09c271da97e10cbe9 /bitbake/lib/bb/taskdata.py | |
parent | 29b4fb17966bfaec74b41cce533725c04ec1078f (diff) | |
download | poky-af04a52bf7d7ae94c187e85028a80dee6d7853f0.tar.gz |
bitbake: taskdata/runqueue: Rewrite without use of ID indirection
I'm not sure what possesed me when I wrote this code originally but its
indirection of everyting to use numeric IDs and position dependent lists
is horrific. Given the way python internals work, its completely and
utterly pointless from performance perspective. It also makes the code
hard to understand and debug since any numeric ID has to be translated
into something human readable.
The hard part is that the IDs are infectous and spread from taskdata
into runqueue and even partly into cooker for the dependency graph
processing. The only real way to deal with this is to convert everything
to use a more sane data structure.
This patch:
* Uses "<fn>:<taskname>" as the ID for tasks rather than a number
* Changes to dict() based structures rather than position dependent lists
* Drops the build name, runtime name and filename ID indexes
On the most part there shouldn't be user visible changes. Sadly we did
leak datastructures to the setscene verify function which has to be
rewritten. To handle this, the variable name used to specifiy the version
changes from BB_SETSCENE_VERIFY_FUNCTION to BB_SETSCENE_VERIFY_FUNCTION2
allowing multiple versions of bitbake to work with suitably written
metadata. Anyone with custom schedulers may also need to change them.
I believe the benefits in code readability and easier debugging far
outweigh those issues though. It also means we have a saner codebase
to add multiconfig support on top of.
During development, I did have some of the original code coexisting with
the new data stores to allow comparision of the data and check it was
working correcty, particuarly for taskdata. I have also compared
task-depends.dot files before and after the change. There should be no
functionality changes in this patch, its purely a data structure change
and that is visible in the patch.
(Bitbake rev: 2c88afb60da54e58f555411a7bd7b006b0c29306)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/taskdata.py')
-rw-r--r-- | bitbake/lib/bb/taskdata.py | 412 |
1 files changed, 152 insertions, 260 deletions
diff --git a/bitbake/lib/bb/taskdata.py b/bitbake/lib/bb/taskdata.py index 65628c86f2..d8bdbcabf9 100644 --- a/bitbake/lib/bb/taskdata.py +++ b/bitbake/lib/bb/taskdata.py | |||
@@ -37,27 +37,24 @@ def re_match_strings(target, strings): | |||
37 | return any(name == target or re.match(name, target) | 37 | return any(name == target or re.match(name, target) |
38 | for name in strings) | 38 | for name in strings) |
39 | 39 | ||
40 | class TaskEntry: | ||
41 | def __init__(self): | ||
42 | self.tdepends = [] | ||
43 | self.idepends = [] | ||
44 | self.irdepends = [] | ||
45 | |||
40 | class TaskData: | 46 | class TaskData: |
41 | """ | 47 | """ |
42 | BitBake Task Data implementation | 48 | BitBake Task Data implementation |
43 | """ | 49 | """ |
44 | def __init__(self, abort = True, tryaltconfigs = False, skiplist = None, allowincomplete = False): | 50 | def __init__(self, abort = True, tryaltconfigs = False, skiplist = None, allowincomplete = False): |
45 | self.build_names_index = [] | ||
46 | self.run_names_index = [] | ||
47 | self.fn_index = [] | ||
48 | |||
49 | self.build_targets = {} | 51 | self.build_targets = {} |
50 | self.run_targets = {} | 52 | self.run_targets = {} |
51 | 53 | ||
52 | self.external_targets = [] | 54 | self.external_targets = [] |
53 | 55 | ||
54 | self.tasks_fnid = [] | 56 | self.seenfns = [] |
55 | self.tasks_name = [] | 57 | self.taskentries = {} |
56 | self.tasks_tdepends = [] | ||
57 | self.tasks_idepends = [] | ||
58 | self.tasks_irdepends = [] | ||
59 | # Cache to speed up task ID lookups | ||
60 | self.tasks_lookup = {} | ||
61 | 58 | ||
62 | self.depids = {} | 59 | self.depids = {} |
63 | self.rdepids = {} | 60 | self.rdepids = {} |
@@ -66,7 +63,7 @@ class TaskData: | |||
66 | 63 | ||
67 | self.failed_deps = [] | 64 | self.failed_deps = [] |
68 | self.failed_rdeps = [] | 65 | self.failed_rdeps = [] |
69 | self.failed_fnids = [] | 66 | self.failed_fns = [] |
70 | 67 | ||
71 | self.abort = abort | 68 | self.abort = abort |
72 | self.tryaltconfigs = tryaltconfigs | 69 | self.tryaltconfigs = tryaltconfigs |
@@ -74,88 +71,6 @@ class TaskData: | |||
74 | 71 | ||
75 | self.skiplist = skiplist | 72 | self.skiplist = skiplist |
76 | 73 | ||
77 | def getbuild_id(self, name): | ||
78 | """ | ||
79 | Return an ID number for the build target name. | ||
80 | If it doesn't exist, create one. | ||
81 | """ | ||
82 | if not name in self.build_names_index: | ||
83 | self.build_names_index.append(name) | ||
84 | return len(self.build_names_index) - 1 | ||
85 | |||
86 | return self.build_names_index.index(name) | ||
87 | |||
88 | def getrun_id(self, name): | ||
89 | """ | ||
90 | Return an ID number for the run target name. | ||
91 | If it doesn't exist, create one. | ||
92 | """ | ||
93 | if not name in self.run_names_index: | ||
94 | self.run_names_index.append(name) | ||
95 | return len(self.run_names_index) - 1 | ||
96 | |||
97 | return self.run_names_index.index(name) | ||
98 | |||
99 | def getfn_id(self, name): | ||
100 | """ | ||
101 | Return an ID number for the filename. | ||
102 | If it doesn't exist, create one. | ||
103 | """ | ||
104 | if not name in self.fn_index: | ||
105 | self.fn_index.append(name) | ||
106 | return len(self.fn_index) - 1 | ||
107 | |||
108 | return self.fn_index.index(name) | ||
109 | |||
110 | def gettask_ids(self, fnid): | ||
111 | """ | ||
112 | Return an array of the ID numbers matching a given fnid. | ||
113 | """ | ||
114 | ids = [] | ||
115 | if fnid in self.tasks_lookup: | ||
116 | for task in self.tasks_lookup[fnid]: | ||
117 | ids.append(self.tasks_lookup[fnid][task]) | ||
118 | return ids | ||
119 | |||
120 | def gettask_id_fromfnid(self, fnid, task): | ||
121 | """ | ||
122 | Return an ID number for the task matching fnid and task. | ||
123 | """ | ||
124 | if fnid in self.tasks_lookup: | ||
125 | if task in self.tasks_lookup[fnid]: | ||
126 | return self.tasks_lookup[fnid][task] | ||
127 | |||
128 | return None | ||
129 | |||
130 | def gettask_id(self, fn, task, create = True): | ||
131 | """ | ||
132 | Return an ID number for the task matching fn and task. | ||
133 | If it doesn't exist, create one by default. | ||
134 | Optionally return None instead. | ||
135 | """ | ||
136 | fnid = self.getfn_id(fn) | ||
137 | |||
138 | if fnid in self.tasks_lookup: | ||
139 | if task in self.tasks_lookup[fnid]: | ||
140 | return self.tasks_lookup[fnid][task] | ||
141 | |||
142 | if not create: | ||
143 | return None | ||
144 | |||
145 | self.tasks_name.append(task) | ||
146 | self.tasks_fnid.append(fnid) | ||
147 | self.tasks_tdepends.append([]) | ||
148 | self.tasks_idepends.append([]) | ||
149 | self.tasks_irdepends.append([]) | ||
150 | |||
151 | listid = len(self.tasks_name) - 1 | ||
152 | |||
153 | if fnid not in self.tasks_lookup: | ||
154 | self.tasks_lookup[fnid] = {} | ||
155 | self.tasks_lookup[fnid][task] = listid | ||
156 | |||
157 | return listid | ||
158 | |||
159 | def add_tasks(self, fn, dataCache): | 74 | def add_tasks(self, fn, dataCache): |
160 | """ | 75 | """ |
161 | Add tasks for a given fn to the database | 76 | Add tasks for a given fn to the database |
@@ -163,29 +78,31 @@ class TaskData: | |||
163 | 78 | ||
164 | task_deps = dataCache.task_deps[fn] | 79 | task_deps = dataCache.task_deps[fn] |
165 | 80 | ||
166 | fnid = self.getfn_id(fn) | 81 | if fn in self.failed_fns: |
167 | |||
168 | if fnid in self.failed_fnids: | ||
169 | bb.msg.fatal("TaskData", "Trying to re-add a failed file? Something is broken...") | 82 | bb.msg.fatal("TaskData", "Trying to re-add a failed file? Something is broken...") |
170 | 83 | ||
171 | # Check if we've already seen this fn | 84 | # Check if we've already seen this fn |
172 | if fnid in self.tasks_fnid: | 85 | if fn in self.seenfns: |
173 | return | 86 | return |
174 | 87 | ||
88 | self.seenfns.append(fn) | ||
89 | |||
175 | self.add_extra_deps(fn, dataCache) | 90 | self.add_extra_deps(fn, dataCache) |
176 | 91 | ||
177 | for task in task_deps['tasks']: | 92 | for task in task_deps['tasks']: |
178 | 93 | ||
94 | tid = "%s:%s" % (fn, task) | ||
95 | self.taskentries[tid] = TaskEntry() | ||
96 | |||
179 | # Work out task dependencies | 97 | # Work out task dependencies |
180 | parentids = [] | 98 | parentids = [] |
181 | for dep in task_deps['parents'][task]: | 99 | for dep in task_deps['parents'][task]: |
182 | if dep not in task_deps['tasks']: | 100 | if dep not in task_deps['tasks']: |
183 | bb.debug(2, "Not adding dependeny of %s on %s since %s does not exist" % (task, dep, dep)) | 101 | bb.debug(2, "Not adding dependeny of %s on %s since %s does not exist" % (task, dep, dep)) |
184 | continue | 102 | continue |
185 | parentid = self.gettask_id(fn, dep) | 103 | parentid = "%s:%s" % (fn, dep) |
186 | parentids.append(parentid) | 104 | parentids.append(parentid) |
187 | taskid = self.gettask_id(fn, task) | 105 | self.taskentries[tid].tdepends.extend(parentids) |
188 | self.tasks_tdepends[taskid].extend(parentids) | ||
189 | 106 | ||
190 | # Touch all intertask dependencies | 107 | # Touch all intertask dependencies |
191 | if 'depends' in task_deps and task in task_deps['depends']: | 108 | if 'depends' in task_deps and task in task_deps['depends']: |
@@ -194,29 +111,30 @@ class TaskData: | |||
194 | if dep: | 111 | if dep: |
195 | if ":" not in dep: | 112 | if ":" not in dep: |
196 | bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'depends' should be specified in the form 'packagename:task'" % (fn, dep)) | 113 | bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'depends' should be specified in the form 'packagename:task'" % (fn, dep)) |
197 | ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1])) | 114 | ids.append(((dep.split(":")[0]), dep.split(":")[1])) |
198 | self.tasks_idepends[taskid].extend(ids) | 115 | self.seen_build_target(dep.split(":")[0]) |
116 | self.taskentries[tid].idepends.extend(ids) | ||
199 | if 'rdepends' in task_deps and task in task_deps['rdepends']: | 117 | if 'rdepends' in task_deps and task in task_deps['rdepends']: |
200 | ids = [] | 118 | ids = [] |
201 | for dep in task_deps['rdepends'][task].split(): | 119 | for dep in task_deps['rdepends'][task].split(): |
202 | if dep: | 120 | if dep: |
203 | if ":" not in dep: | 121 | if ":" not in dep: |
204 | bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'rdepends' should be specified in the form 'packagename:task'" % (fn, dep)) | 122 | bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'rdepends' should be specified in the form 'packagename:task'" % (fn, dep)) |
205 | ids.append(((self.getrun_id(dep.split(":")[0])), dep.split(":")[1])) | 123 | ids.append(((dep.split(":")[0]), dep.split(":")[1])) |
206 | self.tasks_irdepends[taskid].extend(ids) | 124 | self.seen_run_target(dep.split(":")[0]) |
207 | 125 | self.taskentries[tid].irdepends.extend(ids) | |
208 | 126 | ||
209 | # Work out build dependencies | 127 | # Work out build dependencies |
210 | if not fnid in self.depids: | 128 | if not fn in self.depids: |
211 | dependids = {} | 129 | dependids = set() |
212 | for depend in dataCache.deps[fn]: | 130 | for depend in dataCache.deps[fn]: |
213 | dependids[self.getbuild_id(depend)] = None | 131 | dependids.add(depend) |
214 | self.depids[fnid] = dependids.keys() | 132 | self.depids[fn] = list(dependids) |
215 | logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn) | 133 | logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn) |
216 | 134 | ||
217 | # Work out runtime dependencies | 135 | # Work out runtime dependencies |
218 | if not fnid in self.rdepids: | 136 | if not fn in self.rdepids: |
219 | rdependids = {} | 137 | rdependids = set() |
220 | rdepends = dataCache.rundeps[fn] | 138 | rdepends = dataCache.rundeps[fn] |
221 | rrecs = dataCache.runrecs[fn] | 139 | rrecs = dataCache.runrecs[fn] |
222 | rdependlist = [] | 140 | rdependlist = [] |
@@ -224,24 +142,26 @@ class TaskData: | |||
224 | for package in rdepends: | 142 | for package in rdepends: |
225 | for rdepend in rdepends[package]: | 143 | for rdepend in rdepends[package]: |
226 | rdependlist.append(rdepend) | 144 | rdependlist.append(rdepend) |
227 | rdependids[self.getrun_id(rdepend)] = None | 145 | rdependids.add(rdepend) |
228 | for package in rrecs: | 146 | for package in rrecs: |
229 | for rdepend in rrecs[package]: | 147 | for rdepend in rrecs[package]: |
230 | rreclist.append(rdepend) | 148 | rreclist.append(rdepend) |
231 | rdependids[self.getrun_id(rdepend)] = None | 149 | rdependids.add(rdepend) |
232 | if rdependlist: | 150 | if rdependlist: |
233 | logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn) | 151 | logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn) |
234 | if rreclist: | 152 | if rreclist: |
235 | logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn) | 153 | logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn) |
236 | self.rdepids[fnid] = rdependids.keys() | 154 | self.rdepids[fn] = list(rdependids) |
237 | 155 | ||
238 | for dep in self.depids[fnid]: | 156 | for dep in self.depids[fn]: |
157 | self.seen_build_target(dep) | ||
239 | if dep in self.failed_deps: | 158 | if dep in self.failed_deps: |
240 | self.fail_fnid(fnid) | 159 | self.fail_fn(fn) |
241 | return | 160 | return |
242 | for dep in self.rdepids[fnid]: | 161 | for dep in self.rdepids[fn]: |
162 | self.seen_run_target(dep) | ||
243 | if dep in self.failed_rdeps: | 163 | if dep in self.failed_rdeps: |
244 | self.fail_fnid(fnid) | 164 | self.fail_fn(fn) |
245 | return | 165 | return |
246 | 166 | ||
247 | def add_extra_deps(self, fn, dataCache): | 167 | def add_extra_deps(self, fn, dataCache): |
@@ -263,9 +183,7 @@ class TaskData: | |||
263 | """ | 183 | """ |
264 | Have we a build target matching this name? | 184 | Have we a build target matching this name? |
265 | """ | 185 | """ |
266 | targetid = self.getbuild_id(target) | 186 | if target in self.build_targets and self.build_targets[target]: |
267 | |||
268 | if targetid in self.build_targets: | ||
269 | return True | 187 | return True |
270 | return False | 188 | return False |
271 | 189 | ||
@@ -273,50 +191,54 @@ class TaskData: | |||
273 | """ | 191 | """ |
274 | Have we a runtime target matching this name? | 192 | Have we a runtime target matching this name? |
275 | """ | 193 | """ |
276 | targetid = self.getrun_id(target) | 194 | if target in self.run_targets and self.run_targets[target]: |
277 | |||
278 | if targetid in self.run_targets: | ||
279 | return True | 195 | return True |
280 | return False | 196 | return False |
281 | 197 | ||
198 | def seen_build_target(self, name): | ||
199 | """ | ||
200 | Maintain a list of build targets | ||
201 | """ | ||
202 | if name not in self.build_targets: | ||
203 | self.build_targets[name] = [] | ||
204 | |||
282 | def add_build_target(self, fn, item): | 205 | def add_build_target(self, fn, item): |
283 | """ | 206 | """ |
284 | Add a build target. | 207 | Add a build target. |
285 | If already present, append the provider fn to the list | 208 | If already present, append the provider fn to the list |
286 | """ | 209 | """ |
287 | targetid = self.getbuild_id(item) | 210 | if item in self.build_targets: |
288 | fnid = self.getfn_id(fn) | 211 | if fn in self.build_targets[item]: |
289 | |||
290 | if targetid in self.build_targets: | ||
291 | if fnid in self.build_targets[targetid]: | ||
292 | return | 212 | return |
293 | self.build_targets[targetid].append(fnid) | 213 | self.build_targets[item].append(fn) |
294 | return | 214 | return |
295 | self.build_targets[targetid] = [fnid] | 215 | self.build_targets[item] = [fn] |
216 | |||
217 | def seen_run_target(self, name): | ||
218 | """ | ||
219 | Maintain a list of runtime build targets | ||
220 | """ | ||
221 | if name not in self.run_targets: | ||
222 | self.run_targets[name] = [] | ||
296 | 223 | ||
297 | def add_runtime_target(self, fn, item): | 224 | def add_runtime_target(self, fn, item): |
298 | """ | 225 | """ |
299 | Add a runtime target. | 226 | Add a runtime target. |
300 | If already present, append the provider fn to the list | 227 | If already present, append the provider fn to the list |
301 | """ | 228 | """ |
302 | targetid = self.getrun_id(item) | 229 | if item in self.run_targets: |
303 | fnid = self.getfn_id(fn) | 230 | if fn in self.run_targets[item]: |
304 | |||
305 | if targetid in self.run_targets: | ||
306 | if fnid in self.run_targets[targetid]: | ||
307 | return | 231 | return |
308 | self.run_targets[targetid].append(fnid) | 232 | self.run_targets[item].append(fn) |
309 | return | 233 | return |
310 | self.run_targets[targetid] = [fnid] | 234 | self.run_targets[item] = [fn] |
311 | 235 | ||
312 | def mark_external_target(self, item): | 236 | def mark_external_target(self, target): |
313 | """ | 237 | """ |
314 | Mark a build target as being externally requested | 238 | Mark a build target as being externally requested |
315 | """ | 239 | """ |
316 | targetid = self.getbuild_id(item) | 240 | if target not in self.external_targets: |
317 | 241 | self.external_targets.append(target) | |
318 | if targetid not in self.external_targets: | ||
319 | self.external_targets.append(targetid) | ||
320 | 242 | ||
321 | def get_unresolved_build_targets(self, dataCache): | 243 | def get_unresolved_build_targets(self, dataCache): |
322 | """ | 244 | """ |
@@ -324,12 +246,12 @@ class TaskData: | |||
324 | are unknown. | 246 | are unknown. |
325 | """ | 247 | """ |
326 | unresolved = [] | 248 | unresolved = [] |
327 | for target in self.build_names_index: | 249 | for target in self.build_targets: |
328 | if re_match_strings(target, dataCache.ignored_dependencies): | 250 | if re_match_strings(target, dataCache.ignored_dependencies): |
329 | continue | 251 | continue |
330 | if self.build_names_index.index(target) in self.failed_deps: | 252 | if target in self.failed_deps: |
331 | continue | 253 | continue |
332 | if not self.have_build_target(target): | 254 | if not self.build_targets[target]: |
333 | unresolved.append(target) | 255 | unresolved.append(target) |
334 | return unresolved | 256 | return unresolved |
335 | 257 | ||
@@ -339,12 +261,12 @@ class TaskData: | |||
339 | are unknown. | 261 | are unknown. |
340 | """ | 262 | """ |
341 | unresolved = [] | 263 | unresolved = [] |
342 | for target in self.run_names_index: | 264 | for target in self.run_targets: |
343 | if re_match_strings(target, dataCache.ignored_dependencies): | 265 | if re_match_strings(target, dataCache.ignored_dependencies): |
344 | continue | 266 | continue |
345 | if self.run_names_index.index(target) in self.failed_rdeps: | 267 | if target in self.failed_rdeps: |
346 | continue | 268 | continue |
347 | if not self.have_runtime_target(target): | 269 | if not self.run_targets[target]: |
348 | unresolved.append(target) | 270 | unresolved.append(target) |
349 | return unresolved | 271 | return unresolved |
350 | 272 | ||
@@ -352,50 +274,26 @@ class TaskData: | |||
352 | """ | 274 | """ |
353 | Return a list of providers of item | 275 | Return a list of providers of item |
354 | """ | 276 | """ |
355 | targetid = self.getbuild_id(item) | 277 | return self.build_targets[item] |
356 | 278 | ||
357 | return self.build_targets[targetid] | 279 | def get_dependees(self, item): |
358 | |||
359 | def get_dependees(self, itemid): | ||
360 | """ | 280 | """ |
361 | Return a list of targets which depend on item | 281 | Return a list of targets which depend on item |
362 | """ | 282 | """ |
363 | dependees = [] | 283 | dependees = [] |
364 | for fnid in self.depids: | 284 | for fn in self.depids: |
365 | if itemid in self.depids[fnid]: | 285 | if item in self.depids[fn]: |
366 | dependees.append(fnid) | 286 | dependees.append(fn) |
367 | return dependees | ||
368 | |||
369 | def get_dependees_str(self, item): | ||
370 | """ | ||
371 | Return a list of targets which depend on item as a user readable string | ||
372 | """ | ||
373 | itemid = self.getbuild_id(item) | ||
374 | dependees = [] | ||
375 | for fnid in self.depids: | ||
376 | if itemid in self.depids[fnid]: | ||
377 | dependees.append(self.fn_index[fnid]) | ||
378 | return dependees | 287 | return dependees |
379 | 288 | ||
380 | def get_rdependees(self, itemid): | 289 | def get_rdependees(self, item): |
381 | """ | 290 | """ |
382 | Return a list of targets which depend on runtime item | 291 | Return a list of targets which depend on runtime item |
383 | """ | 292 | """ |
384 | dependees = [] | 293 | dependees = [] |
385 | for fnid in self.rdepids: | 294 | for fn in self.rdepids: |
386 | if itemid in self.rdepids[fnid]: | 295 | if item in self.rdepids[fn]: |
387 | dependees.append(fnid) | 296 | dependees.append(fn) |
388 | return dependees | ||
389 | |||
390 | def get_rdependees_str(self, item): | ||
391 | """ | ||
392 | Return a list of targets which depend on runtime item as a user readable string | ||
393 | """ | ||
394 | itemid = self.getrun_id(item) | ||
395 | dependees = [] | ||
396 | for fnid in self.rdepids: | ||
397 | if itemid in self.rdepids[fnid]: | ||
398 | dependees.append(self.fn_index[fnid]) | ||
399 | return dependees | 297 | return dependees |
400 | 298 | ||
401 | def get_reasons(self, item, runtime=False): | 299 | def get_reasons(self, item, runtime=False): |
@@ -431,7 +329,7 @@ class TaskData: | |||
431 | except bb.providers.NoProvider: | 329 | except bb.providers.NoProvider: |
432 | if self.abort: | 330 | if self.abort: |
433 | raise | 331 | raise |
434 | self.remove_buildtarget(self.getbuild_id(item)) | 332 | self.remove_buildtarget(item) |
435 | 333 | ||
436 | self.mark_external_target(item) | 334 | self.mark_external_target(item) |
437 | 335 | ||
@@ -453,7 +351,7 @@ class TaskData: | |||
453 | new = dataCache.pkg_fn[fn] + " RPROVIDES " + item | 351 | new = dataCache.pkg_fn[fn] + " RPROVIDES " + item |
454 | if new not in close_matches: | 352 | if new not in close_matches: |
455 | close_matches.append(new) | 353 | close_matches.append(new) |
456 | bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData) | 354 | bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData) |
457 | raise bb.providers.NoProvider(item) | 355 | raise bb.providers.NoProvider(item) |
458 | 356 | ||
459 | if self.have_build_target(item): | 357 | if self.have_build_target(item): |
@@ -462,10 +360,10 @@ class TaskData: | |||
462 | all_p = dataCache.providers[item] | 360 | all_p = dataCache.providers[item] |
463 | 361 | ||
464 | eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache) | 362 | eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache) |
465 | eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids] | 363 | eligible = [p for p in eligible if not p in self.failed_fns] |
466 | 364 | ||
467 | if not eligible: | 365 | if not eligible: |
468 | bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=["No eligible PROVIDERs exist for '%s'" % item]), cfgData) | 366 | bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees(item), reasons=["No eligible PROVIDERs exist for '%s'" % item]), cfgData) |
469 | raise bb.providers.NoProvider(item) | 367 | raise bb.providers.NoProvider(item) |
470 | 368 | ||
471 | if len(eligible) > 1 and foundUnique == False: | 369 | if len(eligible) > 1 and foundUnique == False: |
@@ -477,8 +375,7 @@ class TaskData: | |||
477 | self.consider_msgs_cache.append(item) | 375 | self.consider_msgs_cache.append(item) |
478 | 376 | ||
479 | for fn in eligible: | 377 | for fn in eligible: |
480 | fnid = self.getfn_id(fn) | 378 | if fn in self.failed_fns: |
481 | if fnid in self.failed_fnids: | ||
482 | continue | 379 | continue |
483 | logger.debug(2, "adding %s to satisfy %s", fn, item) | 380 | logger.debug(2, "adding %s to satisfy %s", fn, item) |
484 | self.add_build_target(fn, item) | 381 | self.add_build_target(fn, item) |
@@ -502,14 +399,14 @@ class TaskData: | |||
502 | all_p = bb.providers.getRuntimeProviders(dataCache, item) | 399 | all_p = bb.providers.getRuntimeProviders(dataCache, item) |
503 | 400 | ||
504 | if not all_p: | 401 | if not all_p: |
505 | bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=self.get_reasons(item, True)), cfgData) | 402 | bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees(item), reasons=self.get_reasons(item, True)), cfgData) |
506 | raise bb.providers.NoRProvider(item) | 403 | raise bb.providers.NoRProvider(item) |
507 | 404 | ||
508 | eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache) | 405 | eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache) |
509 | eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids] | 406 | eligible = [p for p in eligible if not p in self.failed_fns] |
510 | 407 | ||
511 | if not eligible: | 408 | if not eligible: |
512 | bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=["No eligible RPROVIDERs exist for '%s'" % item]), cfgData) | 409 | bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees(item), reasons=["No eligible RPROVIDERs exist for '%s'" % item]), cfgData) |
513 | raise bb.providers.NoRProvider(item) | 410 | raise bb.providers.NoRProvider(item) |
514 | 411 | ||
515 | if len(eligible) > 1 and numberPreferred == 0: | 412 | if len(eligible) > 1 and numberPreferred == 0: |
@@ -531,82 +428,80 @@ class TaskData: | |||
531 | 428 | ||
532 | # run through the list until we find one that we can build | 429 | # run through the list until we find one that we can build |
533 | for fn in eligible: | 430 | for fn in eligible: |
534 | fnid = self.getfn_id(fn) | 431 | if fn in self.failed_fns: |
535 | if fnid in self.failed_fnids: | ||
536 | continue | 432 | continue |
537 | logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item) | 433 | logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item) |
538 | self.add_runtime_target(fn, item) | 434 | self.add_runtime_target(fn, item) |
539 | self.add_tasks(fn, dataCache) | 435 | self.add_tasks(fn, dataCache) |
540 | 436 | ||
541 | def fail_fnid(self, fnid, missing_list=None): | 437 | def fail_fn(self, fn, missing_list=None): |
542 | """ | 438 | """ |
543 | Mark a file as failed (unbuildable) | 439 | Mark a file as failed (unbuildable) |
544 | Remove any references from build and runtime provider lists | 440 | Remove any references from build and runtime provider lists |
545 | 441 | ||
546 | missing_list, A list of missing requirements for this target | 442 | missing_list, A list of missing requirements for this target |
547 | """ | 443 | """ |
548 | if fnid in self.failed_fnids: | 444 | if fn in self.failed_fns: |
549 | return | 445 | return |
550 | if not missing_list: | 446 | if not missing_list: |
551 | missing_list = [] | 447 | missing_list = [] |
552 | logger.debug(1, "File '%s' is unbuildable, removing...", self.fn_index[fnid]) | 448 | logger.debug(1, "File '%s' is unbuildable, removing...", fn) |
553 | self.failed_fnids.append(fnid) | 449 | self.failed_fns.append(fn) |
554 | for target in self.build_targets: | 450 | for target in self.build_targets: |
555 | if fnid in self.build_targets[target]: | 451 | if fn in self.build_targets[target]: |
556 | self.build_targets[target].remove(fnid) | 452 | self.build_targets[target].remove(fn) |
557 | if len(self.build_targets[target]) == 0: | 453 | if len(self.build_targets[target]) == 0: |
558 | self.remove_buildtarget(target, missing_list) | 454 | self.remove_buildtarget(target, missing_list) |
559 | for target in self.run_targets: | 455 | for target in self.run_targets: |
560 | if fnid in self.run_targets[target]: | 456 | if fn in self.run_targets[target]: |
561 | self.run_targets[target].remove(fnid) | 457 | self.run_targets[target].remove(fn) |
562 | if len(self.run_targets[target]) == 0: | 458 | if len(self.run_targets[target]) == 0: |
563 | self.remove_runtarget(target, missing_list) | 459 | self.remove_runtarget(target, missing_list) |
564 | 460 | ||
565 | def remove_buildtarget(self, targetid, missing_list=None): | 461 | def remove_buildtarget(self, target, missing_list=None): |
566 | """ | 462 | """ |
567 | Mark a build target as failed (unbuildable) | 463 | Mark a build target as failed (unbuildable) |
568 | Trigger removal of any files that have this as a dependency | 464 | Trigger removal of any files that have this as a dependency |
569 | """ | 465 | """ |
570 | if not missing_list: | 466 | if not missing_list: |
571 | missing_list = [self.build_names_index[targetid]] | 467 | missing_list = [target] |
572 | else: | 468 | else: |
573 | missing_list = [self.build_names_index[targetid]] + missing_list | 469 | missing_list = [target] + missing_list |
574 | logger.verbose("Target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.build_names_index[targetid], missing_list) | 470 | logger.verbose("Target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", target, missing_list) |
575 | self.failed_deps.append(targetid) | 471 | self.failed_deps.append(target) |
576 | dependees = self.get_dependees(targetid) | 472 | dependees = self.get_dependees(target) |
577 | for fnid in dependees: | 473 | for fn in dependees: |
578 | self.fail_fnid(fnid, missing_list) | 474 | self.fail_fn(fn, missing_list) |
579 | for taskid in range(len(self.tasks_idepends)): | 475 | for tid in self.taskentries: |
580 | idepends = self.tasks_idepends[taskid] | 476 | for (idepend, idependtask) in self.taskentries[tid].idepends: |
581 | for (idependid, idependtask) in idepends: | 477 | if idepend == target: |
582 | if idependid == targetid: | 478 | fn = tid.rsplit(":",1)[0] |
583 | self.fail_fnid(self.tasks_fnid[taskid], missing_list) | 479 | self.fail_fn(fn, missing_list) |
584 | 480 | ||
585 | if self.abort and targetid in self.external_targets: | 481 | if self.abort and target in self.external_targets: |
586 | target = self.build_names_index[targetid] | ||
587 | logger.error("Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s", target, missing_list) | 482 | logger.error("Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s", target, missing_list) |
588 | raise bb.providers.NoProvider(target) | 483 | raise bb.providers.NoProvider(target) |
589 | 484 | ||
590 | def remove_runtarget(self, targetid, missing_list=None): | 485 | def remove_runtarget(self, target, missing_list=None): |
591 | """ | 486 | """ |
592 | Mark a run target as failed (unbuildable) | 487 | Mark a run target as failed (unbuildable) |
593 | Trigger removal of any files that have this as a dependency | 488 | Trigger removal of any files that have this as a dependency |
594 | """ | 489 | """ |
595 | if not missing_list: | 490 | if not missing_list: |
596 | missing_list = [self.run_names_index[targetid]] | 491 | missing_list = [target] |
597 | else: | 492 | else: |
598 | missing_list = [self.run_names_index[targetid]] + missing_list | 493 | missing_list = [target] + missing_list |
599 | 494 | ||
600 | logger.info("Runtime target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.run_names_index[targetid], missing_list) | 495 | logger.info("Runtime target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", target, missing_list) |
601 | self.failed_rdeps.append(targetid) | 496 | self.failed_rdeps.append(target) |
602 | dependees = self.get_rdependees(targetid) | 497 | dependees = self.get_rdependees(target) |
603 | for fnid in dependees: | 498 | for fn in dependees: |
604 | self.fail_fnid(fnid, missing_list) | 499 | self.fail_fn(fn, missing_list) |
605 | for taskid in range(len(self.tasks_irdepends)): | 500 | for tid in self.taskentries: |
606 | irdepends = self.tasks_irdepends[taskid] | 501 | for (idepend, idependtask) in self.taskentries[tid].irdepends: |
607 | for (idependid, idependtask) in irdepends: | 502 | if idepend == target: |
608 | if idependid == targetid: | 503 | fn = tid.rsplit(":",1)[0] |
609 | self.fail_fnid(self.tasks_fnid[taskid], missing_list) | 504 | self.fail_fn(fn, missing_list) |
610 | 505 | ||
611 | def add_unresolved(self, cfgData, dataCache): | 506 | def add_unresolved(self, cfgData, dataCache): |
612 | """ | 507 | """ |
@@ -620,17 +515,16 @@ class TaskData: | |||
620 | self.add_provider_internal(cfgData, dataCache, target) | 515 | self.add_provider_internal(cfgData, dataCache, target) |
621 | added = added + 1 | 516 | added = added + 1 |
622 | except bb.providers.NoProvider: | 517 | except bb.providers.NoProvider: |
623 | targetid = self.getbuild_id(target) | 518 | if self.abort and target in self.external_targets and not self.allowincomplete: |
624 | if self.abort and targetid in self.external_targets and not self.allowincomplete: | ||
625 | raise | 519 | raise |
626 | if not self.allowincomplete: | 520 | if not self.allowincomplete: |
627 | self.remove_buildtarget(targetid) | 521 | self.remove_buildtarget(target) |
628 | for target in self.get_unresolved_run_targets(dataCache): | 522 | for target in self.get_unresolved_run_targets(dataCache): |
629 | try: | 523 | try: |
630 | self.add_rprovider(cfgData, dataCache, target) | 524 | self.add_rprovider(cfgData, dataCache, target) |
631 | added = added + 1 | 525 | added = added + 1 |
632 | except (bb.providers.NoRProvider, bb.providers.MultipleRProvider): | 526 | except (bb.providers.NoRProvider, bb.providers.MultipleRProvider): |
633 | self.remove_runtarget(self.getrun_id(target)) | 527 | self.remove_runtarget(target) |
634 | logger.debug(1, "Resolved " + str(added) + " extra dependencies") | 528 | logger.debug(1, "Resolved " + str(added) + " extra dependencies") |
635 | if added == 0: | 529 | if added == 0: |
636 | break | 530 | break |
@@ -638,13 +532,13 @@ class TaskData: | |||
638 | 532 | ||
639 | def get_providermap(self, prefix=None): | 533 | def get_providermap(self, prefix=None): |
640 | provmap = {} | 534 | provmap = {} |
641 | for name in self.build_names_index: | 535 | for name in self.build_targets: |
642 | if prefix and not name.startswith(prefix): | 536 | if prefix and not name.startswith(prefix): |
643 | continue | 537 | continue |
644 | if self.have_build_target(name): | 538 | if self.have_build_target(name): |
645 | provider = self.get_provider(name) | 539 | provider = self.get_provider(name) |
646 | if provider: | 540 | if provider: |
647 | provmap[name] = self.fn_index[provider[0]] | 541 | provmap[name] = provider[0] |
648 | return provmap | 542 | return provmap |
649 | 543 | ||
650 | def dump_data(self): | 544 | def dump_data(self): |
@@ -652,39 +546,37 @@ class TaskData: | |||
652 | Dump some debug information on the internal data structures | 546 | Dump some debug information on the internal data structures |
653 | """ | 547 | """ |
654 | logger.debug(3, "build_names:") | 548 | logger.debug(3, "build_names:") |
655 | logger.debug(3, ", ".join(self.build_names_index)) | 549 | logger.debug(3, ", ".join(self.build_targets)) |
656 | 550 | ||
657 | logger.debug(3, "run_names:") | 551 | logger.debug(3, "run_names:") |
658 | logger.debug(3, ", ".join(self.run_names_index)) | 552 | logger.debug(3, ", ".join(self.run_targets)) |
659 | 553 | ||
660 | logger.debug(3, "build_targets:") | 554 | logger.debug(3, "build_targets:") |
661 | for buildid in range(len(self.build_names_index)): | 555 | for target in self.build_targets: |
662 | target = self.build_names_index[buildid] | ||
663 | targets = "None" | 556 | targets = "None" |
664 | if buildid in self.build_targets: | 557 | if target in self.build_targets: |
665 | targets = self.build_targets[buildid] | 558 | targets = self.build_targets[target] |
666 | logger.debug(3, " (%s)%s: %s", buildid, target, targets) | 559 | logger.debug(3, " %s: %s", target, targets) |
667 | 560 | ||
668 | logger.debug(3, "run_targets:") | 561 | logger.debug(3, "run_targets:") |
669 | for runid in range(len(self.run_names_index)): | 562 | for target in self.run_targets: |
670 | target = self.run_names_index[runid] | ||
671 | targets = "None" | 563 | targets = "None" |
672 | if runid in self.run_targets: | 564 | if target in self.run_targets: |
673 | targets = self.run_targets[runid] | 565 | targets = self.run_targets[target] |
674 | logger.debug(3, " (%s)%s: %s", runid, target, targets) | 566 | logger.debug(3, " %s: %s", target, targets) |
675 | 567 | ||
676 | logger.debug(3, "tasks:") | 568 | logger.debug(3, "tasks:") |
677 | for task in range(len(self.tasks_name)): | 569 | for tid in self.taskentries: |
678 | logger.debug(3, " (%s)%s - %s: %s", | 570 | logger.debug(3, " %s: %s %s %s", |
679 | task, | 571 | tid, |
680 | self.fn_index[self.tasks_fnid[task]], | 572 | self.taskentries[tid].idepends, |
681 | self.tasks_name[task], | 573 | self.taskentries[tid].irdepends, |
682 | self.tasks_tdepends[task]) | 574 | self.taskentries[tid].tdepends) |
683 | 575 | ||
684 | logger.debug(3, "dependency ids (per fn):") | 576 | logger.debug(3, "dependency ids (per fn):") |
685 | for fnid in self.depids: | 577 | for fn in self.depids: |
686 | logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.depids[fnid]) | 578 | logger.debug(3, " %s: %s", fn, self.depids[fn]) |
687 | 579 | ||
688 | logger.debug(3, "runtime dependency ids (per fn):") | 580 | logger.debug(3, "runtime dependency ids (per fn):") |
689 | for fnid in self.rdepids: | 581 | for fn in self.rdepids: |
690 | logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.rdepids[fnid]) | 582 | logger.debug(3, " %s: %s", fn, self.rdepids[fn]) |