diff options
Diffstat (limited to 'bitbake/lib/bb/providers.py')
| -rw-r--r-- | bitbake/lib/bb/providers.py | 209 |
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 | |||
| 25 | import os, re | ||
| 26 | from bb import data, utils | ||
| 27 | import bb | ||
| 28 | |||
| 29 | class NoProvider(Exception): | ||
| 30 | """Exception raised when no provider of a build dependency can be found""" | ||
| 31 | |||
| 32 | class NoRProvider(Exception): | ||
| 33 | """Exception raised when no provider of a runtime dependency can be found""" | ||
| 34 | |||
| 35 | def 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 | # | ||
| 117 | def 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 | |||
| 188 | def 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 | ||
