diff options
Diffstat (limited to 'bitbake')
-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 | ||