providers.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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
  13. # it under the terms of the GNU General Public License version 2 as
  14. # published by the Free Software Foundation.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU General Public License along
  22. # with this program; if not, write to the Free Software Foundation, Inc.,
  23. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. import os, re
  25. from bb import data, utils
  26. import bb
  27. class NoProvider(Exception):
  28. """Exception raised when no provider of a build dependency can be found"""
  29. class NoRProvider(Exception):
  30. """Exception raised when no provider of a runtime dependency can be found"""
  31. def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
  32. """
  33. If there is a PREFERRED_VERSION, find the highest-priority bbfile
  34. providing that version. If not, find the latest version provided by
  35. an bbfile in the highest-priority set.
  36. """
  37. if not pkg_pn:
  38. pkg_pn = dataCache.pkg_pn
  39. files = pkg_pn[pn]
  40. priorities = {}
  41. for f in files:
  42. priority = dataCache.bbfile_priority[f]
  43. if priority not in priorities:
  44. priorities[priority] = []
  45. priorities[priority].append(f)
  46. p_list = priorities.keys()
  47. p_list.sort(lambda a, b: a - b)
  48. tmp_pn = []
  49. for p in p_list:
  50. tmp_pn = [priorities[p]] + tmp_pn
  51. preferred_file = None
  52. localdata = data.createCopy(cfgData)
  53. bb.data.setVar('OVERRIDES', "%s:%s" % (pn, data.getVar('OVERRIDES', localdata)), localdata)
  54. bb.data.update_data(localdata)
  55. preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, True)
  56. if preferred_v:
  57. m = re.match('(.*)_(.*)', preferred_v)
  58. if m:
  59. preferred_v = m.group(1)
  60. preferred_r = m.group(2)
  61. else:
  62. preferred_r = None
  63. for file_set in tmp_pn:
  64. for f in file_set:
  65. pv,pr = dataCache.pkg_pvpr[f]
  66. if preferred_v == pv and (preferred_r == pr or preferred_r == None):
  67. preferred_file = f
  68. preferred_ver = (pv, pr)
  69. break
  70. if preferred_file:
  71. break;
  72. if preferred_r:
  73. pv_str = '%s-%s' % (preferred_v, preferred_r)
  74. else:
  75. pv_str = preferred_v
  76. itemstr = ""
  77. if item:
  78. itemstr = " (for item %s)" % item
  79. if preferred_file is None:
  80. bb.msg.note(1, bb.msg.domain.Provider, "preferred version %s of %s not available%s" % (pv_str, pn, itemstr))
  81. else:
  82. bb.msg.debug(1, bb.msg.domain.Provider, "selecting %s as PREFERRED_VERSION %s of package %s%s" % (preferred_file, pv_str, pn, itemstr))
  83. del localdata
  84. # get highest priority file set
  85. files = tmp_pn[0]
  86. latest = None
  87. latest_p = 0
  88. latest_f = None
  89. for file_name in files:
  90. pv,pr = dataCache.pkg_pvpr[file_name]
  91. dp = dataCache.pkg_dp[file_name]
  92. if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
  93. latest = (pv, pr)
  94. latest_f = file_name
  95. latest_p = dp
  96. if preferred_file is None:
  97. preferred_file = latest_f
  98. preferred_ver = latest
  99. return (latest,latest_f,preferred_ver, preferred_file)
  100. #
  101. # RP - build_cache_fail needs to move elsewhere
  102. #
  103. def filterProviders(providers, item, cfgData, dataCache, build_cache_fail = {}):
  104. """
  105. Take a list of providers and filter/reorder according to the
  106. environment variables and previous build results
  107. """
  108. eligible = []
  109. preferred_versions = {}
  110. # Collate providers by PN
  111. pkg_pn = {}
  112. for p in providers:
  113. pn = dataCache.pkg_fn[p]
  114. if pn not in pkg_pn:
  115. pkg_pn[pn] = []
  116. pkg_pn[pn].append(p)
  117. bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
  118. for pn in pkg_pn.keys():
  119. preferred_versions[pn] = bb.providers.findBestProvider(pn, cfgData, dataCache, pkg_pn, item)[2:4]
  120. eligible.append(preferred_versions[pn][1])
  121. for p in eligible:
  122. if p in build_cache_fail:
  123. bb.msg.debug(1, bb.msg.domain.Provider, "rejecting already-failed %s" % p)
  124. eligible.remove(p)
  125. if len(eligible) == 0:
  126. bb.msg.error(bb.msg.domain.Provider, "no eligible providers for %s" % item)
  127. return 0
  128. # If pn == item, give it a slight default preference
  129. # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
  130. for p in providers:
  131. pn = dataCache.pkg_fn[p]
  132. if pn != item:
  133. continue
  134. (newvers, fn) = preferred_versions[pn]
  135. if not fn in eligible:
  136. continue
  137. eligible.remove(fn)
  138. eligible = [fn] + eligible
  139. # look to see if one of them is already staged, or marked as preferred.
  140. # if so, bump it to the head of the queue
  141. for p in providers:
  142. pn = dataCache.pkg_fn[p]
  143. pv, pr = dataCache.pkg_pvpr[p]
  144. stamp = '%s.do_populate_staging' % dataCache.stamp[p]
  145. if os.path.exists(stamp):
  146. (newvers, fn) = preferred_versions[pn]
  147. if not fn in eligible:
  148. # package was made ineligible by already-failed check
  149. continue
  150. oldver = "%s-%s" % (pv, pr)
  151. newver = '-'.join(newvers)
  152. if (newver != oldver):
  153. extra_chat = "%s (%s) already staged but upgrading to %s to satisfy %s" % (pn, oldver, newver, item)
  154. else:
  155. extra_chat = "Selecting already-staged %s (%s) to satisfy %s" % (pn, oldver, item)
  156. bb.msg.note(2, bb.msg.domain.Provider, "%s" % extra_chat)
  157. eligible.remove(fn)
  158. eligible = [fn] + eligible
  159. break
  160. return eligible
  161. def getRuntimeProviders(dataCache, rdepend):
  162. """
  163. Return any providers of runtime dependency
  164. """
  165. rproviders = []
  166. if rdepend in dataCache.rproviders:
  167. rproviders += dataCache.rproviders[rdepend]
  168. if rdepend in dataCache.packages:
  169. rproviders += dataCache.packages[rdepend]
  170. if rproviders:
  171. return rproviders
  172. # Only search dynamic packages if we can't find anything in other variables
  173. for pattern in dataCache.packages_dynamic:
  174. regexp = re.compile(pattern)
  175. if regexp.match(rdepend):
  176. rproviders += dataCache.packages_dynamic[pattern]
  177. return rproviders