diff options
| -rw-r--r-- | bitbake/ChangeLog | 5 | ||||
| -rw-r--r-- | bitbake/lib/bb/cache.py | 78 | ||||
| -rw-r--r-- | bitbake/lib/bb/cooker.py | 7 | ||||
| -rw-r--r-- | bitbake/lib/bb/runqueue.py | 130 | ||||
| -rw-r--r-- | bitbake/lib/bb/taskdata.py | 14 |
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 @@ | |||
| 1 | Changes in BitBake 1.8.x: | 1 | Changes 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 | ||
| 25 | Changes in BitBake 1.8.10: | 30 | Changes 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 |
