diff --git a/bitbake/lib/bb/providers.py b/bitbake/lib/bb/providers.py
new file mode 100644
index 0000000..637e1fa
--- /dev/null
+++ b/bitbake/lib/bb/providers.py
@@ -0,0 +1,381 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# Copyright (C) 2003, 2004  Chris Larson
+# Copyright (C) 2003, 2004  Phil Blundell
+# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
+# Copyright (C) 2005        Holger Hans Peter Freyther
+# Copyright (C) 2005        ROAD GmbH
+# Copyright (C) 2006        Richard Purdie
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+import logging
+from bb import data, utils
+from collections import defaultdict
+import bb
+
+logger = logging.getLogger("BitBake.Provider")
+
+class NoProvider(bb.BBHandledException):
+    """Exception raised when no provider of a build dependency can be found"""
+
+class NoRProvider(bb.BBHandledException):
+    """Exception raised when no provider of a runtime dependency can be found"""
+
+class MultipleRProvider(bb.BBHandledException):
+    """Exception raised when multiple providers of a runtime dependency can be found"""
+
+def findProviders(cfgData, dataCache, pkg_pn = None):
+    """
+    Convenience function to get latest and preferred providers in pkg_pn
+    """
+
+    if not pkg_pn:
+        pkg_pn = dataCache.pkg_pn
+
+    # Need to ensure data store is expanded
+    localdata = data.createCopy(cfgData)
+    bb.data.update_data(localdata)
+    bb.data.expandKeys(localdata)
+
+    preferred_versions = {}
+    latest_versions = {}
+
+    for pn in pkg_pn:
+        (last_ver, last_file, pref_ver, pref_file) = findBestProvider(pn, localdata, dataCache, pkg_pn)
+        preferred_versions[pn] = (pref_ver, pref_file)
+        latest_versions[pn] = (last_ver, last_file)
+
+    return (latest_versions, preferred_versions)
+
+
+def allProviders(dataCache):
+    """
+    Find all providers for each pn
+    """
+    all_providers = defaultdict(list)
+    for (fn, pn) in dataCache.pkg_fn.items():
+        ver = dataCache.pkg_pepvpr[fn]
+        all_providers[pn].append((ver, fn))
+    return all_providers
+
+
+def sortPriorities(pn, dataCache, pkg_pn = None):
+    """
+    Reorder pkg_pn by file priority and default preference
+    """
+
+    if not pkg_pn:
+        pkg_pn = dataCache.pkg_pn
+
+    files = pkg_pn[pn]
+    priorities = {}
+    for f in files:
+        priority = dataCache.bbfile_priority[f]
+        preference = dataCache.pkg_dp[f]
+        if priority not in priorities:
+            priorities[priority] = {}
+        if preference not in priorities[priority]:
+            priorities[priority][preference] = []
+        priorities[priority][preference].append(f)
+    tmp_pn = []
+    for pri in sorted(priorities):
+        tmp_pref = []
+        for pref in sorted(priorities[pri]):
+            tmp_pref.extend(priorities[pri][pref])
+        tmp_pn = [tmp_pref] + tmp_pn
+
+    return tmp_pn
+
+def preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
+    """
+    Check if the version pe,pv,pr is the preferred one.
+    If there is preferred version defined and ends with '%', then pv has to start with that version after removing the '%'
+    """
+    if (pr == preferred_r or preferred_r == None):
+        if (pe == preferred_e or preferred_e == None):
+            if preferred_v == pv:
+                return True
+            if preferred_v != None and preferred_v.endswith('%') and pv.startswith(preferred_v[:len(preferred_v)-1]):
+                return True
+    return False
+
+def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
+    """
+    Find the first provider in pkg_pn with a PREFERRED_VERSION set.
+    """
+
+    preferred_file = None
+    preferred_ver = None
+
+    localdata = data.createCopy(cfgData)
+    localdata.setVar('OVERRIDES', "%s:pn-%s:%s" % (data.getVar('OVERRIDES', localdata), pn, pn))
+    bb.data.update_data(localdata)
+
+    preferred_v = localdata.getVar('PREFERRED_VERSION', True)
+    if preferred_v:
+        m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
+        if m:
+            if m.group(1):
+                preferred_e = m.group(1)[:-1]
+            else:
+                preferred_e = None
+            preferred_v = m.group(2)
+            if m.group(3):
+                preferred_r = m.group(3)[1:]
+            else:
+                preferred_r = None
+        else:
+            preferred_e = None
+            preferred_r = None
+
+        for file_set in pkg_pn:
+            for f in file_set:
+                pe, pv, pr = dataCache.pkg_pepvpr[f]
+                if preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
+                    preferred_file = f
+                    preferred_ver = (pe, pv, pr)
+                    break
+            if preferred_file:
+                break;
+        if preferred_r:
+            pv_str = '%s-%s' % (preferred_v, preferred_r)
+        else:
+            pv_str = preferred_v
+        if not (preferred_e is None):
+            pv_str = '%s:%s' % (preferred_e, pv_str)
+        itemstr = ""
+        if item:
+            itemstr = " (for item %s)" % item
+        if preferred_file is None:
+            logger.info("preferred version %s of %s not available%s", pv_str, pn, itemstr)
+            available_vers = []
+            for file_set in pkg_pn:
+                for f in file_set:
+                    pe, pv, pr = dataCache.pkg_pepvpr[f]
+                    ver_str = pv
+                    if pe:
+                        ver_str = "%s:%s" % (pe, ver_str)
+                    if not ver_str in available_vers:
+                        available_vers.append(ver_str)
+            if available_vers:
+                available_vers.sort()
+                logger.info("versions of %s available: %s", pn, ' '.join(available_vers))
+        else:
+            logger.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr)
+
+    return (preferred_ver, preferred_file)
+
+
+def findLatestProvider(pn, cfgData, dataCache, file_set):
+    """
+    Return the highest version of the providers in file_set.
+    Take default preferences into account.
+    """
+    latest = None
+    latest_p = 0
+    latest_f = None
+    for file_name in file_set:
+        pe, pv, pr = dataCache.pkg_pepvpr[file_name]
+        dp = dataCache.pkg_dp[file_name]
+
+        if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pe, pv, pr)) < 0)) or (dp > latest_p):
+            latest = (pe, pv, pr)
+            latest_f = file_name
+            latest_p = dp
+
+    return (latest, latest_f)
+
+
+def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
+    """
+    If there is a PREFERRED_VERSION, find the highest-priority bbfile
+    providing that version.  If not, find the latest version provided by
+    an bbfile in the highest-priority set.
+    """
+
+    sortpkg_pn = sortPriorities(pn, dataCache, pkg_pn)
+    # Find the highest priority provider with a PREFERRED_VERSION set
+    (preferred_ver, preferred_file) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item)
+    # Find the latest version of the highest priority provider
+    (latest, latest_f) = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[0])
+
+    if preferred_file is None:
+        preferred_file = latest_f
+        preferred_ver = latest
+
+    return (latest, latest_f, preferred_ver, preferred_file)
+
+
+def _filterProviders(providers, item, cfgData, dataCache):
+    """
+    Take a list of providers and filter/reorder according to the
+    environment variables and previous build results
+    """
+    eligible = []
+    preferred_versions = {}
+    sortpkg_pn = {}
+
+    # The order of providers depends on the order of the files on the disk
+    # up to here. Sort pkg_pn to make dependency issues reproducible rather
+    # than effectively random.
+    providers.sort()
+
+    # Collate providers by PN
+    pkg_pn = {}
+    for p in providers:
+        pn = dataCache.pkg_fn[p]
+        if pn not in pkg_pn:
+            pkg_pn[pn] = []
+        pkg_pn[pn].append(p)
+
+    logger.debug(1, "providers for %s are: %s", item, pkg_pn.keys())
+
+    # First add PREFERRED_VERSIONS
+    for pn in pkg_pn:
+        sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn)
+        preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
+        if preferred_versions[pn][1]:
+            eligible.append(preferred_versions[pn][1])
+
+    # Now add latest versions
+    for pn in sortpkg_pn:
+        if pn in preferred_versions and preferred_versions[pn][1]:
+            continue
+        preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0])
+        eligible.append(preferred_versions[pn][1])
+
+    if len(eligible) == 0:
+        logger.error("no eligible providers for %s", item)
+        return 0
+
+    # If pn == item, give it a slight default preference
+    # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
+    for p in providers:
+        pn = dataCache.pkg_fn[p]
+        if pn != item:
+            continue
+        (newvers, fn) = preferred_versions[pn]
+        if not fn in eligible:
+            continue
+        eligible.remove(fn)
+        eligible = [fn] + eligible
+
+    return eligible
+
+
+def filterProviders(providers, item, cfgData, dataCache):
+    """
+    Take a list of providers and filter/reorder according to the
+    environment variables and previous build results
+    Takes a "normal" target item
+    """
+
+    eligible = _filterProviders(providers, item, cfgData, dataCache)
+
+    prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % item, True)
+    if prefervar:
+        dataCache.preferred[item] = prefervar
+
+    foundUnique = False
+    if item in dataCache.preferred:
+        for p in eligible:
+            pn = dataCache.pkg_fn[p]
+            if dataCache.preferred[item] == pn:
+                logger.verbose("selecting %s to satisfy %s due to PREFERRED_PROVIDERS", pn, item)
+                eligible.remove(p)
+                eligible = [p] + eligible
+                foundUnique = True
+                break
+
+    logger.debug(1, "sorted providers for %s are: %s", item, eligible)
+
+    return eligible, foundUnique
+
+def filterProvidersRunTime(providers, item, cfgData, dataCache):
+    """
+    Take a list of providers and filter/reorder according to the
+    environment variables and previous build results
+    Takes a "runtime" target item
+    """
+
+    eligible = _filterProviders(providers, item, cfgData, dataCache)
+
+    # Should use dataCache.preferred here?
+    preferred = []
+    preferred_vars = []
+    pns = {}
+    for p in eligible:
+        pns[dataCache.pkg_fn[p]] = p
+    for p in eligible:
+        pn = dataCache.pkg_fn[p]
+        provides = dataCache.pn_provides[pn]
+        for provide in provides:
+            prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
+            #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
+            if prefervar in pns and pns[prefervar] not in preferred:
+                var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
+                logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
+                preferred_vars.append(var)
+                pref = pns[prefervar]
+                eligible.remove(pref)
+                eligible = [pref] + eligible
+                preferred.append(pref)
+                break
+
+    numberPreferred = len(preferred)
+
+    if numberPreferred > 1:
+        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", item, preferred, preferred_vars)
+
+    logger.debug(1, "sorted runtime providers for %s are: %s", item, eligible)
+
+    return eligible, numberPreferred
+
+regexp_cache = {}
+
+def getRuntimeProviders(dataCache, rdepend):
+    """
+    Return any providers of runtime dependency
+    """
+    rproviders = []
+
+    if rdepend in dataCache.rproviders:
+        rproviders += dataCache.rproviders[rdepend]
+
+    if rdepend in dataCache.packages:
+        rproviders += dataCache.packages[rdepend]
+
+    if rproviders:
+        return rproviders
+
+    # Only search dynamic packages if we can't find anything in other variables
+    for pattern in dataCache.packages_dynamic:
+        pattern = pattern.replace('+', "\+")
+        if pattern in regexp_cache:
+            regexp = regexp_cache[pattern]
+        else:
+            try:
+                regexp = re.compile(pattern)
+            except:
+                logger.error("Error parsing regular expression '%s'", pattern)
+                raise
+            regexp_cache[pattern] = regexp
+        if regexp.match(rdepend):
+            rproviders += dataCache.packages_dynamic[pattern]
+            logger.debug(1, "Assuming %s is a dynamic package, but it may not exist" % rdepend)
+
+    return rproviders
