diff options
Diffstat (limited to 'bitbake/lib/bb/cache.py')
| -rw-r--r-- | bitbake/lib/bb/cache.py | 358 |
1 files changed, 165 insertions, 193 deletions
diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py index d083c515ed..09691d98cc 100644 --- a/bitbake/lib/bb/cache.py +++ b/bitbake/lib/bb/cache.py | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | import os | 31 | import os |
| 32 | import logging | 32 | import logging |
| 33 | from collections import defaultdict, namedtuple | 33 | from collections import defaultdict |
| 34 | import bb.data | 34 | import bb.data |
| 35 | import bb.utils | 35 | import bb.utils |
| 36 | 36 | ||
| @@ -45,46 +45,11 @@ except ImportError: | |||
| 45 | 45 | ||
| 46 | __cache_version__ = "138" | 46 | __cache_version__ = "138" |
| 47 | 47 | ||
| 48 | recipe_fields = ( | 48 | |
| 49 | 'pn', | 49 | # RecipeInfoCommon defines common data retrieving methods |
| 50 | 'pv', | 50 | # from meta data for caches. CoreRecipeInfo as well as other |
| 51 | 'pr', | 51 | # Extra RecipeInfo needs to inherit this class |
| 52 | 'pe', | 52 | class RecipeInfoCommon(object): |
| 53 | 'defaultpref', | ||
| 54 | 'depends', | ||
| 55 | 'provides', | ||
| 56 | 'task_deps', | ||
| 57 | 'stamp', | ||
| 58 | 'stamp_extrainfo', | ||
| 59 | 'broken', | ||
| 60 | 'not_world', | ||
| 61 | 'skipped', | ||
| 62 | 'timestamp', | ||
| 63 | 'packages', | ||
| 64 | 'packages_dynamic', | ||
| 65 | 'rdepends', | ||
| 66 | 'rdepends_pkg', | ||
| 67 | 'rprovides', | ||
| 68 | 'rprovides_pkg', | ||
| 69 | 'rrecommends', | ||
| 70 | 'rrecommends_pkg', | ||
| 71 | 'nocache', | ||
| 72 | 'variants', | ||
| 73 | 'file_depends', | ||
| 74 | 'tasks', | ||
| 75 | 'basetaskhashes', | ||
| 76 | 'hashfilename', | ||
| 77 | 'inherits', | ||
| 78 | 'summary', | ||
| 79 | 'license', | ||
| 80 | 'section', | ||
| 81 | 'fakerootenv', | ||
| 82 | 'fakerootdirs' | ||
| 83 | ) | ||
| 84 | |||
| 85 | |||
| 86 | class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)): | ||
| 87 | __slots__ = () | ||
| 88 | 53 | ||
| 89 | @classmethod | 54 | @classmethod |
| 90 | def listvar(cls, var, metadata): | 55 | def listvar(cls, var, metadata): |
| @@ -117,69 +82,162 @@ class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)): | |||
| 117 | def getvar(cls, var, metadata): | 82 | def getvar(cls, var, metadata): |
| 118 | return metadata.getVar(var, True) or '' | 83 | return metadata.getVar(var, True) or '' |
| 119 | 84 | ||
| 120 | @classmethod | 85 | |
| 121 | def make_optional(cls, default=None, **kwargs): | 86 | class CoreRecipeInfo(RecipeInfoCommon): |
| 122 | """Construct the namedtuple from the specified keyword arguments, | 87 | __slots__ = () |
| 123 | with every value considered optional, using the default value if | 88 | |
| 124 | it was not specified.""" | 89 | def __init__(self, filename, metadata): |
| 125 | for field in cls._fields: | 90 | self.name = "base" |
| 126 | kwargs[field] = kwargs.get(field, default) | 91 | # please override this member with the correct data cache file |
| 127 | return cls(**kwargs) | 92 | # such as (bb_cache.dat, bb_extracache_hob.dat) |
| 93 | self.cachefile = "bb_cache.dat" | ||
| 94 | |||
| 95 | self.file_depends = metadata.getVar('__depends', False) | ||
| 96 | self.timestamp = bb.parse.cached_mtime(filename) | ||
| 97 | self.variants = self.listvar('__VARIANTS', metadata) + [''] | ||
| 98 | self.nocache = self.getvar('__BB_DONT_CACHE', metadata) | ||
| 99 | |||
| 100 | if self.getvar('__SKIPPED', metadata): | ||
| 101 | self.skipped = True | ||
| 102 | return | ||
| 103 | |||
| 104 | self.tasks = metadata.getVar('__BBTASKS', False) | ||
| 105 | |||
| 106 | self.pn = self.getvar('PN', metadata) | ||
| 107 | self.packages = self.listvar('PACKAGES', metadata) | ||
| 108 | if not self.pn in self.packages: | ||
| 109 | self.packages.append(self.pn) | ||
| 110 | |||
| 111 | self.basetaskhashes = self.taskvar('BB_BASEHASH', self.tasks, metadata) | ||
| 112 | self.hashfilename = self.getvar('BB_HASHFILENAME', metadata) | ||
| 113 | |||
| 114 | self.file_depends = metadata.getVar('__depends', False) | ||
| 115 | self.task_deps = metadata.getVar('_task_deps', False) or {'tasks': [], 'parents': {}} | ||
| 116 | |||
| 117 | self.skipped = False | ||
| 118 | self.pe = self.getvar('PE', metadata) | ||
| 119 | self.pv = self.getvar('PV', metadata) | ||
| 120 | self.pr = self.getvar('PR', metadata) | ||
| 121 | self.defaultpref = self.intvar('DEFAULT_PREFERENCE', metadata) | ||
| 122 | self.broken = self.getvar('BROKEN', metadata) | ||
| 123 | self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata) | ||
| 124 | self.stamp = self.getvar('STAMP', metadata) | ||
| 125 | self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata) | ||
| 126 | self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata) | ||
| 127 | self.depends = self.depvar('DEPENDS', metadata) | ||
| 128 | self.provides = self.depvar('PROVIDES', metadata) | ||
| 129 | self.rdepends = self.depvar('RDEPENDS', metadata) | ||
| 130 | self.rprovides = self.depvar('RPROVIDES', metadata) | ||
| 131 | self.rrecommends = self.depvar('RRECOMMENDS', metadata) | ||
| 132 | self.rprovides_pkg = self.pkgvar('RPROVIDES', self.packages, metadata) | ||
| 133 | self.rdepends_pkg = self.pkgvar('RDEPENDS', self.packages, metadata) | ||
| 134 | self.rrecommends_pkg = self.pkgvar('RRECOMMENDS', self.packages, metadata) | ||
| 135 | self.inherits = self.getvar('__inherit_cache', metadata) | ||
| 136 | self.summary = self.getvar('SUMMARY', metadata) | ||
| 137 | self.license = self.getvar('LICENSE', metadata) | ||
| 138 | self.section = self.getvar('SECTION', metadata) | ||
| 139 | self.fakerootenv = self.getvar('FAKEROOTENV', metadata) | ||
| 140 | self.fakerootdirs = self.getvar('FAKEROOTDIRS', metadata) | ||
| 128 | 141 | ||
| 129 | @classmethod | 142 | @classmethod |
| 130 | def from_metadata(cls, filename, metadata): | 143 | def init_cacheData(cls, cachedata): |
| 131 | if cls.getvar('__SKIPPED', metadata): | 144 | # CacheData in Core RecipeInfo Class |
| 132 | return cls.make_optional(skipped=True, | 145 | cachedata.task_deps = {} |
| 133 | file_depends=metadata.getVar('__depends', False), | 146 | cachedata.pkg_fn = {} |
| 134 | timestamp=bb.parse.cached_mtime(filename), | 147 | cachedata.pkg_pn = defaultdict(list) |
| 135 | variants=cls.listvar('__VARIANTS', metadata) + ['']) | 148 | cachedata.pkg_pepvpr = {} |
| 136 | 149 | cachedata.pkg_dp = {} | |
| 137 | tasks = metadata.getVar('__BBTASKS', False) | 150 | |
| 138 | 151 | cachedata.stamp = {} | |
| 139 | pn = cls.getvar('PN', metadata) | 152 | cachedata.stamp_extrainfo = {} |
| 140 | packages = cls.listvar('PACKAGES', metadata) | 153 | cachedata.fn_provides = {} |
| 141 | if not pn in packages: | 154 | cachedata.pn_provides = defaultdict(list) |
| 142 | packages.append(pn) | 155 | cachedata.all_depends = [] |
| 143 | 156 | ||
| 144 | return RecipeInfo( | 157 | cachedata.deps = defaultdict(list) |
| 145 | tasks = tasks, | 158 | cachedata.packages = defaultdict(list) |
| 146 | basetaskhashes = cls.taskvar('BB_BASEHASH', tasks, metadata), | 159 | cachedata.providers = defaultdict(list) |
| 147 | hashfilename = cls.getvar('BB_HASHFILENAME', metadata), | 160 | cachedata.rproviders = defaultdict(list) |
| 148 | 161 | cachedata.packages_dynamic = defaultdict(list) | |
| 149 | file_depends = metadata.getVar('__depends', False), | 162 | |
| 150 | task_deps = metadata.getVar('_task_deps', False) or | 163 | cachedata.rundeps = defaultdict(lambda: defaultdict(list)) |
| 151 | {'tasks': [], 'parents': {}}, | 164 | cachedata.runrecs = defaultdict(lambda: defaultdict(list)) |
| 152 | variants = cls.listvar('__VARIANTS', metadata) + [''], | 165 | cachedata.possible_world = [] |
| 153 | 166 | cachedata.universe_target = [] | |
| 154 | skipped = False, | 167 | cachedata.hashfn = {} |
| 155 | timestamp = bb.parse.cached_mtime(filename), | 168 | |
| 156 | packages = cls.listvar('PACKAGES', metadata), | 169 | cachedata.basetaskhash = {} |
| 157 | pn = pn, | 170 | cachedata.inherits = {} |
| 158 | pe = cls.getvar('PE', metadata), | 171 | cachedata.summary = {} |
| 159 | pv = cls.getvar('PV', metadata), | 172 | cachedata.license = {} |
| 160 | pr = cls.getvar('PR', metadata), | 173 | cachedata.section = {} |
| 161 | nocache = cls.getvar('__BB_DONT_CACHE', metadata), | 174 | cachedata.fakerootenv = {} |
| 162 | defaultpref = cls.intvar('DEFAULT_PREFERENCE', metadata), | 175 | cachedata.fakerootdirs = {} |
| 163 | broken = cls.getvar('BROKEN', metadata), | 176 | |
| 164 | not_world = cls.getvar('EXCLUDE_FROM_WORLD', metadata), | 177 | def add_cacheData(self, cachedata, fn): |
| 165 | stamp = cls.getvar('STAMP', metadata), | 178 | cachedata.task_deps[fn] = self.task_deps |
| 166 | stamp_extrainfo = cls.flaglist('stamp-extra-info', tasks, metadata), | 179 | cachedata.pkg_fn[fn] = self.pn |
| 167 | packages_dynamic = cls.listvar('PACKAGES_DYNAMIC', metadata), | 180 | cachedata.pkg_pn[self].append(fn) |
| 168 | depends = cls.depvar('DEPENDS', metadata), | 181 | cachedata.pkg_pepvpr[fn] = (self.pe, self.pv, self.pr) |
| 169 | provides = cls.depvar('PROVIDES', metadata), | 182 | cachedata.pkg_dp[fn] = self.defaultpref |
| 170 | rdepends = cls.depvar('RDEPENDS', metadata), | 183 | cachedata.stamp[fn] = self.stamp |
| 171 | rprovides = cls.depvar('RPROVIDES', metadata), | 184 | cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo |
| 172 | rrecommends = cls.depvar('RRECOMMENDS', metadata), | 185 | |
| 173 | rprovides_pkg = cls.pkgvar('RPROVIDES', packages, metadata), | 186 | provides = [self.pn] |
| 174 | rdepends_pkg = cls.pkgvar('RDEPENDS', packages, metadata), | 187 | for provide in self.provides: |
| 175 | rrecommends_pkg = cls.pkgvar('RRECOMMENDS', packages, metadata), | 188 | if provide not in provides: |
| 176 | inherits = cls.getvar('__inherit_cache', metadata), | 189 | provides.append(provide) |
| 177 | summary = cls.getvar('SUMMARY', metadata), | 190 | cachedata.fn_provides[fn] = provides |
| 178 | license = cls.getvar('LICENSE', metadata), | 191 | |
| 179 | section = cls.getvar('SECTION', metadata), | 192 | for provide in provides: |
| 180 | fakerootenv = cls.getvar('FAKEROOTENV', metadata), | 193 | cachedata.providers[provide].append(fn) |
| 181 | fakerootdirs = cls.getvar('FAKEROOTDIRS', metadata), | 194 | if provide not in cachedata.pn_provides[self.pn]: |
| 182 | ) | 195 | cachedata.pn_provides[self.pn].append(provide) |
| 196 | |||
| 197 | for dep in self.depends: | ||
| 198 | if dep not in cachedata.deps[fn]: | ||
| 199 | cachedata.deps[fn].append(dep) | ||
| 200 | if dep not in cachedata.all_depends: | ||
| 201 | cachedata.all_depends.append(dep) | ||
| 202 | |||
| 203 | rprovides = self.rprovides | ||
| 204 | for package in self.packages: | ||
| 205 | cachedata.packages[package].append(fn) | ||
| 206 | rprovides += self.rprovides_pkg[package] | ||
| 207 | |||
| 208 | for rprovide in rprovides: | ||
| 209 | cachedata.rproviders[rprovide].append(fn) | ||
| 210 | |||
| 211 | for package in self.packages_dynamic: | ||
| 212 | cachedata.packages_dynamic[package].append(fn) | ||
| 213 | |||
| 214 | # Build hash of runtime depends and rececommends | ||
| 215 | for package in self.packages + [self.pn]: | ||
| 216 | cachedata.rundeps[fn][package] = list(self.rdepends) + self.rdepends_pkg[package] | ||
| 217 | cachedata.runrecs[fn][package] = list(self.rrecommends) + self.rrecommends_pkg[package] | ||
| 218 | |||
| 219 | # Collect files we may need for possible world-dep | ||
| 220 | # calculations | ||
| 221 | if not self.broken and not self.not_world: | ||
| 222 | cachedata.possible_world.append(fn) | ||
| 223 | |||
| 224 | # create a collection of all targets for sanity checking | ||
| 225 | # tasks, such as upstream versions, license, and tools for | ||
| 226 | # task and image creation. | ||
| 227 | cachedata.universe_target.append(self.pn) | ||
| 228 | |||
| 229 | cachedata.hashfn[fn] = self.hashfilename | ||
| 230 | for task, taskhash in self.basetaskhashes.iteritems(): | ||
| 231 | identifier = '%s.%s' % (fn, task) | ||
| 232 | cachedata.basetaskhash[identifier] = taskhash | ||
| 233 | |||
| 234 | cachedata.inherits[fn] = self.inherits | ||
| 235 | cachedata.summary[fn] = self.summary | ||
| 236 | cachedata.license[fn] = self.license | ||
| 237 | cachedata.section[fn] = self.section | ||
| 238 | cachedata.fakerootenv[fn] = self.fakerootenv | ||
| 239 | cachedata.fakerootdirs[fn] = self.fakerootdirs | ||
| 240 | |||
| 183 | 241 | ||
| 184 | 242 | ||
| 185 | class Cache(object): | 243 | class Cache(object): |
| @@ -314,7 +372,7 @@ class Cache(object): | |||
| 314 | depends |= (data.getVar("__depends", False) or set()) | 372 | depends |= (data.getVar("__depends", False) or set()) |
| 315 | if depends and not variant: | 373 | if depends and not variant: |
| 316 | data.setVar("__depends", depends) | 374 | data.setVar("__depends", depends) |
| 317 | info = RecipeInfo.from_metadata(filename, data) | 375 | info = CoreRecipeInfo(filename, data) |
| 318 | infos.append((virtualfn, info)) | 376 | infos.append((virtualfn, info)) |
| 319 | return infos | 377 | return infos |
| 320 | 378 | ||
| @@ -500,7 +558,7 @@ class Cache(object): | |||
| 500 | """ | 558 | """ |
| 501 | 559 | ||
| 502 | realfn = self.virtualfn2realfn(file_name)[0] | 560 | realfn = self.virtualfn2realfn(file_name)[0] |
| 503 | info = RecipeInfo.from_metadata(realfn, data) | 561 | info = CoreRecipeInfo(realfn, data) |
| 504 | self.add_info(file_name, info, cacheData, parsed) | 562 | self.add_info(file_name, info, cacheData, parsed) |
| 505 | 563 | ||
| 506 | @staticmethod | 564 | @staticmethod |
| @@ -566,38 +624,11 @@ class CacheData(object): | |||
| 566 | """ | 624 | """ |
| 567 | 625 | ||
| 568 | def __init__(self): | 626 | def __init__(self): |
| 627 | CoreRecipeInfo.init_cacheData(self) | ||
| 569 | # Direct cache variables | 628 | # Direct cache variables |
| 570 | self.providers = defaultdict(list) | ||
| 571 | self.rproviders = defaultdict(list) | ||
| 572 | self.packages = defaultdict(list) | ||
| 573 | self.packages_dynamic = defaultdict(list) | ||
| 574 | self.possible_world = [] | ||
| 575 | self.universe_target = [] | ||
| 576 | self.pkg_pn = defaultdict(list) | ||
| 577 | self.pkg_fn = {} | ||
| 578 | self.pkg_pepvpr = {} | ||
| 579 | self.pkg_dp = {} | ||
| 580 | self.pn_provides = defaultdict(list) | ||
| 581 | self.fn_provides = {} | ||
| 582 | self.all_depends = [] | ||
| 583 | self.deps = defaultdict(list) | ||
| 584 | self.rundeps = defaultdict(lambda: defaultdict(list)) | ||
| 585 | self.runrecs = defaultdict(lambda: defaultdict(list)) | ||
| 586 | self.task_queues = {} | 629 | self.task_queues = {} |
| 587 | self.task_deps = {} | ||
| 588 | self.stamp = {} | ||
| 589 | self.stamp_extrainfo = {} | ||
| 590 | self.preferred = {} | 630 | self.preferred = {} |
| 591 | self.tasks = {} | 631 | self.tasks = {} |
| 592 | self.basetaskhash = {} | ||
| 593 | self.hashfn = {} | ||
| 594 | self.inherits = {} | ||
| 595 | self.summary = {} | ||
| 596 | self.license = {} | ||
| 597 | self.section = {} | ||
| 598 | self.fakerootenv = {} | ||
| 599 | self.fakerootdirs = {} | ||
| 600 | |||
| 601 | # Indirect Cache variables (set elsewhere) | 632 | # Indirect Cache variables (set elsewhere) |
| 602 | self.ignored_dependencies = [] | 633 | self.ignored_dependencies = [] |
| 603 | self.world_target = set() | 634 | self.world_target = set() |
| @@ -605,65 +636,6 @@ class CacheData(object): | |||
| 605 | self.bbfile_config_priorities = [] | 636 | self.bbfile_config_priorities = [] |
| 606 | 637 | ||
| 607 | def add_from_recipeinfo(self, fn, info): | 638 | def add_from_recipeinfo(self, fn, info): |
| 608 | self.task_deps[fn] = info.task_deps | 639 | info.add_cacheData(self, fn) |
| 609 | self.pkg_fn[fn] = info.pn | ||
| 610 | self.pkg_pn[info.pn].append(fn) | ||
| 611 | self.pkg_pepvpr[fn] = (info.pe, info.pv, info.pr) | ||
| 612 | self.pkg_dp[fn] = info.defaultpref | ||
| 613 | self.stamp[fn] = info.stamp | ||
| 614 | self.stamp_extrainfo[fn] = info.stamp_extrainfo | ||
| 615 | |||
| 616 | provides = [info.pn] | ||
| 617 | for provide in info.provides: | ||
| 618 | if provide not in provides: | ||
| 619 | provides.append(provide) | ||
| 620 | self.fn_provides[fn] = provides | ||
| 621 | |||
| 622 | for provide in provides: | ||
| 623 | self.providers[provide].append(fn) | ||
| 624 | if provide not in self.pn_provides[info.pn]: | ||
| 625 | self.pn_provides[info.pn].append(provide) | ||
| 626 | |||
| 627 | for dep in info.depends: | ||
| 628 | if dep not in self.deps[fn]: | ||
| 629 | self.deps[fn].append(dep) | ||
| 630 | if dep not in self.all_depends: | ||
| 631 | self.all_depends.append(dep) | ||
| 632 | |||
| 633 | rprovides = info.rprovides | ||
| 634 | for package in info.packages: | ||
| 635 | self.packages[package].append(fn) | ||
| 636 | rprovides += info.rprovides_pkg[package] | ||
| 637 | 640 | ||
| 638 | for rprovide in rprovides: | 641 | |
| 639 | self.rproviders[rprovide].append(fn) | ||
| 640 | |||
| 641 | for package in info.packages_dynamic: | ||
| 642 | self.packages_dynamic[package].append(fn) | ||
| 643 | |||
| 644 | # Build hash of runtime depends and rececommends | ||
| 645 | for package in info.packages + [info.pn]: | ||
| 646 | self.rundeps[fn][package] = list(info.rdepends) + info.rdepends_pkg[package] | ||
| 647 | self.runrecs[fn][package] = list(info.rrecommends) + info.rrecommends_pkg[package] | ||
| 648 | |||
| 649 | # Collect files we may need for possible world-dep | ||
| 650 | # calculations | ||
| 651 | if not info.broken and not info.not_world: | ||
| 652 | self.possible_world.append(fn) | ||
| 653 | |||
| 654 | # create a collection of all targets for sanity checking | ||
| 655 | # tasks, such as upstream versions, license, and tools for | ||
| 656 | # task and image creation. | ||
| 657 | self.universe_target.append(info.pn) | ||
| 658 | |||
| 659 | self.hashfn[fn] = info.hashfilename | ||
| 660 | for task, taskhash in info.basetaskhashes.iteritems(): | ||
| 661 | identifier = '%s.%s' % (fn, task) | ||
| 662 | self.basetaskhash[identifier] = taskhash | ||
| 663 | |||
| 664 | self.inherits[fn] = info.inherits | ||
| 665 | self.summary[fn] = info.summary | ||
| 666 | self.license[fn] = info.license | ||
| 667 | self.section[fn] = info.section | ||
| 668 | self.fakerootenv[fn] = info.fakerootenv | ||
| 669 | self.fakerootdirs[fn] = info.fakerootdirs | ||
