summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/ChangeLog5
-rw-r--r--bitbake/lib/bb/cache.py78
-rw-r--r--bitbake/lib/bb/cooker.py7
-rw-r--r--bitbake/lib/bb/runqueue.py130
-rw-r--r--bitbake/lib/bb/taskdata.py14
5 files changed, 152 insertions, 82 deletions
diff --git a/bitbake/ChangeLog b/bitbake/ChangeLog
index d074a5e239..7bed88112e 100644
--- a/bitbake/ChangeLog
+++ b/bitbake/ChangeLog
@@ -1,4 +1,5 @@
1Changes in BitBake 1.8.x: 1Changes in BitBake 1.8.x:
2 - Fix -f (force) in conjunction with -b
2 - Fix exit code for build failures in --continue mode 3 - Fix exit code for build failures in --continue mode
3 - Fix git branch tags fetching 4 - Fix git branch tags fetching
4 - Change parseConfigurationFile so it works on real data, not a copy 5 - Change parseConfigurationFile so it works on real data, not a copy
@@ -21,6 +22,10 @@ Changes in BitBake 1.8.x:
21 the way bitbake schedules tasks 22 the way bitbake schedules tasks
22 - Add BB_STAMP_POLICY variable/option ("perfile" or "full") controlling 23 - Add BB_STAMP_POLICY variable/option ("perfile" or "full") controlling
23 how extensively stamps are looked at for validity 24 how extensively stamps are looked at for validity
25 - When handling build target failures make sure idepends are checked and
26 failed where needed. Fixes --continue mode crashes.
27 - Fix problems with recrdeptask handling where some idepends weren't handled
28 correctly.
24 29
25Changes in BitBake 1.8.10: 30Changes in BitBake 1.8.10:
26 - Psyco is available only for x86 - do not use it on other architectures. 31 - Psyco is available only for x86 - do not use it on other architectures.
diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py
index 60e863d52d..9acd301f52 100644
--- a/bitbake/lib/bb/cache.py
+++ b/bitbake/lib/bb/cache.py
@@ -80,7 +80,7 @@ class Cache:
80 if old_mtime > newest_mtime: 80 if old_mtime > newest_mtime:
81 newest_mtime = old_mtime 81 newest_mtime = old_mtime
82 82
83 if self.mtime(self.cachefile) >= newest_mtime: 83 if bb.parse.cached_mtime_noerror(self.cachefile) >= newest_mtime:
84 try: 84 try:
85 p = pickle.Unpickler(file(self.cachefile, "rb")) 85 p = pickle.Unpickler(file(self.cachefile, "rb"))
86 self.depends_cache, version_data = p.load() 86 self.depends_cache, version_data = p.load()
@@ -91,7 +91,7 @@ class Cache:
91 except EOFError: 91 except EOFError:
92 bb.msg.note(1, bb.msg.domain.Cache, "Truncated cache found, rebuilding...") 92 bb.msg.note(1, bb.msg.domain.Cache, "Truncated cache found, rebuilding...")
93 self.depends_cache = {} 93 self.depends_cache = {}
94 except (ValueError, KeyError): 94 except:
95 bb.msg.note(1, bb.msg.domain.Cache, "Invalid cache found, rebuilding...") 95 bb.msg.note(1, bb.msg.domain.Cache, "Invalid cache found, rebuilding...")
96 self.depends_cache = {} 96 self.depends_cache = {}
97 else: 97 else:
@@ -199,31 +199,34 @@ class Cache:
199 self.remove(fn) 199 self.remove(fn)
200 return False 200 return False
201 201
202 mtime = bb.parse.cached_mtime_noerror(fn)
203
202 # Check file still exists 204 # Check file still exists
203 if self.mtime(fn) == 0: 205 if mtime == 0:
204 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s not longer exists" % fn) 206 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s not longer exists" % fn)
205 self.remove(fn) 207 self.remove(fn)
206 return False 208 return False
207 209
208 # Check the file's timestamp 210 # Check the file's timestamp
209 if bb.parse.cached_mtime(fn) > self.getVar("CACHETIMESTAMP", fn, True): 211 if mtime > self.getVar("CACHETIMESTAMP", fn, True):
210 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s changed" % fn) 212 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s changed" % fn)
211 self.remove(fn) 213 self.remove(fn)
212 return False 214 return False
213 215
214 # Check dependencies are still valid 216 # Check dependencies are still valid
215 depends = self.getVar("__depends", fn, True) 217 depends = self.getVar("__depends", fn, True)
216 for f,old_mtime in depends: 218 if depends:
217 # Check if file still exists 219 for f,old_mtime in depends:
218 if self.mtime(f) == 0: 220 fmtime = bb.parse.cached_mtime_noerror(f)
219 self.remove(fn) 221 # Check if file still exists
220 return False 222 if fmtime == 0:
221 223 self.remove(fn)
222 new_mtime = bb.parse.cached_mtime(f) 224 return False
223 if (new_mtime > old_mtime): 225
224 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s's dependency %s changed" % (fn, f)) 226 if (fmtime > old_mtime):
225 self.remove(fn) 227 bb.msg.debug(2, bb.msg.domain.Cache, "Cache: %s's dependency %s changed" % (fn, f))
226 return False 228 self.remove(fn)
229 return False
227 230
228 #bb.msg.debug(2, bb.msg.domain.Cache, "Depends Cache: %s is clean" % fn) 231 #bb.msg.debug(2, bb.msg.domain.Cache, "Depends Cache: %s is clean" % fn)
229 if not fn in self.clean: 232 if not fn in self.clean:
@@ -284,7 +287,6 @@ class Cache:
284 pv = self.getVar('PV', file_name, True) 287 pv = self.getVar('PV', file_name, True)
285 pr = self.getVar('PR', file_name, True) 288 pr = self.getVar('PR', file_name, True)
286 dp = int(self.getVar('DEFAULT_PREFERENCE', file_name, True) or "0") 289 dp = int(self.getVar('DEFAULT_PREFERENCE', file_name, True) or "0")
287 provides = Set([pn] + (self.getVar("PROVIDES", file_name, True) or "").split())
288 depends = bb.utils.explode_deps(self.getVar("DEPENDS", file_name, True) or "") 290 depends = bb.utils.explode_deps(self.getVar("DEPENDS", file_name, True) or "")
289 packages = (self.getVar('PACKAGES', file_name, True) or "").split() 291 packages = (self.getVar('PACKAGES', file_name, True) or "").split()
290 packages_dynamic = (self.getVar('PACKAGES_DYNAMIC', file_name, True) or "").split() 292 packages_dynamic = (self.getVar('PACKAGES_DYNAMIC', file_name, True) or "").split()
@@ -304,24 +306,31 @@ class Cache:
304 cacheData.pkg_pepvpr[file_name] = (pe,pv,pr) 306 cacheData.pkg_pepvpr[file_name] = (pe,pv,pr)
305 cacheData.pkg_dp[file_name] = dp 307 cacheData.pkg_dp[file_name] = dp
306 308
309 provides = [pn]
310 for provide in (self.getVar("PROVIDES", file_name, True) or "").split():
311 if provide not in provides:
312 provides.append(provide)
313
307 # Build forward and reverse provider hashes 314 # Build forward and reverse provider hashes
308 # Forward: virtual -> [filenames] 315 # Forward: virtual -> [filenames]
309 # Reverse: PN -> [virtuals] 316 # Reverse: PN -> [virtuals]
310 if pn not in cacheData.pn_provides: 317 if pn not in cacheData.pn_provides:
311 cacheData.pn_provides[pn] = Set() 318 cacheData.pn_provides[pn] = []
312 cacheData.pn_provides[pn] |= provides
313 319
314 cacheData.fn_provides[file_name] = Set() 320 cacheData.fn_provides[file_name] = provides
315 for provide in provides: 321 for provide in provides:
316 if provide not in cacheData.providers: 322 if provide not in cacheData.providers:
317 cacheData.providers[provide] = [] 323 cacheData.providers[provide] = []
318 cacheData.providers[provide].append(file_name) 324 cacheData.providers[provide].append(file_name)
319 cacheData.fn_provides[file_name].add(provide) 325 if not provide in cacheData.pn_provides[pn]:
326 cacheData.pn_provides[pn].append(provide)
320 327
321 cacheData.deps[file_name] = Set() 328 cacheData.deps[file_name] = []
322 for dep in depends: 329 for dep in depends:
323 cacheData.all_depends.add(dep) 330 if not dep in cacheData.deps[file_name]:
324 cacheData.deps[file_name].add(dep) 331 cacheData.deps[file_name].append(dep)
332 if not dep in cacheData.all_depends:
333 cacheData.all_depends.append(dep)
325 334
326 # Build reverse hash for PACKAGES, so runtime dependencies 335 # Build reverse hash for PACKAGES, so runtime dependencies
327 # can be be resolved (RDEPENDS, RRECOMMENDS etc.) 336 # can be be resolved (RDEPENDS, RRECOMMENDS etc.)
@@ -343,28 +352,21 @@ class Cache:
343 352
344 # Build hash of runtime depends and rececommends 353 # Build hash of runtime depends and rececommends
345 354
346 def add_dep(deplist, deps):
347 for dep in deps:
348 if not dep in deplist:
349 deplist[dep] = ""
350
351 if not file_name in cacheData.rundeps: 355 if not file_name in cacheData.rundeps:
352 cacheData.rundeps[file_name] = {} 356 cacheData.rundeps[file_name] = {}
353 if not file_name in cacheData.runrecs: 357 if not file_name in cacheData.runrecs:
354 cacheData.runrecs[file_name] = {} 358 cacheData.runrecs[file_name] = {}
355 359
356 rdepends = bb.utils.explode_deps(self.getVar('RDEPENDS', file_name, True) or "") 360 rdepends = self.getVar('RDEPENDS', file_name, True) or ""
357 rrecommends = bb.utils.explode_deps(self.getVar('RRECOMMENDS', file_name, True) or "") 361 rrecommends = self.getVar('RRECOMMENDS', file_name, True) or ""
358 for package in packages + [pn]: 362 for package in packages + [pn]:
359 if not package in cacheData.rundeps[file_name]: 363 if not package in cacheData.rundeps[file_name]:
360 cacheData.rundeps[file_name][package] = {} 364 cacheData.rundeps[file_name][package] = []
361 if not package in cacheData.runrecs[file_name]: 365 if not package in cacheData.runrecs[file_name]:
362 cacheData.runrecs[file_name][package] = {} 366 cacheData.runrecs[file_name][package] = []
363 367
364 add_dep(cacheData.rundeps[file_name][package], rdepends) 368 cacheData.rundeps[file_name][package] = rdepends + " " + (self.getVar("RDEPENDS_%s" % package, file_name, True) or "")
365 add_dep(cacheData.runrecs[file_name][package], rrecommends) 369 cacheData.runrecs[file_name][package] = rrecommends + " " + (self.getVar("RRECOMMENDS_%s" % package, file_name, True) or "")
366 add_dep(cacheData.rundeps[file_name][package], bb.utils.explode_deps(self.getVar("RDEPENDS_%s" % package, file_name, True) or ""))
367 add_dep(cacheData.runrecs[file_name][package], bb.utils.explode_deps(self.getVar("RRECOMMENDS_%s" % package, file_name, True) or ""))
368 370
369 # Collect files we may need for possible world-dep 371 # Collect files we may need for possible world-dep
370 # calculations 372 # calculations
@@ -385,7 +387,7 @@ class Cache:
385 data.setVar('TMPDIR', data.getVar('TMPDIR', config, 1) or "", config) 387 data.setVar('TMPDIR', data.getVar('TMPDIR', config, 1) or "", config)
386 bbfile_loc = os.path.abspath(os.path.dirname(bbfile)) 388 bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
387 oldpath = os.path.abspath(os.getcwd()) 389 oldpath = os.path.abspath(os.getcwd())
388 if self.mtime(bbfile_loc): 390 if bb.parse.cached_mtime_noerror(bbfile_loc):
389 os.chdir(bbfile_loc) 391 os.chdir(bbfile_loc)
390 bb_data = data.init_db(config) 392 bb_data = data.init_db(config)
391 try: 393 try:
@@ -444,7 +446,7 @@ class CacheData:
444 self.pkg_dp = {} 446 self.pkg_dp = {}
445 self.pn_provides = {} 447 self.pn_provides = {}
446 self.fn_provides = {} 448 self.fn_provides = {}
447 self.all_depends = Set() 449 self.all_depends = []
448 self.deps = {} 450 self.deps = {}
449 self.rundeps = {} 451 self.rundeps = {}
450 self.runrecs = {} 452 self.runrecs = {}
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 38a8209760..619791f174 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -473,11 +473,11 @@ class BBCooker:
473 473
474 # Load data into the cache for fn 474 # Load data into the cache for fn
475 self.bb_cache = bb.cache.init(self) 475 self.bb_cache = bb.cache.init(self)
476 self.bb_cache.loadData(fn, self.configuration.data) 476 self.bb_cache.loadData(fn, self.configuration.data)
477 477
478 # Parse the loaded cache data 478 # Parse the loaded cache data
479 self.status = bb.cache.CacheData() 479 self.status = bb.cache.CacheData()
480 self.bb_cache.handle_data(fn, self.status) 480 self.bb_cache.handle_data(fn, self.status)
481 481
482 # Tweak some variables 482 # Tweak some variables
483 item = self.bb_cache.getVar('PN', fn, True) 483 item = self.bb_cache.getVar('PN', fn, True)
@@ -493,7 +493,7 @@ class BBCooker:
493 # Remove stamp for target if force mode active 493 # Remove stamp for target if force mode active
494 if self.configuration.force: 494 if self.configuration.force:
495 bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, fn)) 495 bb.msg.note(2, bb.msg.domain.RunQueue, "Remove stamp %s, %s" % (self.configuration.cmd, fn))
496 bb.build.del_stamp('do_%s' % self.configuration.cmd, bbfile_data) 496 bb.build.del_stamp('do_%s' % self.configuration.cmd, self.configuration.data)
497 497
498 # Setup taskdata structure 498 # Setup taskdata structure
499 taskdata = bb.taskdata.TaskData(self.configuration.abort) 499 taskdata = bb.taskdata.TaskData(self.configuration.abort)
@@ -573,6 +573,7 @@ class BBCooker:
573 573
574 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files") 574 bb.msg.debug(1, bb.msg.domain.Collection, "collecting .bb files")
575 (filelist, masked) = self.collect_bbfiles() 575 (filelist, masked) = self.collect_bbfiles()
576 bb.data.renameVar("__depends", "__base_depends", self.configuration.data)
576 self.parse_bbfiles(filelist, masked, self.myProgressCallback) 577 self.parse_bbfiles(filelist, masked, self.myProgressCallback)
577 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete") 578 bb.msg.debug(1, bb.msg.domain.Collection, "parsing complete")
578 579
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 2765343a3e..7b3defd343 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -317,6 +317,7 @@ class RunQueue:
317 317
318 depends = [] 318 depends = []
319 runq_build = [] 319 runq_build = []
320 recursive_tdepends = {}
320 321
321 taskData = self.taskData 322 taskData = self.taskData
322 323
@@ -382,14 +383,45 @@ class RunQueue:
382 # e.g. do_sometask[depends] = "targetname:do_someothertask" 383 # e.g. do_sometask[depends] = "targetname:do_someothertask"
383 # (makes sure sometask runs after targetname's someothertask) 384 # (makes sure sometask runs after targetname's someothertask)
384 idepends = taskData.tasks_idepends[task] 385 idepends = taskData.tasks_idepends[task]
385 for idepend in idepends: 386 for (depid, idependtask) in idepends:
386 depid = int(idepend.split(":")[0])
387 if depid in taskData.build_targets: 387 if depid in taskData.build_targets:
388 # Won't be in build_targets if ASSUME_PROVIDED 388 # Won't be in build_targets if ASSUME_PROVIDED
389 depdata = taskData.build_targets[depid][0] 389 depdata = taskData.build_targets[depid][0]
390 if depdata is not None: 390 if depdata is not None:
391 dep = taskData.fn_index[depdata] 391 dep = taskData.fn_index[depdata]
392 depends.append(taskData.gettask_id(dep, idepend.split(":")[1])) 392 depends.append(taskData.gettask_id(dep, idependtask))
393
394 # Create a list of recursive dependent tasks (from tdepends) and cache
395 def get_recursive_tdepends(task):
396 if not task:
397 return []
398 if task in recursive_tdepends:
399 return recursive_tdepends[task]
400 rectdepends = [task]
401 nextdeps = [task]
402 while len(nextdeps) != 0:
403 newdeps = []
404 for nextdep in nextdeps:
405 for tdepend in taskData.tasks_tdepends[nextdep]:
406 if tdepend not in rectdepends:
407 rectdepends.append(tdepend)
408 newdeps.append(tdepend)
409 nextdeps = newdeps
410 recursive_tdepends[task] = rectdepends
411 return rectdepends
412
413 # Using the list of tdepends for this task create a list of
414 # the recursive idepends we have
415 def get_recursive_idepends(task):
416 if not task:
417 return []
418 rectdepends = get_recursive_tdepends(task)
419
420 recidepends = []
421 for tdepend in rectdepends:
422 for idepend in taskData.tasks_idepends[tdepend]:
423 recidepends.append(idepend)
424 return recidepends
393 425
394 def add_recursive_build(depid, depfnid): 426 def add_recursive_build(depid, depfnid):
395 """ 427 """
@@ -404,13 +436,11 @@ class RunQueue:
404 depdata = taskData.build_targets[depid][0] 436 depdata = taskData.build_targets[depid][0]
405 if depdata is not None: 437 if depdata is not None:
406 dep = taskData.fn_index[depdata] 438 dep = taskData.fn_index[depdata]
407 idepends = []
408 # Need to avoid creating new tasks here 439 # Need to avoid creating new tasks here
409 taskid = taskData.gettask_id(dep, taskname, False) 440 taskid = taskData.gettask_id(dep, taskname, False)
410 if taskid is not None: 441 if taskid is not None:
411 depends.append(taskid) 442 depends.append(taskid)
412 fnid = taskData.tasks_fnid[taskid] 443 fnid = taskData.tasks_fnid[taskid]
413 idepends = taskData.tasks_idepends[taskid]
414 #print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid]) 444 #print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
415 else: 445 else:
416 fnid = taskData.getfn_id(dep) 446 fnid = taskData.getfn_id(dep)
@@ -420,10 +450,9 @@ class RunQueue:
420 for nextdepid in taskData.rdepids[fnid]: 450 for nextdepid in taskData.rdepids[fnid]:
421 if nextdepid not in rdep_seen: 451 if nextdepid not in rdep_seen:
422 add_recursive_run(nextdepid, fnid) 452 add_recursive_run(nextdepid, fnid)
423 for idepend in idepends: 453 for (idependid, idependtask) in get_recursive_idepends(taskid):
424 nextdepid = int(idepend.split(":")[0]) 454 if idependid not in dep_seen:
425 if nextdepid not in dep_seen: 455 add_recursive_build(idependid, fnid)
426 add_recursive_build(nextdepid, fnid)
427 456
428 def add_recursive_run(rdepid, depfnid): 457 def add_recursive_run(rdepid, depfnid):
429 """ 458 """
@@ -438,13 +467,11 @@ class RunQueue:
438 depdata = taskData.run_targets[rdepid][0] 467 depdata = taskData.run_targets[rdepid][0]
439 if depdata is not None: 468 if depdata is not None:
440 dep = taskData.fn_index[depdata] 469 dep = taskData.fn_index[depdata]
441 idepends = []
442 # Need to avoid creating new tasks here 470 # Need to avoid creating new tasks here
443 taskid = taskData.gettask_id(dep, taskname, False) 471 taskid = taskData.gettask_id(dep, taskname, False)
444 if taskid is not None: 472 if taskid is not None:
445 depends.append(taskid) 473 depends.append(taskid)
446 fnid = taskData.tasks_fnid[taskid] 474 fnid = taskData.tasks_fnid[taskid]
447 idepends = taskData.tasks_idepends[taskid]
448 #print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid]) 475 #print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
449 else: 476 else:
450 fnid = taskData.getfn_id(dep) 477 fnid = taskData.getfn_id(dep)
@@ -454,10 +481,9 @@ class RunQueue:
454 for nextdepid in taskData.rdepids[fnid]: 481 for nextdepid in taskData.rdepids[fnid]:
455 if nextdepid not in rdep_seen: 482 if nextdepid not in rdep_seen:
456 add_recursive_run(nextdepid, fnid) 483 add_recursive_run(nextdepid, fnid)
457 for idepend in idepends: 484 for (idependid, idependtask) in get_recursive_idepends(taskid):
458 nextdepid = int(idepend.split(":")[0]) 485 if idependid not in dep_seen:
459 if nextdepid not in dep_seen: 486 add_recursive_build(idependid, fnid)
460 add_recursive_build(nextdepid, fnid)
461 487
462 # Resolve recursive 'recrdeptask' dependencies 488 # Resolve recursive 'recrdeptask' dependencies
463 # 489 #
@@ -472,9 +498,9 @@ class RunQueue:
472 add_recursive_build(depid, fnid) 498 add_recursive_build(depid, fnid)
473 for rdepid in taskData.rdepids[fnid]: 499 for rdepid in taskData.rdepids[fnid]:
474 add_recursive_run(rdepid, fnid) 500 add_recursive_run(rdepid, fnid)
475 for idepend in idepends: 501 deptaskid = taskData.gettask_id(fn, taskname, False)
476 depid = int(idepend.split(":")[0]) 502 for (idependid, idependtask) in get_recursive_idepends(deptaskid):
477 add_recursive_build(depid, fnid) 503 add_recursive_build(idependid, fnid)
478 504
479 # Rmove all self references 505 # Rmove all self references
480 if task in depends: 506 if task in depends:
@@ -659,6 +685,16 @@ class RunQueue:
659 if len(self.runq_depends[task]) == 0: 685 if len(self.runq_depends[task]) == 0:
660 buildable.append(task) 686 buildable.append(task)
661 687
688 def check_buildable(self, task, buildable):
689 for revdep in self.runq_revdeps[task]:
690 alldeps = 1
691 for dep in self.runq_depends[revdep]:
692 if dep in unchecked:
693 alldeps = 0
694 if alldeps == 1:
695 if revdep in unchecked:
696 buildable.append(revdep)
697
662 for task in range(len(self.runq_fnid)): 698 for task in range(len(self.runq_fnid)):
663 if task not in unchecked: 699 if task not in unchecked:
664 continue 700 continue
@@ -669,12 +705,14 @@ class RunQueue:
669 if not os.access(stampfile, os.F_OK): 705 if not os.access(stampfile, os.F_OK):
670 del unchecked[task] 706 del unchecked[task]
671 notcurrent.append(task) 707 notcurrent.append(task)
708 check_buildable(self, task, buildable)
672 continue 709 continue
673 # If its a 'nostamp' task, it's not current 710 # If its a 'nostamp' task, it's not current
674 taskdep = self.dataCache.task_deps[fn] 711 taskdep = self.dataCache.task_deps[fn]
675 if 'nostamp' in taskdep and task in taskdep['nostamp']: 712 if 'nostamp' in taskdep and task in taskdep['nostamp']:
676 del unchecked[task] 713 del unchecked[task]
677 notcurrent.append(task) 714 notcurrent.append(task)
715 check_buildable(self, task, buildable)
678 continue 716 continue
679 717
680 while (len(buildable) > 0): 718 while (len(buildable) > 0):
@@ -705,14 +743,7 @@ class RunQueue:
705 else: 743 else:
706 notcurrent.append(task) 744 notcurrent.append(task)
707 745
708 for revdep in self.runq_revdeps[task]: 746 check_buildable(self, task, nextbuildable)
709 alldeps = 1
710 for dep in self.runq_depends[revdep]:
711 if dep in unchecked:
712 alldeps = 0
713 if alldeps == 1:
714 if revdep in unchecked:
715 nextbuildable.append(revdep)
716 747
717 buildable = nextbuildable 748 buildable = nextbuildable
718 749
@@ -729,6 +760,40 @@ class RunQueue:
729 bb.fatal("check_stamps fatal internal error") 760 bb.fatal("check_stamps fatal internal error")
730 return current 761 return current
731 762
763 def check_stamp(self, task):
764
765 if self.stamppolicy == "perfile":
766 fulldeptree = False
767 else:
768 fulldeptree = True
769
770 fn = self.taskData.fn_index[self.runq_fnid[task]]
771 taskname = self.runq_task[task]
772 stampfile = "%s.%s" % (self.dataCache.stamp[fn], taskname)
773 # If the stamp is missing its not current
774 if not os.access(stampfile, os.F_OK):
775 return False
776 # If its a 'nostamp' task, it's not current
777 taskdep = self.dataCache.task_deps[fn]
778 if 'nostamp' in taskdep and task in taskdep['nostamp']:
779 return False
780
781 iscurrent = True
782 t1 = os.stat(stampfile)[stat.ST_MTIME]
783 for dep in self.runq_depends[task]:
784 if iscurrent:
785 fn2 = self.taskData.fn_index[self.runq_fnid[dep]]
786 taskname2 = self.runq_task[dep]
787 stampfile2 = "%s.%s" % (self.dataCache.stamp[fn2], taskname2)
788 if fulldeptree or fn == fn2:
789 try:
790 t2 = os.stat(stampfile2)[stat.ST_MTIME]
791 if t1 < t2:
792 iscurrent = False
793 except:
794 iscurrent = False
795
796 return iscurrent
732 797
733 def execute_runqueue(self): 798 def execute_runqueue(self):
734 """ 799 """
@@ -817,25 +882,18 @@ class RunQueue:
817 882
818 event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgdata)) 883 event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgdata))
819 884
820 # Find out which tasks have current stamps which we can skip when the
821 # time comes
822 currentstamps = self.check_stamps()
823 self.stats.taskSkipped(len(currentstamps))
824 self.stats.taskCompleted(len(currentstamps))
825
826 while True: 885 while True:
827 task = self.sched.next() 886 task = self.sched.next()
828 if task is not None: 887 if task is not None:
829 fn = self.taskData.fn_index[self.runq_fnid[task]] 888 fn = self.taskData.fn_index[self.runq_fnid[task]]
830 889
831 taskname = self.runq_task[task] 890 taskname = self.runq_task[task]
832 if task in currentstamps: 891 if self.check_stamp(task):
833 #if bb.build.stamp_is_current(taskname, self.dataCache, fn):
834 bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task))) 892 bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task)))
835 self.runq_running[task] = 1 893 self.runq_running[task] = 1
836 self.task_complete(task) 894 self.task_complete(task)
837 #self.stats.taskCompleted() 895 self.stats.taskCompleted()
838 #self.stats.taskSkipped() 896 self.stats.taskSkipped()
839 continue 897 continue
840 898
841 bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task))) 899 bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task)))
diff --git a/bitbake/lib/bb/taskdata.py b/bitbake/lib/bb/taskdata.py
index 4a79e7a56d..0fb34ad748 100644
--- a/bitbake/lib/bb/taskdata.py
+++ b/bitbake/lib/bb/taskdata.py
@@ -150,7 +150,7 @@ class TaskData:
150 ids = [] 150 ids = []
151 for dep in task_deps['depends'][task].split(): 151 for dep in task_deps['depends'][task].split():
152 if dep: 152 if dep:
153 ids.append(str(self.getbuild_id(dep.split(":")[0])) + ":" + dep.split(":")[1]) 153 ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1]))
154 self.tasks_idepends[taskid].extend(ids) 154 self.tasks_idepends[taskid].extend(ids)
155 155
156 # Work out build dependencies 156 # Work out build dependencies
@@ -167,11 +167,11 @@ class TaskData:
167 rdepends = dataCache.rundeps[fn] 167 rdepends = dataCache.rundeps[fn]
168 rrecs = dataCache.runrecs[fn] 168 rrecs = dataCache.runrecs[fn]
169 for package in rdepends: 169 for package in rdepends:
170 for rdepend in rdepends[package]: 170 for rdepend in bb.utils.explode_deps(rdepends[package]):
171 bb.msg.debug(2, bb.msg.domain.TaskData, "Added runtime dependency %s for %s" % (rdepend, fn)) 171 bb.msg.debug(2, bb.msg.domain.TaskData, "Added runtime dependency %s for %s" % (rdepend, fn))
172 rdependids[self.getrun_id(rdepend)] = None 172 rdependids[self.getrun_id(rdepend)] = None
173 for package in rrecs: 173 for package in rrecs:
174 for rdepend in rrecs[package]: 174 for rdepend in bb.utils.explode_deps(rrecs[package]):
175 bb.msg.debug(2, bb.msg.domain.TaskData, "Added runtime recommendation %s for %s" % (rdepend, fn)) 175 bb.msg.debug(2, bb.msg.domain.TaskData, "Added runtime recommendation %s for %s" % (rdepend, fn))
176 rdependids[self.getrun_id(rdepend)] = None 176 rdependids[self.getrun_id(rdepend)] = None
177 self.rdepids[fnid] = rdependids.keys() 177 self.rdepids[fnid] = rdependids.keys()
@@ -458,8 +458,6 @@ class TaskData:
458 """ 458 """
459 if fnid in self.failed_fnids: 459 if fnid in self.failed_fnids:
460 return 460 return
461 if not missing_list:
462 missing_list = [fnid]
463 bb.msg.debug(1, bb.msg.domain.Provider, "File '%s' is unbuildable, removing..." % self.fn_index[fnid]) 461 bb.msg.debug(1, bb.msg.domain.Provider, "File '%s' is unbuildable, removing..." % self.fn_index[fnid])
464 self.failed_fnids.append(fnid) 462 self.failed_fnids.append(fnid)
465 for target in self.build_targets: 463 for target in self.build_targets:
@@ -487,6 +485,12 @@ class TaskData:
487 dependees = self.get_dependees(targetid) 485 dependees = self.get_dependees(targetid)
488 for fnid in dependees: 486 for fnid in dependees:
489 self.fail_fnid(fnid, missing_list) 487 self.fail_fnid(fnid, missing_list)
488 for taskid in range(len(self.tasks_idepends)):
489 idepends = self.tasks_idepends[taskid]
490 for (idependid, idependtask) in idepends:
491 if idependid == targetid:
492 self.fail_fnid(self.tasks_fnid[taskid], missing_list)
493
490 if self.abort and targetid in self.external_targets: 494 if self.abort and targetid in self.external_targets:
491 bb.msg.error(bb.msg.domain.Provider, "Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s" % (self.build_names_index[targetid], missing_list)) 495 bb.msg.error(bb.msg.domain.Provider, "Required build target '%s' has no buildable providers.\nMissing or unbuildable dependency chain was: %s" % (self.build_names_index[targetid], missing_list))
492 raise bb.providers.NoProvider 496 raise bb.providers.NoProvider