summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib/bb/providers.py
diff options
context:
space:
mode:
authorRichard Purdie <richard@openedhand.com>2008-09-30 15:08:33 +0000
committerRichard Purdie <richard@openedhand.com>2008-09-30 15:08:33 +0000
commitc30eddb243e7e65f67f656e62848a033cf6f2e5c (patch)
tree110dd95788b76f55d31cb8d30aac2de8400b6f4a /bitbake-dev/lib/bb/providers.py
parent5ef0510474004eeb2ae8a99b64e2febb1920e077 (diff)
downloadpoky-c30eddb243e7e65f67f656e62848a033cf6f2e5c.tar.gz
Add bitbake-dev to allow ease of testing and development of bitbake trunk
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5337 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake-dev/lib/bb/providers.py')
-rw-r--r--bitbake-dev/lib/bb/providers.py303
1 files changed, 303 insertions, 0 deletions
diff --git a/bitbake-dev/lib/bb/providers.py b/bitbake-dev/lib/bb/providers.py
new file mode 100644
index 0000000000..0ad5876ef0
--- /dev/null
+++ b/bitbake-dev/lib/bb/providers.py
@@ -0,0 +1,303 @@
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
24import os, re
25from bb import data, utils
26import bb
27
28class NoProvider(Exception):
29 """Exception raised when no provider of a build dependency can be found"""
30
31class NoRProvider(Exception):
32 """Exception raised when no provider of a runtime dependency can be found"""
33
34
35def 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
67def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
68 """
69 Find the first provider in pkg_pn with a PREFERRED_VERSION set.
70 """
71
72 preferred_file = None
73 preferred_ver = None
74
75 localdata = data.createCopy(cfgData)
76 bb.data.setVar('OVERRIDES', "pn-%s:%s:%s" % (pn, pn, data.getVar('OVERRIDES', localdata)), localdata)
77 bb.data.update_data(localdata)
78
79 preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, True)
80 if preferred_v:
81 m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
82 if m:
83 if m.group(1):
84 preferred_e = int(m.group(1)[:-1])
85 else:
86 preferred_e = None
87 preferred_v = m.group(2)
88 if m.group(3):
89 preferred_r = m.group(3)[1:]
90 else:
91 preferred_r = None
92 else:
93 preferred_e = None
94 preferred_r = None
95
96 for file_set in pkg_pn:
97 for f in file_set:
98 pe,pv,pr = dataCache.pkg_pepvpr[f]
99 if preferred_v == pv and (preferred_r == pr or preferred_r == None) and (preferred_e == pe or preferred_e == None):
100 preferred_file = f
101 preferred_ver = (pe, pv, pr)
102 break
103 if preferred_file:
104 break;
105 if preferred_r:
106 pv_str = '%s-%s' % (preferred_v, preferred_r)
107 else:
108 pv_str = preferred_v
109 if not (preferred_e is None):
110 pv_str = '%s:%s' % (preferred_e, pv_str)
111 itemstr = ""
112 if item:
113 itemstr = " (for item %s)" % item
114 if preferred_file is None:
115 bb.msg.note(1, bb.msg.domain.Provider, "preferred version %s of %s not available%s" % (pv_str, pn, itemstr))
116 else:
117 bb.msg.debug(1, bb.msg.domain.Provider, "selecting %s as PREFERRED_VERSION %s of package %s%s" % (preferred_file, pv_str, pn, itemstr))
118
119 return (preferred_ver, preferred_file)
120
121
122def findLatestProvider(pn, cfgData, dataCache, file_set):
123 """
124 Return the highest version of the providers in file_set.
125 Take default preferences into account.
126 """
127 latest = None
128 latest_p = 0
129 latest_f = None
130 for file_name in file_set:
131 pe,pv,pr = dataCache.pkg_pepvpr[file_name]
132 dp = dataCache.pkg_dp[file_name]
133
134 if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pe, pv, pr)) < 0)) or (dp > latest_p):
135 latest = (pe, pv, pr)
136 latest_f = file_name
137 latest_p = dp
138
139 return (latest, latest_f)
140
141
142def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
143 """
144 If there is a PREFERRED_VERSION, find the highest-priority bbfile
145 providing that version. If not, find the latest version provided by
146 an bbfile in the highest-priority set.
147 """
148
149 sortpkg_pn = sortPriorities(pn, dataCache, pkg_pn)
150 # Find the highest priority provider with a PREFERRED_VERSION set
151 (preferred_ver, preferred_file) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item)
152 # Find the latest version of the highest priority provider
153 (latest, latest_f) = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[0])
154
155 if preferred_file is None:
156 preferred_file = latest_f
157 preferred_ver = latest
158
159 return (latest, latest_f, preferred_ver, preferred_file)
160
161
162def _filterProviders(providers, item, cfgData, dataCache):
163 """
164 Take a list of providers and filter/reorder according to the
165 environment variables and previous build results
166 """
167 eligible = []
168 preferred_versions = {}
169 sortpkg_pn = {}
170
171 # The order of providers depends on the order of the files on the disk
172 # up to here. Sort pkg_pn to make dependency issues reproducible rather
173 # than effectively random.
174 providers.sort()
175
176 # Collate providers by PN
177 pkg_pn = {}
178 for p in providers:
179 pn = dataCache.pkg_fn[p]
180 if pn not in pkg_pn:
181 pkg_pn[pn] = []
182 pkg_pn[pn].append(p)
183
184 bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
185
186 # First add PREFERRED_VERSIONS
187 for pn in pkg_pn.keys():
188 sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn)
189 preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
190 if preferred_versions[pn][1]:
191 eligible.append(preferred_versions[pn][1])
192
193 # Now add latest verisons
194 for pn in pkg_pn.keys():
195 if pn in preferred_versions and preferred_versions[pn][1]:
196 continue
197 preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0])
198 eligible.append(preferred_versions[pn][1])
199
200 if len(eligible) == 0:
201 bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
202 return 0
203
204 # If pn == item, give it a slight default preference
205 # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
206 for p in providers:
207 pn = dataCache.pkg_fn[p]
208 if pn != item:
209 continue
210 (newvers, fn) = preferred_versions[pn]
211 if not fn in eligible:
212 continue
213 eligible.remove(fn)
214 eligible = [fn] + eligible
215
216 return eligible
217
218
219def filterProviders(providers, item, cfgData, dataCache):
220 """
221 Take a list of providers and filter/reorder according to the
222 environment variables and previous build results
223 Takes a "normal" target item
224 """
225
226 eligible = _filterProviders(providers, item, cfgData, dataCache)
227
228 prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, cfgData, 1)
229 if prefervar:
230 dataCache.preferred[item] = prefervar
231
232 foundUnique = False
233 if item in dataCache.preferred:
234 for p in eligible:
235 pn = dataCache.pkg_fn[p]
236 if dataCache.preferred[item] == pn:
237 bb.msg.note(2, bb.msg.domain.Provider, "selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
238 eligible.remove(p)
239 eligible = [p] + eligible
240 foundUnique = True
241 break
242
243 bb.msg.debug(1, bb.msg.domain.Provider, "sorted providers for %s are: %s" % (item, eligible))
244
245 return eligible, foundUnique
246
247def filterProvidersRunTime(providers, item, cfgData, dataCache):
248 """
249 Take a list of providers and filter/reorder according to the
250 environment variables and previous build results
251 Takes a "runtime" target item
252 """
253
254 eligible = _filterProviders(providers, item, cfgData, dataCache)
255
256 # Should use dataCache.preferred here?
257 preferred = []
258 preferred_vars = []
259 for p in eligible:
260 pn = dataCache.pkg_fn[p]
261 provides = dataCache.pn_provides[pn]
262 for provide in provides:
263 prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % provide, cfgData, 1)
264 if prefervar == pn:
265 var = "PREFERRED_PROVIDERS_%s = %s" % (provide, prefervar)
266 bb.msg.note(2, bb.msg.domain.Provider, "selecting %s to satisfy runtime %s due to %s" % (pn, item, var))
267 preferred_vars.append(var)
268 eligible.remove(p)
269 eligible = [p] + eligible
270 preferred.append(p)
271 break
272
273 numberPreferred = len(preferred)
274
275 if numberPreferred > 1:
276 bb.msg.error(bb.msg.domain.Provider, "Conflicting PREFERRED_PROVIDERS 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))
277
278 bb.msg.debug(1, bb.msg.domain.Provider, "sorted providers for %s are: %s" % (item, eligible))
279
280 return eligible, numberPreferred
281
282def getRuntimeProviders(dataCache, rdepend):
283 """
284 Return any providers of runtime dependency
285 """
286 rproviders = []
287
288 if rdepend in dataCache.rproviders:
289 rproviders += dataCache.rproviders[rdepend]
290
291 if rdepend in dataCache.packages:
292 rproviders += dataCache.packages[rdepend]
293
294 if rproviders:
295 return rproviders
296
297 # Only search dynamic packages if we can't find anything in other variables
298 for pattern in dataCache.packages_dynamic:
299 regexp = re.compile(pattern)
300 if regexp.match(rdepend):
301 rproviders += dataCache.packages_dynamic[pattern]
302
303 return rproviders