1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
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
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.
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.
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.
25 from bb import data, utils
28 class NoProvider(Exception):
29 """Exception raised when no provider of a build dependency can be found"""
31 class NoRProvider(Exception):
32 """Exception raised when no provider of a runtime dependency can be found"""
34 def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
36 If there is a PREFERRED_VERSION, find the highest-priority bbfile
37 providing that version. If not, find the latest version provided by
38 an bbfile in the highest-priority set.
41 pkg_pn = dataCache.pkg_pn
46 priority = dataCache.bbfile_priority[f]
47 if priority not in priorities:
48 priorities[priority] = []
49 priorities[priority].append(f)
50 p_list = priorities.keys()
51 p_list.sort(lambda a, b: a - b)
54 tmp_pn = [priorities[p]] + tmp_pn
58 localdata = data.createCopy(cfgData)
59 bb.data.setVar('OVERRIDES', "pn-%s:%s:%s" % (pn, pn, data.getVar('OVERRIDES', localdata)), localdata)
60 bb.data.update_data(localdata)
62 preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, True)
64 m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
67 preferred_e = int(m.group(1)[:-1])
70 preferred_v = m.group(2)
72 preferred_r = m.group(3)[1:]
79 for file_set in tmp_pn:
81 pe,pv,pr = dataCache.pkg_pepvpr[f]
82 if preferred_v == pv and (preferred_r == pr or preferred_r == None) and (preferred_e == pe or preferred_e == None):
84 preferred_ver = (pe, pv, pr)
89 pv_str = '%s-%s' % (preferred_v, preferred_r)
92 if not (preferred_e is None):
93 pv_str = '%s:%s' % (preferred_e, pv_str)
96 itemstr = " (for item %s)" % item
97 if preferred_file is None:
98 bb.msg.note(1, bb.msg.domain.Provider, "preferred version %s of %s not available%s" % (pv_str, pn, itemstr))
100 bb.msg.debug(1, bb.msg.domain.Provider, "selecting %s as PREFERRED_VERSION %s of package %s%s" % (preferred_file, pv_str, pn, itemstr))
104 # get highest priority file set
109 for file_name in files:
110 pe,pv,pr = dataCache.pkg_pepvpr[file_name]
111 dp = dataCache.pkg_dp[file_name]
113 if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pe, pv, pr)) < 0)) or (dp > latest_p):
114 latest = (pe, pv, pr)
117 if preferred_file is None:
118 preferred_file = latest_f
119 preferred_ver = latest
121 return (latest,latest_f,preferred_ver, preferred_file)
123 def filterProviders(providers, item, cfgData, dataCache):
125 Take a list of providers and filter/reorder according to the
126 environment variables and previous build results
129 preferred_versions = {}
131 # Collate providers by PN
134 pn = dataCache.pkg_fn[p]
139 bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
141 for pn in pkg_pn.keys():
142 preferred_versions[pn] = bb.providers.findBestProvider(pn, cfgData, dataCache, pkg_pn, item)[2:4]
143 eligible.append(preferred_versions[pn][1])
145 if len(eligible) == 0:
146 bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
150 # If pn == item, give it a slight default preference
151 # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
153 pn = dataCache.pkg_fn[p]
156 (newvers, fn) = preferred_versions[pn]
157 if not fn in eligible:
160 eligible = [fn] + eligible
162 # look to see if one of them is already staged, or marked as preferred.
163 # if so, bump it to the head of the queue
165 pn = dataCache.pkg_fn[p]
166 pe, pv, pr = dataCache.pkg_pepvpr[p]
168 stamp = '%s.do_populate_staging' % dataCache.stamp[p]
169 if os.path.exists(stamp):
170 (newvers, fn) = preferred_versions[pn]
171 if not fn in eligible:
172 # package was made ineligible by already-failed check
174 oldver = "%s-%s" % (pv, pr)
176 oldver = "%s:%s" % (pe, oldver)
177 newver = "%s-%s" % (newvers[1], newvers[2])
179 newver = "%s:%s" % (newvers[0], newver)
180 if (newver != oldver):
181 extra_chat = "%s (%s) already staged but upgrading to %s to satisfy %s" % (pn, oldver, newver, item)
183 extra_chat = "Selecting already-staged %s (%s) to satisfy %s" % (pn, oldver, item)
185 bb.msg.note(2, bb.msg.domain.Provider, "%s" % extra_chat)
187 eligible = [fn] + eligible
192 def getRuntimeProviders(dataCache, rdepend):
194 Return any providers of runtime dependency
198 if rdepend in dataCache.rproviders:
199 rproviders += dataCache.rproviders[rdepend]
201 if rdepend in dataCache.packages:
202 rproviders += dataCache.packages[rdepend]
207 # Only search dynamic packages if we can't find anything in other variables
208 for pattern in dataCache.packages_dynamic:
209 regexp = re.compile(pattern)
210 if regexp.match(rdepend):
211 rproviders += dataCache.packages_dynamic[pattern]