blob: 94e822c485f35002d89493cedb57ef8b2276d47f [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#!/usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4"""
5BitBake 'TaskData' implementation
6
7Task data collection and handling
8
9"""
10
11# Copyright (C) 2006 Richard Purdie
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26import logging
27import re
28import bb
29
30logger = logging.getLogger("BitBake.TaskData")
31
32def re_match_strings(target, strings):
33 """
34 Whether or not the string 'target' matches
35 any one string of the strings which can be regular expression string
36 """
37 return any(name == target or re.match(name, target)
38 for name in strings)
39
Patrick Williamsc0f7c042017-02-23 20:41:17 -060040class TaskEntry:
41 def __init__(self):
42 self.tdepends = []
43 self.idepends = []
44 self.irdepends = []
45
Patrick Williamsc124f4f2015-09-15 14:41:29 -050046class TaskData:
47 """
48 BitBake Task Data implementation
49 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -050050 def __init__(self, abort = True, skiplist = None, allowincomplete = False):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051 self.build_targets = {}
52 self.run_targets = {}
53
54 self.external_targets = []
55
Patrick Williamsc0f7c042017-02-23 20:41:17 -060056 self.seenfns = []
57 self.taskentries = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
59 self.depids = {}
60 self.rdepids = {}
61
62 self.consider_msgs_cache = []
63
64 self.failed_deps = []
65 self.failed_rdeps = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -060066 self.failed_fns = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067
68 self.abort = abort
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069 self.allowincomplete = allowincomplete
70
71 self.skiplist = skiplist
72
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080073 self.mcdepends = []
74
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075 def add_tasks(self, fn, dataCache):
76 """
77 Add tasks for a given fn to the database
78 """
79
80 task_deps = dataCache.task_deps[fn]
81
Patrick Williamsc0f7c042017-02-23 20:41:17 -060082 if fn in self.failed_fns:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083 bb.msg.fatal("TaskData", "Trying to re-add a failed file? Something is broken...")
84
85 # Check if we've already seen this fn
Patrick Williamsc0f7c042017-02-23 20:41:17 -060086 if fn in self.seenfns:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087 return
88
Patrick Williamsc0f7c042017-02-23 20:41:17 -060089 self.seenfns.append(fn)
90
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050091 self.add_extra_deps(fn, dataCache)
92
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080093 def add_mcdepends(task):
94 for dep in task_deps['mcdepends'][task].split():
95 if len(dep.split(':')) != 5:
96 bb.msg.fatal("TaskData", "Error for %s:%s[%s], multiconfig dependency %s does not contain exactly four ':' characters.\n Task '%s' should be specified in the form 'multiconfig:fromMC:toMC:packagename:task'" % (fn, task, 'mcdepends', dep, 'mcdepends'))
97 if dep not in self.mcdepends:
98 self.mcdepends.append(dep)
99
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500100 # Common code for dep_name/depends = 'depends'/idepends and 'rdepends'/irdepends
101 def handle_deps(task, dep_name, depends, seen):
102 if dep_name in task_deps and task in task_deps[dep_name]:
103 ids = []
104 for dep in task_deps[dep_name][task].split():
105 if dep:
106 parts = dep.split(":")
107 if len(parts) != 2:
108 bb.msg.fatal("TaskData", "Error for %s:%s[%s], dependency %s in '%s' does not contain exactly one ':' character.\n Task '%s' should be specified in the form 'packagename:task'" % (fn, task, dep_name, dep, task_deps[dep_name][task], dep_name))
109 ids.append((parts[0], parts[1]))
110 seen(parts[0])
111 depends.extend(ids)
112
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113 for task in task_deps['tasks']:
114
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600115 tid = "%s:%s" % (fn, task)
116 self.taskentries[tid] = TaskEntry()
117
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500118 # Work out task dependencies
119 parentids = []
120 for dep in task_deps['parents'][task]:
121 if dep not in task_deps['tasks']:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800122 bb.debug(2, "Not adding dependency of %s on %s since %s does not exist" % (task, dep, dep))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500123 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600124 parentid = "%s:%s" % (fn, dep)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500125 parentids.append(parentid)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600126 self.taskentries[tid].tdepends.extend(parentids)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800128
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 # Touch all intertask dependencies
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500130 handle_deps(task, 'depends', self.taskentries[tid].idepends, self.seen_build_target)
131 handle_deps(task, 'rdepends', self.taskentries[tid].irdepends, self.seen_run_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800133 if 'mcdepends' in task_deps and task in task_deps['mcdepends']:
134 add_mcdepends(task)
135
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500136 # Work out build dependencies
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600137 if not fn in self.depids:
138 dependids = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139 for depend in dataCache.deps[fn]:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600140 dependids.add(depend)
141 self.depids[fn] = list(dependids)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142 logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn)
143
144 # Work out runtime dependencies
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600145 if not fn in self.rdepids:
146 rdependids = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500147 rdepends = dataCache.rundeps[fn]
148 rrecs = dataCache.runrecs[fn]
149 rdependlist = []
150 rreclist = []
151 for package in rdepends:
152 for rdepend in rdepends[package]:
153 rdependlist.append(rdepend)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600154 rdependids.add(rdepend)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155 for package in rrecs:
156 for rdepend in rrecs[package]:
157 rreclist.append(rdepend)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600158 rdependids.add(rdepend)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500159 if rdependlist:
160 logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn)
161 if rreclist:
162 logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600163 self.rdepids[fn] = list(rdependids)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500164
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600165 for dep in self.depids[fn]:
166 self.seen_build_target(dep)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500167 if dep in self.failed_deps:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600168 self.fail_fn(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500169 return
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600170 for dep in self.rdepids[fn]:
171 self.seen_run_target(dep)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500172 if dep in self.failed_rdeps:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600173 self.fail_fn(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174 return
175
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500176 def add_extra_deps(self, fn, dataCache):
177 func = dataCache.extradepsfunc.get(fn, None)
178 if func:
179 bb.providers.buildWorldTargetList(dataCache)
180 pn = dataCache.pkg_fn[fn]
181 params = {'deps': dataCache.deps[fn],
182 'world_target': dataCache.world_target,
183 'pkg_pn': dataCache.pkg_pn,
184 'self_pn': pn}
185 funcname = '_%s_calculate_extra_depends' % pn.replace('-', '_')
186 paramlist = ','.join(params.keys())
187 func = 'def %s(%s):\n%s\n\n%s(%s)' % (funcname, paramlist, func, funcname, paramlist)
188 bb.utils.better_exec(func, params)
189
190
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500191 def have_build_target(self, target):
192 """
193 Have we a build target matching this name?
194 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600195 if target in self.build_targets and self.build_targets[target]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196 return True
197 return False
198
199 def have_runtime_target(self, target):
200 """
201 Have we a runtime target matching this name?
202 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600203 if target in self.run_targets and self.run_targets[target]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500204 return True
205 return False
206
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600207 def seen_build_target(self, name):
208 """
209 Maintain a list of build targets
210 """
211 if name not in self.build_targets:
212 self.build_targets[name] = []
213
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500214 def add_build_target(self, fn, item):
215 """
216 Add a build target.
217 If already present, append the provider fn to the list
218 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600219 if item in self.build_targets:
220 if fn in self.build_targets[item]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 return
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600222 self.build_targets[item].append(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 return
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600224 self.build_targets[item] = [fn]
225
226 def seen_run_target(self, name):
227 """
228 Maintain a list of runtime build targets
229 """
230 if name not in self.run_targets:
231 self.run_targets[name] = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500232
233 def add_runtime_target(self, fn, item):
234 """
235 Add a runtime target.
236 If already present, append the provider fn to the list
237 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600238 if item in self.run_targets:
239 if fn in self.run_targets[item]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500240 return
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600241 self.run_targets[item].append(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500242 return
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600243 self.run_targets[item] = [fn]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500244
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600245 def mark_external_target(self, target):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500246 """
247 Mark a build target as being externally requested
248 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600249 if target not in self.external_targets:
250 self.external_targets.append(target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251
252 def get_unresolved_build_targets(self, dataCache):
253 """
254 Return a list of build targets who's providers
255 are unknown.
256 """
257 unresolved = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600258 for target in self.build_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500259 if re_match_strings(target, dataCache.ignored_dependencies):
260 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600261 if target in self.failed_deps:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500262 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600263 if not self.build_targets[target]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500264 unresolved.append(target)
265 return unresolved
266
267 def get_unresolved_run_targets(self, dataCache):
268 """
269 Return a list of runtime targets who's providers
270 are unknown.
271 """
272 unresolved = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600273 for target in self.run_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500274 if re_match_strings(target, dataCache.ignored_dependencies):
275 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600276 if target in self.failed_rdeps:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500277 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600278 if not self.run_targets[target]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500279 unresolved.append(target)
280 return unresolved
281
282 def get_provider(self, item):
283 """
284 Return a list of providers of item
285 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600286 return self.build_targets[item]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500287
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600288 def get_dependees(self, item):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 """
290 Return a list of targets which depend on item
291 """
292 dependees = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600293 for fn in self.depids:
294 if item in self.depids[fn]:
295 dependees.append(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500296 return dependees
297
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600298 def get_rdependees(self, item):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500299 """
300 Return a list of targets which depend on runtime item
301 """
302 dependees = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600303 for fn in self.rdepids:
304 if item in self.rdepids[fn]:
305 dependees.append(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500306 return dependees
307
308 def get_reasons(self, item, runtime=False):
309 """
310 Get the reason(s) for an item not being provided, if any
311 """
312 reasons = []
313 if self.skiplist:
314 for fn in self.skiplist:
315 skipitem = self.skiplist[fn]
316 if skipitem.pn == item:
317 reasons.append("%s was skipped: %s" % (skipitem.pn, skipitem.skipreason))
318 elif runtime and item in skipitem.rprovides:
319 reasons.append("%s RPROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
320 elif not runtime and item in skipitem.provides:
321 reasons.append("%s PROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
322 return reasons
323
324 def get_close_matches(self, item, provider_list):
325 import difflib
326 if self.skiplist:
327 skipped = []
328 for fn in self.skiplist:
329 skipped.append(self.skiplist[fn].pn)
330 full_list = provider_list + skipped
331 else:
332 full_list = provider_list
333 return difflib.get_close_matches(item, full_list, cutoff=0.7)
334
335 def add_provider(self, cfgData, dataCache, item):
336 try:
337 self.add_provider_internal(cfgData, dataCache, item)
338 except bb.providers.NoProvider:
339 if self.abort:
340 raise
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600341 self.remove_buildtarget(item)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342
343 self.mark_external_target(item)
344
345 def add_provider_internal(self, cfgData, dataCache, item):
346 """
347 Add the providers of item to the task data
348 Mark entries were specifically added externally as against dependencies
349 added internally during dependency resolution
350 """
351
352 if re_match_strings(item, dataCache.ignored_dependencies):
353 return
354
355 if not item in dataCache.providers:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600356 close_matches = self.get_close_matches(item, list(dataCache.providers.keys()))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500357 # Is it in RuntimeProviders ?
358 all_p = bb.providers.getRuntimeProviders(dataCache, item)
359 for fn in all_p:
360 new = dataCache.pkg_fn[fn] + " RPROVIDES " + item
361 if new not in close_matches:
362 close_matches.append(new)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600363 bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500364 raise bb.providers.NoProvider(item)
365
366 if self.have_build_target(item):
367 return
368
369 all_p = dataCache.providers[item]
370
371 eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600372 eligible = [p for p in eligible if not p in self.failed_fns]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500373
374 if not eligible:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600375 bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees(item), reasons=["No eligible PROVIDERs exist for '%s'" % item]), cfgData)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376 raise bb.providers.NoProvider(item)
377
378 if len(eligible) > 1 and foundUnique == False:
379 if item not in self.consider_msgs_cache:
380 providers_list = []
381 for fn in eligible:
382 providers_list.append(dataCache.pkg_fn[fn])
383 bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
384 self.consider_msgs_cache.append(item)
385
386 for fn in eligible:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600387 if fn in self.failed_fns:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500388 continue
389 logger.debug(2, "adding %s to satisfy %s", fn, item)
390 self.add_build_target(fn, item)
391 self.add_tasks(fn, dataCache)
392
393
394 #item = dataCache.pkg_fn[fn]
395
396 def add_rprovider(self, cfgData, dataCache, item):
397 """
398 Add the runtime providers of item to the task data
399 (takes item names from RDEPENDS/PACKAGES namespace)
400 """
401
402 if re_match_strings(item, dataCache.ignored_dependencies):
403 return
404
405 if self.have_runtime_target(item):
406 return
407
408 all_p = bb.providers.getRuntimeProviders(dataCache, item)
409
410 if not all_p:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600411 bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees(item), reasons=self.get_reasons(item, True)), cfgData)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412 raise bb.providers.NoRProvider(item)
413
414 eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600415 eligible = [p for p in eligible if not p in self.failed_fns]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500416
417 if not eligible:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600418 bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees(item), reasons=["No eligible RPROVIDERs exist for '%s'" % item]), cfgData)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500419 raise bb.providers.NoRProvider(item)
420
421 if len(eligible) > 1 and numberPreferred == 0:
422 if item not in self.consider_msgs_cache:
423 providers_list = []
424 for fn in eligible:
425 providers_list.append(dataCache.pkg_fn[fn])
426 bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
427 self.consider_msgs_cache.append(item)
428
429 if numberPreferred > 1:
430 if item not in self.consider_msgs_cache:
431 providers_list = []
432 for fn in eligible:
433 providers_list.append(dataCache.pkg_fn[fn])
434 bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
435 self.consider_msgs_cache.append(item)
436 raise bb.providers.MultipleRProvider(item)
437
438 # run through the list until we find one that we can build
439 for fn in eligible:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600440 if fn in self.failed_fns:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500441 continue
442 logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item)
443 self.add_runtime_target(fn, item)
444 self.add_tasks(fn, dataCache)
445
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600446 def fail_fn(self, fn, missing_list=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500447 """
448 Mark a file as failed (unbuildable)
449 Remove any references from build and runtime provider lists
450
451 missing_list, A list of missing requirements for this target
452 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600453 if fn in self.failed_fns:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500454 return
455 if not missing_list:
456 missing_list = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600457 logger.debug(1, "File '%s' is unbuildable, removing...", fn)
458 self.failed_fns.append(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 for target in self.build_targets:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600460 if fn in self.build_targets[target]:
461 self.build_targets[target].remove(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500462 if len(self.build_targets[target]) == 0:
463 self.remove_buildtarget(target, missing_list)
464 for target in self.run_targets:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600465 if fn in self.run_targets[target]:
466 self.run_targets[target].remove(fn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500467 if len(self.run_targets[target]) == 0:
468 self.remove_runtarget(target, missing_list)
469
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600470 def remove_buildtarget(self, target, missing_list=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500471 """
472 Mark a build target as failed (unbuildable)
473 Trigger removal of any files that have this as a dependency
474 """
475 if not missing_list:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600476 missing_list = [target]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500477 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600478 missing_list = [target] + missing_list
479 logger.verbose("Target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", target, missing_list)
480 self.failed_deps.append(target)
481 dependees = self.get_dependees(target)
482 for fn in dependees:
483 self.fail_fn(fn, missing_list)
484 for tid in self.taskentries:
485 for (idepend, idependtask) in self.taskentries[tid].idepends:
486 if idepend == target:
487 fn = tid.rsplit(":",1)[0]
488 self.fail_fn(fn, missing_list)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500489
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600490 if self.abort and target in self.external_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500491 logger.error("Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s", target, missing_list)
492 raise bb.providers.NoProvider(target)
493
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600494 def remove_runtarget(self, target, missing_list=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500495 """
496 Mark a run target as failed (unbuildable)
497 Trigger removal of any files that have this as a dependency
498 """
499 if not missing_list:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600500 missing_list = [target]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500501 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600502 missing_list = [target] + missing_list
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500503
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600504 logger.info("Runtime target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", target, missing_list)
505 self.failed_rdeps.append(target)
506 dependees = self.get_rdependees(target)
507 for fn in dependees:
508 self.fail_fn(fn, missing_list)
509 for tid in self.taskentries:
510 for (idepend, idependtask) in self.taskentries[tid].irdepends:
511 if idepend == target:
512 fn = tid.rsplit(":",1)[0]
513 self.fail_fn(fn, missing_list)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500514
515 def add_unresolved(self, cfgData, dataCache):
516 """
517 Resolve all unresolved build and runtime targets
518 """
519 logger.info("Resolving any missing task queue dependencies")
520 while True:
521 added = 0
522 for target in self.get_unresolved_build_targets(dataCache):
523 try:
524 self.add_provider_internal(cfgData, dataCache, target)
525 added = added + 1
526 except bb.providers.NoProvider:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600527 if self.abort and target in self.external_targets and not self.allowincomplete:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500528 raise
529 if not self.allowincomplete:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600530 self.remove_buildtarget(target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500531 for target in self.get_unresolved_run_targets(dataCache):
532 try:
533 self.add_rprovider(cfgData, dataCache, target)
534 added = added + 1
535 except (bb.providers.NoRProvider, bb.providers.MultipleRProvider):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600536 self.remove_runtarget(target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500537 logger.debug(1, "Resolved " + str(added) + " extra dependencies")
538 if added == 0:
539 break
540 # self.dump_data()
541
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500542 def get_providermap(self, prefix=None):
543 provmap = {}
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600544 for name in self.build_targets:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500545 if prefix and not name.startswith(prefix):
546 continue
547 if self.have_build_target(name):
548 provider = self.get_provider(name)
549 if provider:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600550 provmap[name] = provider[0]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500551 return provmap
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500552
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800553 def get_mcdepends(self):
554 return self.mcdepends
555
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500556 def dump_data(self):
557 """
558 Dump some debug information on the internal data structures
559 """
560 logger.debug(3, "build_names:")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600561 logger.debug(3, ", ".join(self.build_targets))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500562
563 logger.debug(3, "run_names:")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600564 logger.debug(3, ", ".join(self.run_targets))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500565
566 logger.debug(3, "build_targets:")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600567 for target in self.build_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500568 targets = "None"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600569 if target in self.build_targets:
570 targets = self.build_targets[target]
571 logger.debug(3, " %s: %s", target, targets)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500572
573 logger.debug(3, "run_targets:")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600574 for target in self.run_targets:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500575 targets = "None"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600576 if target in self.run_targets:
577 targets = self.run_targets[target]
578 logger.debug(3, " %s: %s", target, targets)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500579
580 logger.debug(3, "tasks:")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600581 for tid in self.taskentries:
582 logger.debug(3, " %s: %s %s %s",
583 tid,
584 self.taskentries[tid].idepends,
585 self.taskentries[tid].irdepends,
586 self.taskentries[tid].tdepends)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500587
588 logger.debug(3, "dependency ids (per fn):")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600589 for fn in self.depids:
590 logger.debug(3, " %s: %s", fn, self.depids[fn])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500591
592 logger.debug(3, "runtime dependency ids (per fn):")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600593 for fn in self.rdepids:
594 logger.debug(3, " %s: %s", fn, self.rdepids[fn])