diff options
Diffstat (limited to 'bitbake-dev/lib/bb/providers.py')
-rw-r--r-- | bitbake-dev/lib/bb/providers.py | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/bitbake-dev/lib/bb/providers.py b/bitbake-dev/lib/bb/providers.py deleted file mode 100644 index 8617251ca3..0000000000 --- a/bitbake-dev/lib/bb/providers.py +++ /dev/null | |||
@@ -1,327 +0,0 @@ | |||
1 | # ex:ts=4:sw=4:sts=4:et | ||
2 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | ||
3 | # | ||
4 | # Copyright (C) 2003, 2004 Chris Larson | ||
5 | # Copyright (C) 2003, 2004 Phil Blundell | ||
6 | # Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer | ||
7 | # Copyright (C) 2005 Holger Hans Peter Freyther | ||
8 | # Copyright (C) 2005 ROAD GmbH | ||
9 | # Copyright (C) 2006 Richard Purdie | ||
10 | # | ||
11 | # This program is free software; you can redistribute it and/or modify | ||
12 | # it under the terms of the GNU General Public License version 2 as | ||
13 | # published by the Free Software Foundation. | ||
14 | # | ||
15 | # This program is distributed in the hope that it will be useful, | ||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | # GNU General Public License for more details. | ||
19 | # | ||
20 | # You should have received a copy of the GNU General Public License along | ||
21 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
23 | |||
24 | import re | ||
25 | from bb import data, utils | ||
26 | import bb | ||
27 | |||
28 | class NoProvider(Exception): | ||
29 | """Exception raised when no provider of a build dependency can be found""" | ||
30 | |||
31 | class NoRProvider(Exception): | ||
32 | """Exception raised when no provider of a runtime dependency can be found""" | ||
33 | |||
34 | |||
35 | def sortPriorities(pn, dataCache, pkg_pn = None): | ||
36 | """ | ||
37 | Reorder pkg_pn by file priority and default preference | ||
38 | """ | ||
39 | |||
40 | if not pkg_pn: | ||
41 | pkg_pn = dataCache.pkg_pn | ||
42 | |||
43 | files = pkg_pn[pn] | ||
44 | priorities = {} | ||
45 | for f in files: | ||
46 | priority = dataCache.bbfile_priority[f] | ||
47 | preference = dataCache.pkg_dp[f] | ||
48 | if priority not in priorities: | ||
49 | priorities[priority] = {} | ||
50 | if preference not in priorities[priority]: | ||
51 | priorities[priority][preference] = [] | ||
52 | priorities[priority][preference].append(f) | ||
53 | pri_list = priorities.keys() | ||
54 | pri_list.sort(lambda a, b: a - b) | ||
55 | tmp_pn = [] | ||
56 | for pri in pri_list: | ||
57 | pref_list = priorities[pri].keys() | ||
58 | pref_list.sort(lambda a, b: b - a) | ||
59 | tmp_pref = [] | ||
60 | for pref in pref_list: | ||
61 | tmp_pref.extend(priorities[pri][pref]) | ||
62 | tmp_pn = [tmp_pref] + tmp_pn | ||
63 | |||
64 | return tmp_pn | ||
65 | |||
66 | def preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r): | ||
67 | """ | ||
68 | Check if the version pe,pv,pr is the preferred one. | ||
69 | If there is preferred version defined and ends with '%', then pv has to start with that version after removing the '%' | ||
70 | """ | ||
71 | if (pr == preferred_r or preferred_r == None): | ||
72 | if (pe == preferred_e or preferred_e == None): | ||
73 | if preferred_v == pv: | ||
74 | return True | ||
75 | if preferred_v != None and preferred_v.endswith('%') and pv.startswith(preferred_v[:len(preferred_v)-1]): | ||
76 | return True | ||
77 | return False | ||
78 | |||
79 | def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None): | ||
80 | """ | ||
81 | Find the first provider in pkg_pn with a PREFERRED_VERSION set. | ||
82 | """ | ||
83 | |||
84 | preferred_file = None | ||
85 | preferred_ver = None | ||
86 | |||
87 | localdata = data.createCopy(cfgData) | ||
88 | bb.data.setVar('OVERRIDES', "pn-%s:%s:%s" % (pn, pn, data.getVar('OVERRIDES', localdata)), localdata) | ||
89 | bb.data.update_data(localdata) | ||
90 | |||
91 | preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, True) | ||
92 | if preferred_v: | ||
93 | m = re.match('(\d+:)*(.*)(_.*)*', preferred_v) | ||
94 | if m: | ||
95 | if m.group(1): | ||
96 | preferred_e = int(m.group(1)[:-1]) | ||
97 | else: | ||
98 | preferred_e = None | ||
99 | preferred_v = m.group(2) | ||
100 | if m.group(3): | ||
101 | preferred_r = m.group(3)[1:] | ||
102 | else: | ||
103 | preferred_r = None | ||
104 | else: | ||
105 | preferred_e = None | ||
106 | preferred_r = None | ||
107 | |||
108 | for file_set in pkg_pn: | ||
109 | for f in file_set: | ||
110 | pe,pv,pr = dataCache.pkg_pepvpr[f] | ||
111 | if preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r): | ||
112 | preferred_file = f | ||
113 | preferred_ver = (pe, pv, pr) | ||
114 | break | ||
115 | if preferred_file: | ||
116 | break; | ||
117 | if preferred_r: | ||
118 | pv_str = '%s-%s' % (preferred_v, preferred_r) | ||
119 | else: | ||
120 | pv_str = preferred_v | ||
121 | if not (preferred_e is None): | ||
122 | pv_str = '%s:%s' % (preferred_e, pv_str) | ||
123 | itemstr = "" | ||
124 | if item: | ||
125 | itemstr = " (for item %s)" % item | ||
126 | if preferred_file is None: | ||
127 | bb.msg.note(1, bb.msg.domain.Provider, "preferred version %s of %s not available%s" % (pv_str, pn, itemstr)) | ||
128 | else: | ||
129 | bb.msg.debug(1, bb.msg.domain.Provider, "selecting %s as PREFERRED_VERSION %s of package %s%s" % (preferred_file, pv_str, pn, itemstr)) | ||
130 | |||
131 | return (preferred_ver, preferred_file) | ||
132 | |||
133 | |||
134 | def findLatestProvider(pn, cfgData, dataCache, file_set): | ||
135 | """ | ||
136 | Return the highest version of the providers in file_set. | ||
137 | Take default preferences into account. | ||
138 | """ | ||
139 | latest = None | ||
140 | latest_p = 0 | ||
141 | latest_f = None | ||
142 | for file_name in file_set: | ||
143 | pe,pv,pr = dataCache.pkg_pepvpr[file_name] | ||
144 | dp = dataCache.pkg_dp[file_name] | ||
145 | |||
146 | if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pe, pv, pr)) < 0)) or (dp > latest_p): | ||
147 | latest = (pe, pv, pr) | ||
148 | latest_f = file_name | ||
149 | latest_p = dp | ||
150 | |||
151 | return (latest, latest_f) | ||
152 | |||
153 | |||
154 | def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None): | ||
155 | """ | ||
156 | If there is a PREFERRED_VERSION, find the highest-priority bbfile | ||
157 | providing that version. If not, find the latest version provided by | ||
158 | an bbfile in the highest-priority set. | ||
159 | """ | ||
160 | |||
161 | sortpkg_pn = sortPriorities(pn, dataCache, pkg_pn) | ||
162 | # Find the highest priority provider with a PREFERRED_VERSION set | ||
163 | (preferred_ver, preferred_file) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item) | ||
164 | # Find the latest version of the highest priority provider | ||
165 | (latest, latest_f) = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[0]) | ||
166 | |||
167 | if preferred_file is None: | ||
168 | preferred_file = latest_f | ||
169 | preferred_ver = latest | ||
170 | |||
171 | return (latest, latest_f, preferred_ver, preferred_file) | ||
172 | |||
173 | |||
174 | def _filterProviders(providers, item, cfgData, dataCache): | ||
175 | """ | ||
176 | Take a list of providers and filter/reorder according to the | ||
177 | environment variables and previous build results | ||
178 | """ | ||
179 | eligible = [] | ||
180 | preferred_versions = {} | ||
181 | sortpkg_pn = {} | ||
182 | |||
183 | # The order of providers depends on the order of the files on the disk | ||
184 | # up to here. Sort pkg_pn to make dependency issues reproducible rather | ||
185 | # than effectively random. | ||
186 | providers.sort() | ||
187 | |||
188 | # Collate providers by PN | ||
189 | pkg_pn = {} | ||
190 | for p in providers: | ||
191 | pn = dataCache.pkg_fn[p] | ||
192 | if pn not in pkg_pn: | ||
193 | pkg_pn[pn] = [] | ||
194 | pkg_pn[pn].append(p) | ||
195 | |||
196 | bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys())) | ||
197 | |||
198 | # First add PREFERRED_VERSIONS | ||
199 | for pn in pkg_pn.keys(): | ||
200 | sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn) | ||
201 | preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item) | ||
202 | if preferred_versions[pn][1]: | ||
203 | eligible.append(preferred_versions[pn][1]) | ||
204 | |||
205 | # Now add latest verisons | ||
206 | for pn in sortpkg_pn.keys(): | ||
207 | if pn in preferred_versions and preferred_versions[pn][1]: | ||
208 | continue | ||
209 | preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0]) | ||
210 | eligible.append(preferred_versions[pn][1]) | ||
211 | |||
212 | if len(eligible) == 0: | ||
213 | bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item) | ||
214 | return 0 | ||
215 | |||
216 | # If pn == item, give it a slight default preference | ||
217 | # This means PREFERRED_PROVIDER_foobar defaults to foobar if available | ||
218 | for p in providers: | ||
219 | pn = dataCache.pkg_fn[p] | ||
220 | if pn != item: | ||
221 | continue | ||
222 | (newvers, fn) = preferred_versions[pn] | ||
223 | if not fn in eligible: | ||
224 | continue | ||
225 | eligible.remove(fn) | ||
226 | eligible = [fn] + eligible | ||
227 | |||
228 | return eligible | ||
229 | |||
230 | |||
231 | def filterProviders(providers, item, cfgData, dataCache): | ||
232 | """ | ||
233 | Take a list of providers and filter/reorder according to the | ||
234 | environment variables and previous build results | ||
235 | Takes a "normal" target item | ||
236 | """ | ||
237 | |||
238 | eligible = _filterProviders(providers, item, cfgData, dataCache) | ||
239 | |||
240 | prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, cfgData, 1) | ||
241 | if prefervar: | ||
242 | dataCache.preferred[item] = prefervar | ||
243 | |||
244 | foundUnique = False | ||
245 | if item in dataCache.preferred: | ||
246 | for p in eligible: | ||
247 | pn = dataCache.pkg_fn[p] | ||
248 | if dataCache.preferred[item] == pn: | ||
249 | bb.msg.note(2, bb.msg.domain.Provider, "selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item)) | ||
250 | eligible.remove(p) | ||
251 | eligible = [p] + eligible | ||
252 | foundUnique = True | ||
253 | break | ||
254 | |||
255 | bb.msg.debug(1, bb.msg.domain.Provider, "sorted providers for %s are: %s" % (item, eligible)) | ||
256 | |||
257 | return eligible, foundUnique | ||
258 | |||
259 | def filterProvidersRunTime(providers, item, cfgData, dataCache): | ||
260 | """ | ||
261 | Take a list of providers and filter/reorder according to the | ||
262 | environment variables and previous build results | ||
263 | Takes a "runtime" target item | ||
264 | """ | ||
265 | |||
266 | eligible = _filterProviders(providers, item, cfgData, dataCache) | ||
267 | |||
268 | # Should use dataCache.preferred here? | ||
269 | preferred = [] | ||
270 | preferred_vars = [] | ||
271 | for p in eligible: | ||
272 | pn = dataCache.pkg_fn[p] | ||
273 | provides = dataCache.pn_provides[pn] | ||
274 | for provide in provides: | ||
275 | bb.msg.note(2, bb.msg.domain.Provider, "checking PREFERRED_PROVIDER_%s" % (provide)) | ||
276 | prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % provide, cfgData, 1) | ||
277 | if prefervar == pn: | ||
278 | var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar) | ||
279 | bb.msg.note(2, bb.msg.domain.Provider, "selecting %s to satisfy runtime %s due to %s" % (pn, item, var)) | ||
280 | preferred_vars.append(var) | ||
281 | eligible.remove(p) | ||
282 | eligible = [p] + eligible | ||
283 | preferred.append(p) | ||
284 | break | ||
285 | |||
286 | numberPreferred = len(preferred) | ||
287 | |||
288 | if numberPreferred > 1: | ||
289 | bb.msg.error(bb.msg.domain.Provider, "Conflicting PREFERRED_PROVIDER entries were found which resulted in an attempt to select multiple providers (%s) for runtime dependecy %s\nThe entries resulting in this conflict were: %s" % (preferred, item, preferred_vars)) | ||
290 | |||
291 | bb.msg.debug(1, bb.msg.domain.Provider, "sorted providers for %s are: %s" % (item, eligible)) | ||
292 | |||
293 | return eligible, numberPreferred | ||
294 | |||
295 | regexp_cache = {} | ||
296 | |||
297 | def getRuntimeProviders(dataCache, rdepend): | ||
298 | """ | ||
299 | Return any providers of runtime dependency | ||
300 | """ | ||
301 | rproviders = [] | ||
302 | |||
303 | if rdepend in dataCache.rproviders: | ||
304 | rproviders += dataCache.rproviders[rdepend] | ||
305 | |||
306 | if rdepend in dataCache.packages: | ||
307 | rproviders += dataCache.packages[rdepend] | ||
308 | |||
309 | if rproviders: | ||
310 | return rproviders | ||
311 | |||
312 | # Only search dynamic packages if we can't find anything in other variables | ||
313 | for pattern in dataCache.packages_dynamic: | ||
314 | pattern = pattern.replace('+', "\+") | ||
315 | if pattern in regexp_cache: | ||
316 | regexp = regexp_cache[pattern] | ||
317 | else: | ||
318 | try: | ||
319 | regexp = re.compile(pattern) | ||
320 | except: | ||
321 | bb.msg.error(bb.msg.domain.Provider, "Error parsing re expression: %s" % pattern) | ||
322 | raise | ||
323 | regexp_cache[pattern] = regexp | ||
324 | if regexp.match(rdepend): | ||
325 | rproviders += dataCache.packages_dynamic[pattern] | ||
326 | |||
327 | return rproviders | ||