summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/taskdata.py
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2016-06-12 23:55:48 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-06-15 08:35:07 +0100
commitaf04a52bf7d7ae94c187e85028a80dee6d7853f0 (patch)
treed0c65de172d7ded2e1ba28f09c271da97e10cbe9 /bitbake/lib/bb/taskdata.py
parent29b4fb17966bfaec74b41cce533725c04ec1078f (diff)
downloadpoky-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.py412
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
40class TaskEntry:
41 def __init__(self):
42 self.tdepends = []
43 self.idepends = []
44 self.irdepends = []
45
40class TaskData: 46class 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])