taskdata.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. #!/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. """
  5. BitBake 'TaskData' implementation
  6. Task data collection and handling
  7. """
  8. # Copyright (C) 2006 Richard Purdie
  9. #
  10. # This program is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License version 2 as
  12. # published by the Free Software Foundation.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License along
  20. # with this program; if not, write to the Free Software Foundation, Inc.,
  21. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22. import logging
  23. import re
  24. import bb
  25. logger = logging.getLogger("BitBake.TaskData")
  26. def re_match_strings(target, strings):
  27. """
  28. Whether or not the string 'target' matches
  29. any one string of the strings which can be regular expression string
  30. """
  31. return any(name == target or re.match(name, target)
  32. for name in strings)
  33. class TaskData:
  34. """
  35. BitBake Task Data implementation
  36. """
  37. def __init__(self, abort = True, tryaltconfigs = False, skiplist = None, allowincomplete = False):
  38. self.build_names_index = []
  39. self.run_names_index = []
  40. self.fn_index = []
  41. self.build_targets = {}
  42. self.run_targets = {}
  43. self.external_targets = []
  44. self.tasks_fnid = []
  45. self.tasks_name = []
  46. self.tasks_tdepends = []
  47. self.tasks_idepends = []
  48. self.tasks_irdepends = []
  49. # Cache to speed up task ID lookups
  50. self.tasks_lookup = {}
  51. self.depids = {}
  52. self.rdepids = {}
  53. self.consider_msgs_cache = []
  54. self.failed_deps = []
  55. self.failed_rdeps = []
  56. self.failed_fnids = []
  57. self.abort = abort
  58. self.tryaltconfigs = tryaltconfigs
  59. self.allowincomplete = allowincomplete
  60. self.skiplist = skiplist
  61. def getbuild_id(self, name):
  62. """
  63. Return an ID number for the build target name.
  64. If it doesn't exist, create one.
  65. """
  66. if not name in self.build_names_index:
  67. self.build_names_index.append(name)
  68. return len(self.build_names_index) - 1
  69. return self.build_names_index.index(name)
  70. def getrun_id(self, name):
  71. """
  72. Return an ID number for the run target name.
  73. If it doesn't exist, create one.
  74. """
  75. if not name in self.run_names_index:
  76. self.run_names_index.append(name)
  77. return len(self.run_names_index) - 1
  78. return self.run_names_index.index(name)
  79. def getfn_id(self, name):
  80. """
  81. Return an ID number for the filename.
  82. If it doesn't exist, create one.
  83. """
  84. if not name in self.fn_index:
  85. self.fn_index.append(name)
  86. return len(self.fn_index) - 1
  87. return self.fn_index.index(name)
  88. def gettask_ids(self, fnid):
  89. """
  90. Return an array of the ID numbers matching a given fnid.
  91. """
  92. ids = []
  93. if fnid in self.tasks_lookup:
  94. for task in self.tasks_lookup[fnid]:
  95. ids.append(self.tasks_lookup[fnid][task])
  96. return ids
  97. def gettask_id_fromfnid(self, fnid, task):
  98. """
  99. Return an ID number for the task matching fnid and task.
  100. """
  101. if fnid in self.tasks_lookup:
  102. if task in self.tasks_lookup[fnid]:
  103. return self.tasks_lookup[fnid][task]
  104. return None
  105. def gettask_id(self, fn, task, create = True):
  106. """
  107. Return an ID number for the task matching fn and task.
  108. If it doesn't exist, create one by default.
  109. Optionally return None instead.
  110. """
  111. fnid = self.getfn_id(fn)
  112. if fnid in self.tasks_lookup:
  113. if task in self.tasks_lookup[fnid]:
  114. return self.tasks_lookup[fnid][task]
  115. if not create:
  116. return None
  117. self.tasks_name.append(task)
  118. self.tasks_fnid.append(fnid)
  119. self.tasks_tdepends.append([])
  120. self.tasks_idepends.append([])
  121. self.tasks_irdepends.append([])
  122. listid = len(self.tasks_name) - 1
  123. if fnid not in self.tasks_lookup:
  124. self.tasks_lookup[fnid] = {}
  125. self.tasks_lookup[fnid][task] = listid
  126. return listid
  127. def add_tasks(self, fn, dataCache):
  128. """
  129. Add tasks for a given fn to the database
  130. """
  131. task_deps = dataCache.task_deps[fn]
  132. fnid = self.getfn_id(fn)
  133. if fnid in self.failed_fnids:
  134. bb.msg.fatal("TaskData", "Trying to re-add a failed file? Something is broken...")
  135. # Check if we've already seen this fn
  136. if fnid in self.tasks_fnid:
  137. return
  138. self.add_extra_deps(fn, dataCache)
  139. for task in task_deps['tasks']:
  140. # Work out task dependencies
  141. parentids = []
  142. for dep in task_deps['parents'][task]:
  143. if dep not in task_deps['tasks']:
  144. bb.debug(2, "Not adding dependeny of %s on %s since %s does not exist" % (task, dep, dep))
  145. continue
  146. parentid = self.gettask_id(fn, dep)
  147. parentids.append(parentid)
  148. taskid = self.gettask_id(fn, task)
  149. self.tasks_tdepends[taskid].extend(parentids)
  150. # Touch all intertask dependencies
  151. if 'depends' in task_deps and task in task_deps['depends']:
  152. ids = []
  153. for dep in task_deps['depends'][task].split():
  154. if dep:
  155. if ":" not in dep:
  156. 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))
  157. ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1]))
  158. self.tasks_idepends[taskid].extend(ids)
  159. if 'rdepends' in task_deps and task in task_deps['rdepends']:
  160. ids = []
  161. for dep in task_deps['rdepends'][task].split():
  162. if dep:
  163. if ":" not in dep:
  164. 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))
  165. ids.append(((self.getrun_id(dep.split(":")[0])), dep.split(":")[1]))
  166. self.tasks_irdepends[taskid].extend(ids)
  167. # Work out build dependencies
  168. if not fnid in self.depids:
  169. dependids = {}
  170. for depend in dataCache.deps[fn]:
  171. dependids[self.getbuild_id(depend)] = None
  172. self.depids[fnid] = dependids.keys()
  173. logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn)
  174. # Work out runtime dependencies
  175. if not fnid in self.rdepids:
  176. rdependids = {}
  177. rdepends = dataCache.rundeps[fn]
  178. rrecs = dataCache.runrecs[fn]
  179. rdependlist = []
  180. rreclist = []
  181. for package in rdepends:
  182. for rdepend in rdepends[package]:
  183. rdependlist.append(rdepend)
  184. rdependids[self.getrun_id(rdepend)] = None
  185. for package in rrecs:
  186. for rdepend in rrecs[package]:
  187. rreclist.append(rdepend)
  188. rdependids[self.getrun_id(rdepend)] = None
  189. if rdependlist:
  190. logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn)
  191. if rreclist:
  192. logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn)
  193. self.rdepids[fnid] = rdependids.keys()
  194. for dep in self.depids[fnid]:
  195. if dep in self.failed_deps:
  196. self.fail_fnid(fnid)
  197. return
  198. for dep in self.rdepids[fnid]:
  199. if dep in self.failed_rdeps:
  200. self.fail_fnid(fnid)
  201. return
  202. def add_extra_deps(self, fn, dataCache):
  203. func = dataCache.extradepsfunc.get(fn, None)
  204. if func:
  205. bb.providers.buildWorldTargetList(dataCache)
  206. pn = dataCache.pkg_fn[fn]
  207. params = {'deps': dataCache.deps[fn],
  208. 'world_target': dataCache.world_target,
  209. 'pkg_pn': dataCache.pkg_pn,
  210. 'self_pn': pn}
  211. funcname = '_%s_calculate_extra_depends' % pn.replace('-', '_')
  212. paramlist = ','.join(params.keys())
  213. func = 'def %s(%s):\n%s\n\n%s(%s)' % (funcname, paramlist, func, funcname, paramlist)
  214. bb.utils.better_exec(func, params)
  215. def have_build_target(self, target):
  216. """
  217. Have we a build target matching this name?
  218. """
  219. targetid = self.getbuild_id(target)
  220. if targetid in self.build_targets:
  221. return True
  222. return False
  223. def have_runtime_target(self, target):
  224. """
  225. Have we a runtime target matching this name?
  226. """
  227. targetid = self.getrun_id(target)
  228. if targetid in self.run_targets:
  229. return True
  230. return False
  231. def add_build_target(self, fn, item):
  232. """
  233. Add a build target.
  234. If already present, append the provider fn to the list
  235. """
  236. targetid = self.getbuild_id(item)
  237. fnid = self.getfn_id(fn)
  238. if targetid in self.build_targets:
  239. if fnid in self.build_targets[targetid]:
  240. return
  241. self.build_targets[targetid].append(fnid)
  242. return
  243. self.build_targets[targetid] = [fnid]
  244. def add_runtime_target(self, fn, item):
  245. """
  246. Add a runtime target.
  247. If already present, append the provider fn to the list
  248. """
  249. targetid = self.getrun_id(item)
  250. fnid = self.getfn_id(fn)
  251. if targetid in self.run_targets:
  252. if fnid in self.run_targets[targetid]:
  253. return
  254. self.run_targets[targetid].append(fnid)
  255. return
  256. self.run_targets[targetid] = [fnid]
  257. def mark_external_target(self, item):
  258. """
  259. Mark a build target as being externally requested
  260. """
  261. targetid = self.getbuild_id(item)
  262. if targetid not in self.external_targets:
  263. self.external_targets.append(targetid)
  264. def get_unresolved_build_targets(self, dataCache):
  265. """
  266. Return a list of build targets who's providers
  267. are unknown.
  268. """
  269. unresolved = []
  270. for target in self.build_names_index:
  271. if re_match_strings(target, dataCache.ignored_dependencies):
  272. continue
  273. if self.build_names_index.index(target) in self.failed_deps:
  274. continue
  275. if not self.have_build_target(target):
  276. unresolved.append(target)
  277. return unresolved
  278. def get_unresolved_run_targets(self, dataCache):
  279. """
  280. Return a list of runtime targets who's providers
  281. are unknown.
  282. """
  283. unresolved = []
  284. for target in self.run_names_index:
  285. if re_match_strings(target, dataCache.ignored_dependencies):
  286. continue
  287. if self.run_names_index.index(target) in self.failed_rdeps:
  288. continue
  289. if not self.have_runtime_target(target):
  290. unresolved.append(target)
  291. return unresolved
  292. def get_provider(self, item):
  293. """
  294. Return a list of providers of item
  295. """
  296. targetid = self.getbuild_id(item)
  297. return self.build_targets[targetid]
  298. def get_dependees(self, itemid):
  299. """
  300. Return a list of targets which depend on item
  301. """
  302. dependees = []
  303. for fnid in self.depids:
  304. if itemid in self.depids[fnid]:
  305. dependees.append(fnid)
  306. return dependees
  307. def get_dependees_str(self, item):
  308. """
  309. Return a list of targets which depend on item as a user readable string
  310. """
  311. itemid = self.getbuild_id(item)
  312. dependees = []
  313. for fnid in self.depids:
  314. if itemid in self.depids[fnid]:
  315. dependees.append(self.fn_index[fnid])
  316. return dependees
  317. def get_rdependees(self, itemid):
  318. """
  319. Return a list of targets which depend on runtime item
  320. """
  321. dependees = []
  322. for fnid in self.rdepids:
  323. if itemid in self.rdepids[fnid]:
  324. dependees.append(fnid)
  325. return dependees
  326. def get_rdependees_str(self, item):
  327. """
  328. Return a list of targets which depend on runtime item as a user readable string
  329. """
  330. itemid = self.getrun_id(item)
  331. dependees = []
  332. for fnid in self.rdepids:
  333. if itemid in self.rdepids[fnid]:
  334. dependees.append(self.fn_index[fnid])
  335. return dependees
  336. def get_reasons(self, item, runtime=False):
  337. """
  338. Get the reason(s) for an item not being provided, if any
  339. """
  340. reasons = []
  341. if self.skiplist:
  342. for fn in self.skiplist:
  343. skipitem = self.skiplist[fn]
  344. if skipitem.pn == item:
  345. reasons.append("%s was skipped: %s" % (skipitem.pn, skipitem.skipreason))
  346. elif runtime and item in skipitem.rprovides:
  347. reasons.append("%s RPROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
  348. elif not runtime and item in skipitem.provides:
  349. reasons.append("%s PROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
  350. return reasons
  351. def get_close_matches(self, item, provider_list):
  352. import difflib
  353. if self.skiplist:
  354. skipped = []
  355. for fn in self.skiplist:
  356. skipped.append(self.skiplist[fn].pn)
  357. full_list = provider_list + skipped
  358. else:
  359. full_list = provider_list
  360. return difflib.get_close_matches(item, full_list, cutoff=0.7)
  361. def add_provider(self, cfgData, dataCache, item):
  362. try:
  363. self.add_provider_internal(cfgData, dataCache, item)
  364. except bb.providers.NoProvider:
  365. if self.abort:
  366. raise
  367. self.remove_buildtarget(self.getbuild_id(item))
  368. self.mark_external_target(item)
  369. def add_provider_internal(self, cfgData, dataCache, item):
  370. """
  371. Add the providers of item to the task data
  372. Mark entries were specifically added externally as against dependencies
  373. added internally during dependency resolution
  374. """
  375. if re_match_strings(item, dataCache.ignored_dependencies):
  376. return
  377. if not item in dataCache.providers:
  378. close_matches = self.get_close_matches(item, list(dataCache.providers.keys()))
  379. # Is it in RuntimeProviders ?
  380. all_p = bb.providers.getRuntimeProviders(dataCache, item)
  381. for fn in all_p:
  382. new = dataCache.pkg_fn[fn] + " RPROVIDES " + item
  383. if new not in close_matches:
  384. close_matches.append(new)
  385. bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData)
  386. raise bb.providers.NoProvider(item)
  387. if self.have_build_target(item):
  388. return
  389. all_p = dataCache.providers[item]
  390. eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache)
  391. eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
  392. if not eligible:
  393. bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=["No eligible PROVIDERs exist for '%s'" % item]), cfgData)
  394. raise bb.providers.NoProvider(item)
  395. if len(eligible) > 1 and foundUnique == False:
  396. if item not in self.consider_msgs_cache:
  397. providers_list = []
  398. for fn in eligible:
  399. providers_list.append(dataCache.pkg_fn[fn])
  400. bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
  401. self.consider_msgs_cache.append(item)
  402. for fn in eligible:
  403. fnid = self.getfn_id(fn)
  404. if fnid in self.failed_fnids:
  405. continue
  406. logger.debug(2, "adding %s to satisfy %s", fn, item)
  407. self.add_build_target(fn, item)
  408. self.add_tasks(fn, dataCache)
  409. #item = dataCache.pkg_fn[fn]
  410. def add_rprovider(self, cfgData, dataCache, item):
  411. """
  412. Add the runtime providers of item to the task data
  413. (takes item names from RDEPENDS/PACKAGES namespace)
  414. """
  415. if re_match_strings(item, dataCache.ignored_dependencies):
  416. return
  417. if self.have_runtime_target(item):
  418. return
  419. all_p = bb.providers.getRuntimeProviders(dataCache, item)
  420. if not all_p:
  421. bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=self.get_reasons(item, True)), cfgData)
  422. raise bb.providers.NoRProvider(item)
  423. eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
  424. eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
  425. if not eligible:
  426. bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=["No eligible RPROVIDERs exist for '%s'" % item]), cfgData)
  427. raise bb.providers.NoRProvider(item)
  428. if len(eligible) > 1 and numberPreferred == 0:
  429. if item not in self.consider_msgs_cache:
  430. providers_list = []
  431. for fn in eligible:
  432. providers_list.append(dataCache.pkg_fn[fn])
  433. bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
  434. self.consider_msgs_cache.append(item)
  435. if numberPreferred > 1:
  436. if item not in self.consider_msgs_cache:
  437. providers_list = []
  438. for fn in eligible:
  439. providers_list.append(dataCache.pkg_fn[fn])
  440. bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
  441. self.consider_msgs_cache.append(item)
  442. raise bb.providers.MultipleRProvider(item)
  443. # run through the list until we find one that we can build
  444. for fn in eligible:
  445. fnid = self.getfn_id(fn)
  446. if fnid in self.failed_fnids:
  447. continue
  448. logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item)
  449. self.add_runtime_target(fn, item)
  450. self.add_tasks(fn, dataCache)
  451. def fail_fnid(self, fnid, missing_list=None):
  452. """
  453. Mark a file as failed (unbuildable)
  454. Remove any references from build and runtime provider lists
  455. missing_list, A list of missing requirements for this target
  456. """
  457. if fnid in self.failed_fnids:
  458. return
  459. if not missing_list:
  460. missing_list = []
  461. logger.debug(1, "File '%s' is unbuildable, removing...", self.fn_index[fnid])
  462. self.failed_fnids.append(fnid)
  463. for target in self.build_targets:
  464. if fnid in self.build_targets[target]:
  465. self.build_targets[target].remove(fnid)
  466. if len(self.build_targets[target]) == 0:
  467. self.remove_buildtarget(target, missing_list)
  468. for target in self.run_targets:
  469. if fnid in self.run_targets[target]:
  470. self.run_targets[target].remove(fnid)
  471. if len(self.run_targets[target]) == 0:
  472. self.remove_runtarget(target, missing_list)
  473. def remove_buildtarget(self, targetid, missing_list=None):
  474. """
  475. Mark a build target as failed (unbuildable)
  476. Trigger removal of any files that have this as a dependency
  477. """
  478. if not missing_list:
  479. missing_list = [self.build_names_index[targetid]]
  480. else:
  481. missing_list = [self.build_names_index[targetid]] + missing_list
  482. logger.verbose("Target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.build_names_index[targetid], missing_list)
  483. self.failed_deps.append(targetid)
  484. dependees = self.get_dependees(targetid)
  485. for fnid in dependees:
  486. self.fail_fnid(fnid, missing_list)
  487. for taskid in range(len(self.tasks_idepends)):
  488. idepends = self.tasks_idepends[taskid]
  489. for (idependid, idependtask) in idepends:
  490. if idependid == targetid:
  491. self.fail_fnid(self.tasks_fnid[taskid], missing_list)
  492. if self.abort and targetid in self.external_targets:
  493. target = self.build_names_index[targetid]
  494. logger.error("Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s", target, missing_list)
  495. raise bb.providers.NoProvider(target)
  496. def remove_runtarget(self, targetid, missing_list=None):
  497. """
  498. Mark a run target as failed (unbuildable)
  499. Trigger removal of any files that have this as a dependency
  500. """
  501. if not missing_list:
  502. missing_list = [self.run_names_index[targetid]]
  503. else:
  504. missing_list = [self.run_names_index[targetid]] + missing_list
  505. logger.info("Runtime target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.run_names_index[targetid], missing_list)
  506. self.failed_rdeps.append(targetid)
  507. dependees = self.get_rdependees(targetid)
  508. for fnid in dependees:
  509. self.fail_fnid(fnid, missing_list)
  510. for taskid in range(len(self.tasks_irdepends)):
  511. irdepends = self.tasks_irdepends[taskid]
  512. for (idependid, idependtask) in irdepends:
  513. if idependid == targetid:
  514. self.fail_fnid(self.tasks_fnid[taskid], missing_list)
  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:
  527. targetid = self.getbuild_id(target)
  528. if self.abort and targetid in self.external_targets and not self.allowincomplete:
  529. raise
  530. if not self.allowincomplete:
  531. self.remove_buildtarget(targetid)
  532. for target in self.get_unresolved_run_targets(dataCache):
  533. try:
  534. self.add_rprovider(cfgData, dataCache, target)
  535. added = added + 1
  536. except (bb.providers.NoRProvider, bb.providers.MultipleRProvider):
  537. self.remove_runtarget(self.getrun_id(target))
  538. logger.debug(1, "Resolved " + str(added) + " extra dependencies")
  539. if added == 0:
  540. break
  541. # self.dump_data()
  542. def get_providermap(self, prefix=None):
  543. provmap = {}
  544. for name in self.build_names_index:
  545. 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:
  550. provmap[name] = self.fn_index[provider[0]]
  551. return provmap
  552. def dump_data(self):
  553. """
  554. Dump some debug information on the internal data structures
  555. """
  556. logger.debug(3, "build_names:")
  557. logger.debug(3, ", ".join(self.build_names_index))
  558. logger.debug(3, "run_names:")
  559. logger.debug(3, ", ".join(self.run_names_index))
  560. logger.debug(3, "build_targets:")
  561. for buildid in range(len(self.build_names_index)):
  562. target = self.build_names_index[buildid]
  563. targets = "None"
  564. if buildid in self.build_targets:
  565. targets = self.build_targets[buildid]
  566. logger.debug(3, " (%s)%s: %s", buildid, target, targets)
  567. logger.debug(3, "run_targets:")
  568. for runid in range(len(self.run_names_index)):
  569. target = self.run_names_index[runid]
  570. targets = "None"
  571. if runid in self.run_targets:
  572. targets = self.run_targets[runid]
  573. logger.debug(3, " (%s)%s: %s", runid, target, targets)
  574. logger.debug(3, "tasks:")
  575. for task in range(len(self.tasks_name)):
  576. logger.debug(3, " (%s)%s - %s: %s",
  577. task,
  578. self.fn_index[self.tasks_fnid[task]],
  579. self.tasks_name[task],
  580. self.tasks_tdepends[task])
  581. logger.debug(3, "dependency ids (per fn):")
  582. for fnid in self.depids:
  583. logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.depids[fnid])
  584. logger.debug(3, "runtime dependency ids (per fn):")
  585. for fnid in self.rdepids:
  586. logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.rdepids[fnid])