1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Chris Larson 3*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Phil Blundell 4*4882a593Smuzhiyun# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer 5*4882a593Smuzhiyun# Copyright (C) 2005 Holger Hans Peter Freyther 6*4882a593Smuzhiyun# Copyright (C) 2005 ROAD GmbH 7*4882a593Smuzhiyun# Copyright (C) 2006 Richard Purdie 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 10*4882a593Smuzhiyun# 11*4882a593Smuzhiyun 12*4882a593Smuzhiyunimport re 13*4882a593Smuzhiyunimport logging 14*4882a593Smuzhiyunfrom bb import data, utils 15*4882a593Smuzhiyunfrom collections import defaultdict 16*4882a593Smuzhiyunimport bb 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunlogger = logging.getLogger("BitBake.Provider") 19*4882a593Smuzhiyun 20*4882a593Smuzhiyunclass NoProvider(bb.BBHandledException): 21*4882a593Smuzhiyun """Exception raised when no provider of a build dependency can be found""" 22*4882a593Smuzhiyun 23*4882a593Smuzhiyunclass NoRProvider(bb.BBHandledException): 24*4882a593Smuzhiyun """Exception raised when no provider of a runtime dependency can be found""" 25*4882a593Smuzhiyun 26*4882a593Smuzhiyunclass MultipleRProvider(bb.BBHandledException): 27*4882a593Smuzhiyun """Exception raised when multiple providers of a runtime dependency can be found""" 28*4882a593Smuzhiyun 29*4882a593Smuzhiyundef findProviders(cfgData, dataCache, pkg_pn = None): 30*4882a593Smuzhiyun """ 31*4882a593Smuzhiyun Convenience function to get latest and preferred providers in pkg_pn 32*4882a593Smuzhiyun """ 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun if not pkg_pn: 35*4882a593Smuzhiyun pkg_pn = dataCache.pkg_pn 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun # Need to ensure data store is expanded 38*4882a593Smuzhiyun localdata = data.createCopy(cfgData) 39*4882a593Smuzhiyun bb.data.expandKeys(localdata) 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun required = {} 42*4882a593Smuzhiyun preferred_versions = {} 43*4882a593Smuzhiyun latest_versions = {} 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun for pn in pkg_pn: 46*4882a593Smuzhiyun (last_ver, last_file, pref_ver, pref_file, req) = findBestProvider(pn, localdata, dataCache, pkg_pn) 47*4882a593Smuzhiyun preferred_versions[pn] = (pref_ver, pref_file) 48*4882a593Smuzhiyun latest_versions[pn] = (last_ver, last_file) 49*4882a593Smuzhiyun required[pn] = req 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun return (latest_versions, preferred_versions, required) 52*4882a593Smuzhiyun 53*4882a593Smuzhiyundef allProviders(dataCache): 54*4882a593Smuzhiyun """ 55*4882a593Smuzhiyun Find all providers for each pn 56*4882a593Smuzhiyun """ 57*4882a593Smuzhiyun all_providers = defaultdict(list) 58*4882a593Smuzhiyun for (fn, pn) in dataCache.pkg_fn.items(): 59*4882a593Smuzhiyun ver = dataCache.pkg_pepvpr[fn] 60*4882a593Smuzhiyun all_providers[pn].append((ver, fn)) 61*4882a593Smuzhiyun return all_providers 62*4882a593Smuzhiyun 63*4882a593Smuzhiyundef sortPriorities(pn, dataCache, pkg_pn = None): 64*4882a593Smuzhiyun """ 65*4882a593Smuzhiyun Reorder pkg_pn by file priority and default preference 66*4882a593Smuzhiyun """ 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun if not pkg_pn: 69*4882a593Smuzhiyun pkg_pn = dataCache.pkg_pn 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun files = pkg_pn[pn] 72*4882a593Smuzhiyun priorities = {} 73*4882a593Smuzhiyun for f in files: 74*4882a593Smuzhiyun priority = dataCache.bbfile_priority[f] 75*4882a593Smuzhiyun preference = dataCache.pkg_dp[f] 76*4882a593Smuzhiyun if priority not in priorities: 77*4882a593Smuzhiyun priorities[priority] = {} 78*4882a593Smuzhiyun if preference not in priorities[priority]: 79*4882a593Smuzhiyun priorities[priority][preference] = [] 80*4882a593Smuzhiyun priorities[priority][preference].append(f) 81*4882a593Smuzhiyun tmp_pn = [] 82*4882a593Smuzhiyun for pri in sorted(priorities): 83*4882a593Smuzhiyun tmp_pref = [] 84*4882a593Smuzhiyun for pref in sorted(priorities[pri]): 85*4882a593Smuzhiyun tmp_pref.extend(priorities[pri][pref]) 86*4882a593Smuzhiyun tmp_pn = [tmp_pref] + tmp_pn 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun return tmp_pn 89*4882a593Smuzhiyun 90*4882a593Smuzhiyundef versionVariableMatch(cfgData, keyword, pn): 91*4882a593Smuzhiyun """ 92*4882a593Smuzhiyun Return the value of the <keyword>_VERSION variable if set. 93*4882a593Smuzhiyun """ 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun # pn can contain '_', e.g. gcc-cross-x86_64 and an override cannot 96*4882a593Smuzhiyun # hence we do this manually rather than use OVERRIDES 97*4882a593Smuzhiyun ver = cfgData.getVar("%s_VERSION:pn-%s" % (keyword, pn)) 98*4882a593Smuzhiyun if not ver: 99*4882a593Smuzhiyun ver = cfgData.getVar("%s_VERSION_%s" % (keyword, pn)) 100*4882a593Smuzhiyun if not ver: 101*4882a593Smuzhiyun ver = cfgData.getVar("%s_VERSION" % keyword) 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun return ver 104*4882a593Smuzhiyun 105*4882a593Smuzhiyundef preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r): 106*4882a593Smuzhiyun """ 107*4882a593Smuzhiyun Check if the version pe,pv,pr is the preferred one. 108*4882a593Smuzhiyun If there is preferred version defined and ends with '%', then pv has to start with that version after removing the '%' 109*4882a593Smuzhiyun """ 110*4882a593Smuzhiyun if pr == preferred_r or preferred_r is None: 111*4882a593Smuzhiyun if pe == preferred_e or preferred_e is None: 112*4882a593Smuzhiyun if preferred_v == pv: 113*4882a593Smuzhiyun return True 114*4882a593Smuzhiyun if preferred_v is not None and preferred_v.endswith('%') and pv.startswith(preferred_v[:len(preferred_v)-1]): 115*4882a593Smuzhiyun return True 116*4882a593Smuzhiyun return False 117*4882a593Smuzhiyun 118*4882a593Smuzhiyundef findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None): 119*4882a593Smuzhiyun """ 120*4882a593Smuzhiyun Find the first provider in pkg_pn with REQUIRED_VERSION or PREFERRED_VERSION set. 121*4882a593Smuzhiyun """ 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun preferred_file = None 124*4882a593Smuzhiyun preferred_ver = None 125*4882a593Smuzhiyun required = False 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun required_v = versionVariableMatch(cfgData, "REQUIRED", pn) 128*4882a593Smuzhiyun preferred_v = versionVariableMatch(cfgData, "PREFERRED", pn) 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun itemstr = "" 131*4882a593Smuzhiyun if item: 132*4882a593Smuzhiyun itemstr = " (for item %s)" % item 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun if required_v is not None: 135*4882a593Smuzhiyun if preferred_v is not None: 136*4882a593Smuzhiyun logger.warning("REQUIRED_VERSION and PREFERRED_VERSION for package %s%s are both set using REQUIRED_VERSION %s", pn, itemstr, required_v) 137*4882a593Smuzhiyun else: 138*4882a593Smuzhiyun logger.debug("REQUIRED_VERSION is set for package %s%s", pn, itemstr) 139*4882a593Smuzhiyun # REQUIRED_VERSION always takes precedence over PREFERRED_VERSION 140*4882a593Smuzhiyun preferred_v = required_v 141*4882a593Smuzhiyun required = True 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun if preferred_v: 144*4882a593Smuzhiyun m = re.match(r'(\d+:)*(.*)(_.*)*', preferred_v) 145*4882a593Smuzhiyun if m: 146*4882a593Smuzhiyun if m.group(1): 147*4882a593Smuzhiyun preferred_e = m.group(1)[:-1] 148*4882a593Smuzhiyun else: 149*4882a593Smuzhiyun preferred_e = None 150*4882a593Smuzhiyun preferred_v = m.group(2) 151*4882a593Smuzhiyun if m.group(3): 152*4882a593Smuzhiyun preferred_r = m.group(3)[1:] 153*4882a593Smuzhiyun else: 154*4882a593Smuzhiyun preferred_r = None 155*4882a593Smuzhiyun else: 156*4882a593Smuzhiyun preferred_e = None 157*4882a593Smuzhiyun preferred_r = None 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun for file_set in pkg_pn: 160*4882a593Smuzhiyun for f in file_set: 161*4882a593Smuzhiyun pe, pv, pr = dataCache.pkg_pepvpr[f] 162*4882a593Smuzhiyun if preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r): 163*4882a593Smuzhiyun preferred_file = f 164*4882a593Smuzhiyun preferred_ver = (pe, pv, pr) 165*4882a593Smuzhiyun break 166*4882a593Smuzhiyun if preferred_file: 167*4882a593Smuzhiyun break; 168*4882a593Smuzhiyun if preferred_r: 169*4882a593Smuzhiyun pv_str = '%s-%s' % (preferred_v, preferred_r) 170*4882a593Smuzhiyun else: 171*4882a593Smuzhiyun pv_str = preferred_v 172*4882a593Smuzhiyun if not (preferred_e is None): 173*4882a593Smuzhiyun pv_str = '%s:%s' % (preferred_e, pv_str) 174*4882a593Smuzhiyun if preferred_file is None: 175*4882a593Smuzhiyun if not required: 176*4882a593Smuzhiyun logger.warning("preferred version %s of %s not available%s", pv_str, pn, itemstr) 177*4882a593Smuzhiyun available_vers = [] 178*4882a593Smuzhiyun for file_set in pkg_pn: 179*4882a593Smuzhiyun for f in file_set: 180*4882a593Smuzhiyun pe, pv, pr = dataCache.pkg_pepvpr[f] 181*4882a593Smuzhiyun ver_str = pv 182*4882a593Smuzhiyun if pe: 183*4882a593Smuzhiyun ver_str = "%s:%s" % (pe, ver_str) 184*4882a593Smuzhiyun if not ver_str in available_vers: 185*4882a593Smuzhiyun available_vers.append(ver_str) 186*4882a593Smuzhiyun if available_vers: 187*4882a593Smuzhiyun available_vers.sort() 188*4882a593Smuzhiyun logger.warning("versions of %s available: %s", pn, ' '.join(available_vers)) 189*4882a593Smuzhiyun if required: 190*4882a593Smuzhiyun logger.error("required version %s of %s not available%s", pv_str, pn, itemstr) 191*4882a593Smuzhiyun else: 192*4882a593Smuzhiyun if required: 193*4882a593Smuzhiyun logger.debug("selecting %s as REQUIRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr) 194*4882a593Smuzhiyun else: 195*4882a593Smuzhiyun logger.debug("selecting %s as PREFERRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr) 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun return (preferred_ver, preferred_file, required) 198*4882a593Smuzhiyun 199*4882a593Smuzhiyundef findLatestProvider(pn, cfgData, dataCache, file_set): 200*4882a593Smuzhiyun """ 201*4882a593Smuzhiyun Return the highest version of the providers in file_set. 202*4882a593Smuzhiyun Take default preferences into account. 203*4882a593Smuzhiyun """ 204*4882a593Smuzhiyun latest = None 205*4882a593Smuzhiyun latest_p = 0 206*4882a593Smuzhiyun latest_f = None 207*4882a593Smuzhiyun for file_name in file_set: 208*4882a593Smuzhiyun pe, pv, pr = dataCache.pkg_pepvpr[file_name] 209*4882a593Smuzhiyun dp = dataCache.pkg_dp[file_name] 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pe, pv, pr)) < 0)) or (dp > latest_p): 212*4882a593Smuzhiyun latest = (pe, pv, pr) 213*4882a593Smuzhiyun latest_f = file_name 214*4882a593Smuzhiyun latest_p = dp 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun return (latest, latest_f) 217*4882a593Smuzhiyun 218*4882a593Smuzhiyundef findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None): 219*4882a593Smuzhiyun """ 220*4882a593Smuzhiyun If there is a PREFERRED_VERSION, find the highest-priority bbfile 221*4882a593Smuzhiyun providing that version. If not, find the latest version provided by 222*4882a593Smuzhiyun an bbfile in the highest-priority set. 223*4882a593Smuzhiyun """ 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun sortpkg_pn = sortPriorities(pn, dataCache, pkg_pn) 226*4882a593Smuzhiyun # Find the highest priority provider with a REQUIRED_VERSION or PREFERRED_VERSION set 227*4882a593Smuzhiyun (preferred_ver, preferred_file, required) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item) 228*4882a593Smuzhiyun # Find the latest version of the highest priority provider 229*4882a593Smuzhiyun (latest, latest_f) = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[0]) 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun if not required and preferred_file is None: 232*4882a593Smuzhiyun preferred_file = latest_f 233*4882a593Smuzhiyun preferred_ver = latest 234*4882a593Smuzhiyun 235*4882a593Smuzhiyun return (latest, latest_f, preferred_ver, preferred_file, required) 236*4882a593Smuzhiyun 237*4882a593Smuzhiyundef _filterProviders(providers, item, cfgData, dataCache): 238*4882a593Smuzhiyun """ 239*4882a593Smuzhiyun Take a list of providers and filter/reorder according to the 240*4882a593Smuzhiyun environment variables 241*4882a593Smuzhiyun """ 242*4882a593Smuzhiyun eligible = [] 243*4882a593Smuzhiyun preferred_versions = {} 244*4882a593Smuzhiyun sortpkg_pn = {} 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun # The order of providers depends on the order of the files on the disk 247*4882a593Smuzhiyun # up to here. Sort pkg_pn to make dependency issues reproducible rather 248*4882a593Smuzhiyun # than effectively random. 249*4882a593Smuzhiyun providers.sort() 250*4882a593Smuzhiyun 251*4882a593Smuzhiyun # Collate providers by PN 252*4882a593Smuzhiyun pkg_pn = {} 253*4882a593Smuzhiyun for p in providers: 254*4882a593Smuzhiyun pn = dataCache.pkg_fn[p] 255*4882a593Smuzhiyun if pn not in pkg_pn: 256*4882a593Smuzhiyun pkg_pn[pn] = [] 257*4882a593Smuzhiyun pkg_pn[pn].append(p) 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun logger.debug("providers for %s are: %s", item, list(sorted(pkg_pn.keys()))) 260*4882a593Smuzhiyun 261*4882a593Smuzhiyun # First add REQUIRED_VERSIONS or PREFERRED_VERSIONS 262*4882a593Smuzhiyun for pn in sorted(pkg_pn): 263*4882a593Smuzhiyun sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn) 264*4882a593Smuzhiyun preferred_ver, preferred_file, required = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item) 265*4882a593Smuzhiyun if required and preferred_file is None: 266*4882a593Smuzhiyun return eligible 267*4882a593Smuzhiyun preferred_versions[pn] = (preferred_ver, preferred_file) 268*4882a593Smuzhiyun if preferred_versions[pn][1]: 269*4882a593Smuzhiyun eligible.append(preferred_versions[pn][1]) 270*4882a593Smuzhiyun 271*4882a593Smuzhiyun # Now add latest versions 272*4882a593Smuzhiyun for pn in sorted(sortpkg_pn): 273*4882a593Smuzhiyun if pn in preferred_versions and preferred_versions[pn][1]: 274*4882a593Smuzhiyun continue 275*4882a593Smuzhiyun preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0]) 276*4882a593Smuzhiyun eligible.append(preferred_versions[pn][1]) 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun if not eligible: 279*4882a593Smuzhiyun return eligible 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun # If pn == item, give it a slight default preference 282*4882a593Smuzhiyun # This means PREFERRED_PROVIDER_foobar defaults to foobar if available 283*4882a593Smuzhiyun for p in providers: 284*4882a593Smuzhiyun pn = dataCache.pkg_fn[p] 285*4882a593Smuzhiyun if pn != item: 286*4882a593Smuzhiyun continue 287*4882a593Smuzhiyun (newvers, fn) = preferred_versions[pn] 288*4882a593Smuzhiyun if not fn in eligible: 289*4882a593Smuzhiyun continue 290*4882a593Smuzhiyun eligible.remove(fn) 291*4882a593Smuzhiyun eligible = [fn] + eligible 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun return eligible 294*4882a593Smuzhiyun 295*4882a593Smuzhiyundef filterProviders(providers, item, cfgData, dataCache): 296*4882a593Smuzhiyun """ 297*4882a593Smuzhiyun Take a list of providers and filter/reorder according to the 298*4882a593Smuzhiyun environment variables 299*4882a593Smuzhiyun Takes a "normal" target item 300*4882a593Smuzhiyun """ 301*4882a593Smuzhiyun 302*4882a593Smuzhiyun eligible = _filterProviders(providers, item, cfgData, dataCache) 303*4882a593Smuzhiyun 304*4882a593Smuzhiyun prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % item) 305*4882a593Smuzhiyun if prefervar: 306*4882a593Smuzhiyun dataCache.preferred[item] = prefervar 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun foundUnique = False 309*4882a593Smuzhiyun if item in dataCache.preferred: 310*4882a593Smuzhiyun for p in eligible: 311*4882a593Smuzhiyun pn = dataCache.pkg_fn[p] 312*4882a593Smuzhiyun if dataCache.preferred[item] == pn: 313*4882a593Smuzhiyun logger.verbose("selecting %s to satisfy %s due to PREFERRED_PROVIDERS", pn, item) 314*4882a593Smuzhiyun eligible.remove(p) 315*4882a593Smuzhiyun eligible = [p] + eligible 316*4882a593Smuzhiyun foundUnique = True 317*4882a593Smuzhiyun break 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun logger.debug("sorted providers for %s are: %s", item, eligible) 320*4882a593Smuzhiyun 321*4882a593Smuzhiyun return eligible, foundUnique 322*4882a593Smuzhiyun 323*4882a593Smuzhiyundef filterProvidersRunTime(providers, item, cfgData, dataCache): 324*4882a593Smuzhiyun """ 325*4882a593Smuzhiyun Take a list of providers and filter/reorder according to the 326*4882a593Smuzhiyun environment variables 327*4882a593Smuzhiyun Takes a "runtime" target item 328*4882a593Smuzhiyun """ 329*4882a593Smuzhiyun 330*4882a593Smuzhiyun eligible = _filterProviders(providers, item, cfgData, dataCache) 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun # First try and match any PREFERRED_RPROVIDER entry 333*4882a593Smuzhiyun prefervar = cfgData.getVar('PREFERRED_RPROVIDER_%s' % item) 334*4882a593Smuzhiyun foundUnique = False 335*4882a593Smuzhiyun if prefervar: 336*4882a593Smuzhiyun for p in eligible: 337*4882a593Smuzhiyun pn = dataCache.pkg_fn[p] 338*4882a593Smuzhiyun if prefervar == pn: 339*4882a593Smuzhiyun logger.verbose("selecting %s to satisfy %s due to PREFERRED_RPROVIDER", pn, item) 340*4882a593Smuzhiyun eligible.remove(p) 341*4882a593Smuzhiyun eligible = [p] + eligible 342*4882a593Smuzhiyun foundUnique = True 343*4882a593Smuzhiyun numberPreferred = 1 344*4882a593Smuzhiyun break 345*4882a593Smuzhiyun 346*4882a593Smuzhiyun # If we didn't find an RPROVIDER entry, try and infer the provider from PREFERRED_PROVIDER entries 347*4882a593Smuzhiyun # by looking through the provides of each eligible recipe and seeing if a PREFERRED_PROVIDER was set. 348*4882a593Smuzhiyun # This is most useful for virtual/ entries rather than having a RPROVIDER per entry. 349*4882a593Smuzhiyun if not foundUnique: 350*4882a593Smuzhiyun # Should use dataCache.preferred here? 351*4882a593Smuzhiyun preferred = [] 352*4882a593Smuzhiyun preferred_vars = [] 353*4882a593Smuzhiyun pns = {} 354*4882a593Smuzhiyun for p in eligible: 355*4882a593Smuzhiyun pns[dataCache.pkg_fn[p]] = p 356*4882a593Smuzhiyun for p in eligible: 357*4882a593Smuzhiyun pn = dataCache.pkg_fn[p] 358*4882a593Smuzhiyun provides = dataCache.pn_provides[pn] 359*4882a593Smuzhiyun for provide in provides: 360*4882a593Smuzhiyun prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide) 361*4882a593Smuzhiyun #logger.debug("checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys()) 362*4882a593Smuzhiyun if prefervar in pns and pns[prefervar] not in preferred: 363*4882a593Smuzhiyun var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar) 364*4882a593Smuzhiyun logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var) 365*4882a593Smuzhiyun preferred_vars.append(var) 366*4882a593Smuzhiyun pref = pns[prefervar] 367*4882a593Smuzhiyun eligible.remove(pref) 368*4882a593Smuzhiyun eligible = [pref] + eligible 369*4882a593Smuzhiyun preferred.append(pref) 370*4882a593Smuzhiyun break 371*4882a593Smuzhiyun 372*4882a593Smuzhiyun numberPreferred = len(preferred) 373*4882a593Smuzhiyun 374*4882a593Smuzhiyun if numberPreferred > 1: 375*4882a593Smuzhiyun logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s. You could set PREFERRED_RPROVIDER_%s" % (item, preferred, preferred_vars, item)) 376*4882a593Smuzhiyun 377*4882a593Smuzhiyun logger.debug("sorted runtime providers for %s are: %s", item, eligible) 378*4882a593Smuzhiyun 379*4882a593Smuzhiyun return eligible, numberPreferred 380*4882a593Smuzhiyun 381*4882a593Smuzhiyunregexp_cache = {} 382*4882a593Smuzhiyun 383*4882a593Smuzhiyundef getRuntimeProviders(dataCache, rdepend): 384*4882a593Smuzhiyun """ 385*4882a593Smuzhiyun Return any providers of runtime dependency 386*4882a593Smuzhiyun """ 387*4882a593Smuzhiyun rproviders = [] 388*4882a593Smuzhiyun 389*4882a593Smuzhiyun if rdepend in dataCache.rproviders: 390*4882a593Smuzhiyun rproviders += dataCache.rproviders[rdepend] 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun if rdepend in dataCache.packages: 393*4882a593Smuzhiyun rproviders += dataCache.packages[rdepend] 394*4882a593Smuzhiyun 395*4882a593Smuzhiyun if rproviders: 396*4882a593Smuzhiyun return rproviders 397*4882a593Smuzhiyun 398*4882a593Smuzhiyun # Only search dynamic packages if we can't find anything in other variables 399*4882a593Smuzhiyun for pat_key in dataCache.packages_dynamic: 400*4882a593Smuzhiyun pattern = pat_key.replace(r'+', r"\+") 401*4882a593Smuzhiyun if pattern in regexp_cache: 402*4882a593Smuzhiyun regexp = regexp_cache[pattern] 403*4882a593Smuzhiyun else: 404*4882a593Smuzhiyun try: 405*4882a593Smuzhiyun regexp = re.compile(pattern) 406*4882a593Smuzhiyun except: 407*4882a593Smuzhiyun logger.error("Error parsing regular expression '%s'", pattern) 408*4882a593Smuzhiyun raise 409*4882a593Smuzhiyun regexp_cache[pattern] = regexp 410*4882a593Smuzhiyun if regexp.match(rdepend): 411*4882a593Smuzhiyun rproviders += dataCache.packages_dynamic[pat_key] 412*4882a593Smuzhiyun logger.debug("Assuming %s is a dynamic package, but it may not exist" % rdepend) 413*4882a593Smuzhiyun 414*4882a593Smuzhiyun return rproviders 415*4882a593Smuzhiyun 416*4882a593Smuzhiyundef buildWorldTargetList(dataCache, task=None): 417*4882a593Smuzhiyun """ 418*4882a593Smuzhiyun Build package list for "bitbake world" 419*4882a593Smuzhiyun """ 420*4882a593Smuzhiyun if dataCache.world_target: 421*4882a593Smuzhiyun return 422*4882a593Smuzhiyun 423*4882a593Smuzhiyun logger.debug("collating packages for \"world\"") 424*4882a593Smuzhiyun for f in dataCache.possible_world: 425*4882a593Smuzhiyun terminal = True 426*4882a593Smuzhiyun pn = dataCache.pkg_fn[f] 427*4882a593Smuzhiyun if task and task not in dataCache.task_deps[f]['tasks']: 428*4882a593Smuzhiyun logger.debug2("World build skipping %s as task %s doesn't exist", f, task) 429*4882a593Smuzhiyun terminal = False 430*4882a593Smuzhiyun 431*4882a593Smuzhiyun for p in dataCache.pn_provides[pn]: 432*4882a593Smuzhiyun if p.startswith('virtual/'): 433*4882a593Smuzhiyun logger.debug2("World build skipping %s due to %s provider starting with virtual/", f, p) 434*4882a593Smuzhiyun terminal = False 435*4882a593Smuzhiyun break 436*4882a593Smuzhiyun for pf in dataCache.providers[p]: 437*4882a593Smuzhiyun if dataCache.pkg_fn[pf] != pn: 438*4882a593Smuzhiyun logger.debug2("World build skipping %s due to both us and %s providing %s", f, pf, p) 439*4882a593Smuzhiyun terminal = False 440*4882a593Smuzhiyun break 441*4882a593Smuzhiyun if terminal: 442*4882a593Smuzhiyun dataCache.world_target.add(pn) 443