taskdata.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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. for task in task_deps['tasks']:
  139. # Work out task dependencies
  140. parentids = []
  141. for dep in task_deps['parents'][task]:
  142. if dep not in task_deps['tasks']:
  143. bb.debug(2, "Not adding dependeny of %s on %s since %s does not exist" % (task, dep, dep))
  144. continue
  145. parentid = self.gettask_id(fn, dep)
  146. parentids.append(parentid)
  147. taskid = self.gettask_id(fn, task)
  148. self.tasks_tdepends[taskid].extend(parentids)
  149. # Touch all intertask dependencies
  150. if 'depends' in task_deps and task in task_deps['depends']:
  151. ids = []
  152. for dep in task_deps['depends'][task].split():
  153. if dep:
  154. if ":" not in dep:
  155. 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))
  156. ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1]))
  157. self.tasks_idepends[taskid].extend(ids)
  158. if 'rdepends' in task_deps and task in task_deps['rdepends']:
  159. ids = []
  160. for dep in task_deps['rdepends'][task].split():
  161. if dep:
  162. if ":" not in dep:
  163. 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))
  164. ids.append(((self.getrun_id(dep.split(":")[0])), dep.split(":")[1]))
  165. self.tasks_irdepends[taskid].extend(ids)
  166. # Work out build dependencies
  167. if not fnid in self.depids:
  168. dependids = {}
  169. for depend in dataCache.deps[fn]:
  170. dependids[self.getbuild_id(depend)] = None
  171. self.depids[fnid] = dependids.keys()
  172. logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn)
  173. # Work out runtime dependencies
  174. if not fnid in self.rdepids:
  175. rdependids = {}
  176. rdepends = dataCache.rundeps[fn]
  177. rrecs = dataCache.runrecs[fn]
  178. rdependlist = []
  179. rreclist = []
  180. for package in rdepends:
  181. for rdepend in rdepends[package]:
  182. rdependlist.append(rdepend)
  183. rdependids[self.getrun_id(rdepend)] = None
  184. for package in rrecs:
  185. for rdepend in rrecs[package]:
  186. rreclist.append(rdepend)
  187. rdependids[self.getrun_id(rdepend)] = None
  188. if rdependlist:
  189. logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn)
  190. if rreclist:
  191. logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn)
  192. self.rdepids[fnid] = rdependids.keys()
  193. for dep in self.depids[fnid]:
  194. if dep in self.failed_deps:
  195. self.fail_fnid(fnid)
  196. return
  197. for dep in self.rdepids[fnid]:
  198. if dep in self.failed_rdeps:
  199. self.fail_fnid(fnid)
  200. return
  201. def have_build_target(self, target):
  202. """
  203. Have we a build target matching this name?
  204. """
  205. targetid = self.getbuild_id(target)
  206. if targetid in self.build_targets:
  207. return True
  208. return False
  209. def have_runtime_target(self, target):
  210. """
  211. Have we a runtime target matching this name?
  212. """
  213. targetid = self.getrun_id(target)
  214. if targetid in self.run_targets:
  215. return True
  216. return False
  217. def add_build_target(self, fn, item):
  218. """
  219. Add a build target.
  220. If already present, append the provider fn to the list
  221. """
  222. targetid = self.getbuild_id(item)
  223. fnid = self.getfn_id(fn)
  224. if targetid in self.build_targets:
  225. if fnid in self.build_targets[targetid]:
  226. return
  227. self.build_targets[targetid].append(fnid)
  228. return
  229. self.build_targets[targetid] = [fnid]
  230. def add_runtime_target(self, fn, item):
  231. """
  232. Add a runtime target.
  233. If already present, append the provider fn to the list
  234. """
  235. targetid = self.getrun_id(item)
  236. fnid = self.getfn_id(fn)
  237. if targetid in self.run_targets:
  238. if fnid in self.run_targets[targetid]:
  239. return
  240. self.run_targets[targetid].append(fnid)
  241. return
  242. self.run_targets[targetid] = [fnid]
  243. def mark_external_target(self, item):
  244. """
  245. Mark a build target as being externally requested
  246. """
  247. targetid = self.getbuild_id(item)
  248. if targetid not in self.external_targets:
  249. self.external_targets.append(targetid)
  250. def get_unresolved_build_targets(self, dataCache):
  251. """
  252. Return a list of build targets who's providers
  253. are unknown.
  254. """
  255. unresolved = []
  256. for target in self.build_names_index:
  257. if re_match_strings(target, dataCache.ignored_dependencies):
  258. continue
  259. if self.build_names_index.index(target) in self.failed_deps:
  260. continue
  261. if not self.have_build_target(target):
  262. unresolved.append(target)
  263. return unresolved
  264. def get_unresolved_run_targets(self, dataCache):
  265. """
  266. Return a list of runtime targets who's providers
  267. are unknown.
  268. """
  269. unresolved = []
  270. for target in self.run_names_index:
  271. if re_match_strings(target, dataCache.ignored_dependencies):
  272. continue
  273. if self.run_names_index.index(target) in self.failed_rdeps:
  274. continue
  275. if not self.have_runtime_target(target):
  276. unresolved.append(target)
  277. return unresolved
  278. def get_provider(self, item):
  279. """
  280. Return a list of providers of item
  281. """
  282. targetid = self.getbuild_id(item)
  283. return self.build_targets[targetid]
  284. def get_dependees(self, itemid):
  285. """
  286. Return a list of targets which depend on item
  287. """
  288. dependees = []
  289. for fnid in self.depids:
  290. if itemid in self.depids[fnid]:
  291. dependees.append(fnid)
  292. return dependees
  293. def get_dependees_str(self, item):
  294. """
  295. Return a list of targets which depend on item as a user readable string
  296. """
  297. itemid = self.getbuild_id(item)
  298. dependees = []
  299. for fnid in self.depids:
  300. if itemid in self.depids[fnid]:
  301. dependees.append(self.fn_index[fnid])
  302. return dependees
  303. def get_rdependees(self, itemid):
  304. """
  305. Return a list of targets which depend on runtime item
  306. """
  307. dependees = []
  308. for fnid in self.rdepids:
  309. if itemid in self.rdepids[fnid]:
  310. dependees.append(fnid)
  311. return dependees
  312. def get_rdependees_str(self, item):
  313. """
  314. Return a list of targets which depend on runtime item as a user readable string
  315. """
  316. itemid = self.getrun_id(item)
  317. dependees = []
  318. for fnid in self.rdepids:
  319. if itemid in self.rdepids[fnid]:
  320. dependees.append(self.fn_index[fnid])
  321. return dependees
  322. def get_reasons(self, item, runtime=False):
  323. """
  324. Get the reason(s) for an item not being provided, if any
  325. """
  326. reasons = []
  327. if self.skiplist:
  328. for fn in self.skiplist:
  329. skipitem = self.skiplist[fn]
  330. if skipitem.pn == item:
  331. reasons.append("%s was skipped: %s" % (skipitem.pn, skipitem.skipreason))
  332. elif runtime and item in skipitem.rprovides:
  333. reasons.append("%s RPROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
  334. elif not runtime and item in skipitem.provides:
  335. reasons.append("%s PROVIDES %s but was skipped: %s" % (skipitem.pn, item, skipitem.skipreason))
  336. return reasons
  337. def get_close_matches(self, item, provider_list):
  338. import difflib
  339. if self.skiplist:
  340. skipped = []
  341. for fn in self.skiplist:
  342. skipped.append(self.skiplist[fn].pn)
  343. full_list = provider_list + skipped
  344. else:
  345. full_list = provider_list
  346. return difflib.get_close_matches(item, full_list, cutoff=0.7)
  347. def add_provider(self, cfgData, dataCache, item):
  348. try:
  349. self.add_provider_internal(cfgData, dataCache, item)
  350. except bb.providers.NoProvider:
  351. if self.abort:
  352. raise
  353. self.remove_buildtarget(self.getbuild_id(item))
  354. self.mark_external_target(item)
  355. def add_provider_internal(self, cfgData, dataCache, item):
  356. """
  357. Add the providers of item to the task data
  358. Mark entries were specifically added externally as against dependencies
  359. added internally during dependency resolution
  360. """
  361. if re_match_strings(item, dataCache.ignored_dependencies):
  362. return
  363. if not item in dataCache.providers:
  364. bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=self.get_close_matches(item, dataCache.providers.keys())), cfgData)
  365. raise bb.providers.NoProvider(item)
  366. if self.have_build_target(item):
  367. return
  368. all_p = dataCache.providers[item]
  369. eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache)
  370. eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
  371. if not eligible:
  372. bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=["No eligible PROVIDERs exist for '%s'" % item]), cfgData)
  373. raise bb.providers.NoProvider(item)
  374. if len(eligible) > 1 and foundUnique == False:
  375. if item not in self.consider_msgs_cache:
  376. providers_list = []
  377. for fn in eligible:
  378. providers_list.append(dataCache.pkg_fn[fn])
  379. bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
  380. self.consider_msgs_cache.append(item)
  381. for fn in eligible:
  382. fnid = self.getfn_id(fn)
  383. if fnid in self.failed_fnids:
  384. continue
  385. logger.debug(2, "adding %s to satisfy %s", fn, item)
  386. self.add_build_target(fn, item)
  387. self.add_tasks(fn, dataCache)
  388. #item = dataCache.pkg_fn[fn]
  389. def add_rprovider(self, cfgData, dataCache, item):
  390. """
  391. Add the runtime providers of item to the task data
  392. (takes item names from RDEPENDS/PACKAGES namespace)
  393. """
  394. if re_match_strings(item, dataCache.ignored_dependencies):
  395. return
  396. if self.have_runtime_target(item):
  397. return
  398. all_p = bb.providers.getRuntimeProviders(dataCache, item)
  399. if not all_p:
  400. bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=self.get_reasons(item, True)), cfgData)
  401. raise bb.providers.NoRProvider(item)
  402. eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
  403. eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
  404. if not eligible:
  405. bb.event.fire(bb.event.NoProvider(item, runtime=True, dependees=self.get_rdependees_str(item), reasons=["No eligible RPROVIDERs exist for '%s'" % item]), cfgData)
  406. raise bb.providers.NoRProvider(item)
  407. if len(eligible) > 1 and numberPreferred == 0:
  408. if item not in self.consider_msgs_cache:
  409. providers_list = []
  410. for fn in eligible:
  411. providers_list.append(dataCache.pkg_fn[fn])
  412. bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
  413. self.consider_msgs_cache.append(item)
  414. if numberPreferred > 1:
  415. if item not in self.consider_msgs_cache:
  416. providers_list = []
  417. for fn in eligible:
  418. providers_list.append(dataCache.pkg_fn[fn])
  419. bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
  420. self.consider_msgs_cache.append(item)
  421. raise bb.providers.MultipleRProvider(item)
  422. # run through the list until we find one that we can build
  423. for fn in eligible:
  424. fnid = self.getfn_id(fn)
  425. if fnid in self.failed_fnids:
  426. continue
  427. logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item)
  428. self.add_runtime_target(fn, item)
  429. self.add_tasks(fn, dataCache)
  430. def fail_fnid(self, fnid, missing_list=None):
  431. """
  432. Mark a file as failed (unbuildable)
  433. Remove any references from build and runtime provider lists
  434. missing_list, A list of missing requirements for this target
  435. """
  436. if fnid in self.failed_fnids:
  437. return
  438. if not missing_list:
  439. missing_list = []
  440. logger.debug(1, "File '%s' is unbuildable, removing...", self.fn_index[fnid])
  441. self.failed_fnids.append(fnid)
  442. for target in self.build_targets:
  443. if fnid in self.build_targets[target]:
  444. self.build_targets[target].remove(fnid)
  445. if len(self.build_targets[target]) == 0:
  446. self.remove_buildtarget(target, missing_list)
  447. for target in self.run_targets:
  448. if fnid in self.run_targets[target]:
  449. self.run_targets[target].remove(fnid)
  450. if len(self.run_targets[target]) == 0:
  451. self.remove_runtarget(target, missing_list)
  452. def remove_buildtarget(self, targetid, missing_list=None):
  453. """
  454. Mark a build target as failed (unbuildable)
  455. Trigger removal of any files that have this as a dependency
  456. """
  457. if not missing_list:
  458. missing_list = [self.build_names_index[targetid]]
  459. else:
  460. missing_list = [self.build_names_index[targetid]] + missing_list
  461. logger.verbose("Target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.build_names_index[targetid], missing_list)
  462. self.failed_deps.append(targetid)
  463. dependees = self.get_dependees(targetid)
  464. for fnid in dependees:
  465. self.fail_fnid(fnid, missing_list)
  466. for taskid in xrange(len(self.tasks_idepends)):
  467. idepends = self.tasks_idepends[taskid]
  468. for (idependid, idependtask) in idepends:
  469. if idependid == targetid:
  470. self.fail_fnid(self.tasks_fnid[taskid], missing_list)
  471. if self.abort and targetid in self.external_targets:
  472. target = self.build_names_index[targetid]
  473. logger.error("Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s", target, missing_list)
  474. raise bb.providers.NoProvider(target)
  475. def remove_runtarget(self, targetid, missing_list=None):
  476. """
  477. Mark a run target as failed (unbuildable)
  478. Trigger removal of any files that have this as a dependency
  479. """
  480. if not missing_list:
  481. missing_list = [self.run_names_index[targetid]]
  482. else:
  483. missing_list = [self.run_names_index[targetid]] + missing_list
  484. logger.info("Runtime target '%s' is unbuildable, removing...\nMissing or unbuildable dependency chain was: %s", self.run_names_index[targetid], missing_list)
  485. self.failed_rdeps.append(targetid)
  486. dependees = self.get_rdependees(targetid)
  487. for fnid in dependees:
  488. self.fail_fnid(fnid, missing_list)
  489. for taskid in xrange(len(self.tasks_irdepends)):
  490. irdepends = self.tasks_irdepends[taskid]
  491. for (idependid, idependtask) in irdepends:
  492. if idependid == targetid:
  493. self.fail_fnid(self.tasks_fnid[taskid], missing_list)
  494. def add_unresolved(self, cfgData, dataCache):
  495. """
  496. Resolve all unresolved build and runtime targets
  497. """
  498. logger.info("Resolving any missing task queue dependencies")
  499. while True:
  500. added = 0
  501. for target in self.get_unresolved_build_targets(dataCache):
  502. try:
  503. self.add_provider_internal(cfgData, dataCache, target)
  504. added = added + 1
  505. except bb.providers.NoProvider:
  506. targetid = self.getbuild_id(target)
  507. if self.abort and targetid in self.external_targets and not self.allowincomplete:
  508. raise
  509. if not self.allowincomplete:
  510. self.remove_buildtarget(targetid)
  511. for target in self.get_unresolved_run_targets(dataCache):
  512. try:
  513. self.add_rprovider(cfgData, dataCache, target)
  514. added = added + 1
  515. except (bb.providers.NoRProvider, bb.providers.MultipleRProvider):
  516. self.remove_runtarget(self.getrun_id(target))
  517. logger.debug(1, "Resolved " + str(added) + " extra dependencies")
  518. if added == 0:
  519. break
  520. # self.dump_data()
  521. def get_providermap(self, prefix=None):
  522. provmap = {}
  523. for name in self.build_names_index:
  524. if prefix and not name.startswith(prefix):
  525. continue
  526. if self.have_build_target(name):
  527. provmap[name] = self.fn_index[self.get_provider(name)[0]]
  528. return provmap
  529. def dump_data(self):
  530. """
  531. Dump some debug information on the internal data structures
  532. """
  533. logger.debug(3, "build_names:")
  534. logger.debug(3, ", ".join(self.build_names_index))
  535. logger.debug(3, "run_names:")
  536. logger.debug(3, ", ".join(self.run_names_index))
  537. logger.debug(3, "build_targets:")
  538. for buildid in xrange(len(self.build_names_index)):
  539. target = self.build_names_index[buildid]
  540. targets = "None"
  541. if buildid in self.build_targets:
  542. targets = self.build_targets[buildid]
  543. logger.debug(3, " (%s)%s: %s", buildid, target, targets)
  544. logger.debug(3, "run_targets:")
  545. for runid in xrange(len(self.run_names_index)):
  546. target = self.run_names_index[runid]
  547. targets = "None"
  548. if runid in self.run_targets:
  549. targets = self.run_targets[runid]
  550. logger.debug(3, " (%s)%s: %s", runid, target, targets)
  551. logger.debug(3, "tasks:")
  552. for task in xrange(len(self.tasks_name)):
  553. logger.debug(3, " (%s)%s - %s: %s",
  554. task,
  555. self.fn_index[self.tasks_fnid[task]],
  556. self.tasks_name[task],
  557. self.tasks_tdepends[task])
  558. logger.debug(3, "dependency ids (per fn):")
  559. for fnid in self.depids:
  560. logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.depids[fnid])
  561. logger.debug(3, "runtime dependency ids (per fn):")
  562. for fnid in self.rdepids:
  563. logger.debug(3, " %s %s: %s", fnid, self.fn_index[fnid], self.rdepids[fnid])