summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/providers.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/providers.py')
-rw-r--r--bitbake/lib/bb/providers.py209
1 files changed, 209 insertions, 0 deletions
diff --git a/bitbake/lib/bb/providers.py b/bitbake/lib/bb/providers.py
new file mode 100644
index 0000000000..3cb7cc1f07
--- /dev/null
+++ b/bitbake/lib/bb/providers.py
@@ -0,0 +1,209 @@
1#!/usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# Copyright (C) 2003, 2004 Chris Larson
6# Copyright (C) 2003, 2004 Phil Blundell
7# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
8# Copyright (C) 2005 Holger Hans Peter Freyther
9# Copyright (C) 2005 ROAD GmbH
10# Copyright (C) 2006 Richard Purdie
11#
12# This program is free software; you can redistribute it and/or modify it under
13# the terms of the GNU General Public License as published by the Free Software
14# Foundation; either version 2 of the License, or (at your option) any later
15# version.
16#
17# This program is distributed in the hope that it will be useful, but WITHOUT
18# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along with
22# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23# Place, Suite 330, Boston, MA 02111-1307 USA.
24
25import os, re
26from bb import data, utils
27import bb
28
29class NoProvider(Exception):
30 """Exception raised when no provider of a build dependency can be found"""
31
32class NoRProvider(Exception):
33 """Exception raised when no provider of a runtime dependency can be found"""
34
35def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
36 """
37 If there is a PREFERRED_VERSION, find the highest-priority bbfile
38 providing that version. If not, find the latest version provided by
39 an bbfile in the highest-priority set.
40 """
41 if not pkg_pn:
42 pkg_pn = dataCache.pkg_pn
43
44 files = pkg_pn[pn]
45 priorities = {}
46 for f in files:
47 priority = dataCache.bbfile_priority[f]
48 if priority not in priorities:
49 priorities[priority] = []
50 priorities[priority].append(f)
51 p_list = priorities.keys()
52 p_list.sort(lambda a, b: a - b)
53 tmp_pn = []
54 for p in p_list:
55 tmp_pn = [priorities[p]] + tmp_pn
56
57 preferred_file = None
58
59 localdata = data.createCopy(cfgData)
60 bb.data.setVar('OVERRIDES', "%s:%s" % (pn, data.getVar('OVERRIDES', localdata)), localdata)
61 bb.data.update_data(localdata)
62
63 preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, True)
64 if preferred_v:
65 m = re.match('(.*)_(.*)', preferred_v)
66 if m:
67 preferred_v = m.group(1)
68 preferred_r = m.group(2)
69 else:
70 preferred_r = None
71
72 for file_set in tmp_pn:
73 for f in file_set:
74 pv,pr = dataCache.pkg_pvpr[f]
75 if preferred_v == pv and (preferred_r == pr or preferred_r == None):
76 preferred_file = f
77 preferred_ver = (pv, pr)
78 break
79 if preferred_file:
80 break;
81 if preferred_r:
82 pv_str = '%s-%s' % (preferred_v, preferred_r)
83 else:
84 pv_str = preferred_v
85 itemstr = ""
86 if item:
87 itemstr = " (for item %s)" % item
88 if preferred_file is None:
89 bb.msg.note(1, bb.msg.domain.Provider, "preferred version %s of %s not available%s" % (pv_str, pn, itemstr))
90 else:
91 bb.msg.debug(1, bb.msg.domain.Provider, "selecting %s as PREFERRED_VERSION %s of package %s%s" % (preferred_file, pv_str, pn, itemstr))
92
93 del localdata
94
95 # get highest priority file set
96 files = tmp_pn[0]
97 latest = None
98 latest_p = 0
99 latest_f = None
100 for file_name in files:
101 pv,pr = dataCache.pkg_pvpr[file_name]
102 dp = dataCache.pkg_dp[file_name]
103
104 if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
105 latest = (pv, pr)
106 latest_f = file_name
107 latest_p = dp
108 if preferred_file is None:
109 preferred_file = latest_f
110 preferred_ver = latest
111
112 return (latest,latest_f,preferred_ver, preferred_file)
113
114#
115# RP - build_cache_fail needs to move elsewhere
116#
117def filterProviders(providers, item, cfgData, dataCache, build_cache_fail = {}):
118 """
119 Take a list of providers and filter/reorder according to the
120 environment variables and previous build results
121 """
122 eligible = []
123 preferred_versions = {}
124
125 # Collate providers by PN
126 pkg_pn = {}
127 for p in providers:
128 pn = dataCache.pkg_fn[p]
129 if pn not in pkg_pn:
130 pkg_pn[pn] = []
131 pkg_pn[pn].append(p)
132
133 bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
134
135 for pn in pkg_pn.keys():
136 preferred_versions[pn] = bb.providers.findBestProvider(pn, cfgData, dataCache, pkg_pn, item)[2:4]
137 eligible.append(preferred_versions[pn][1])
138
139
140 for p in eligible:
141 if p in build_cache_fail:
142 bb.msg.debug(1, bb.msg.domain.Provider, "rejecting already-failed %s" % p)
143 eligible.remove(p)
144
145 if len(eligible) == 0:
146 bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
147 return 0
148
149
150 # If pn == item, give it a slight default preference
151 # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
152 for p in providers:
153 pn = dataCache.pkg_fn[p]
154 if pn != item:
155 continue
156 (newvers, fn) = preferred_versions[pn]
157 if not fn in eligible:
158 continue
159 eligible.remove(fn)
160 eligible = [fn] + eligible
161
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
164 for p in providers:
165 pn = dataCache.pkg_fn[p]
166 pv, pr = dataCache.pkg_pvpr[p]
167
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
173 continue
174 oldver = "%s-%s" % (pv, pr)
175 newver = '-'.join(newvers)
176 if (newver != oldver):
177 extra_chat = "%s (%s) already staged but upgrading to %s to satisfy %s" % (pn, oldver, newver, item)
178 else:
179 extra_chat = "Selecting already-staged %s (%s) to satisfy %s" % (pn, oldver, item)
180
181 bb.msg.note(2, bb.msg.domain.Provider, "%s" % extra_chat)
182 eligible.remove(fn)
183 eligible = [fn] + eligible
184 break
185
186 return eligible
187
188def getRuntimeProviders(dataCache, rdepend):
189 """
190 Return any providers of runtime dependency
191 """
192 rproviders = []
193
194 if rdepend in dataCache.rproviders:
195 rproviders += dataCache.rproviders[rdepend]
196
197 if rdepend in dataCache.packages:
198 rproviders += dataCache.packages[rdepend]
199
200 if rproviders:
201 return rproviders
202
203 # Only search dynamic packages if we can't find anything in other variables
204 for pattern in dataCache.packages_dynamic:
205 regexp = re.compile(pattern)
206 if regexp.match(rdepend):
207 rproviders += dataCache.packages_dynamic[pattern]
208
209 return rproviders