2006-11-16 15:02:15 +00:00
# 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
#
2007-01-08 23:53:01 +00:00
# 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.
2006-11-16 15:02:15 +00:00
#
2007-01-08 23:53:01 +00:00
# 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.
2006-11-16 15:02:15 +00:00
#
2007-01-08 23:53:01 +00:00
# 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.
2006-11-16 15:02:15 +00:00
2010-01-20 18:46:02 +00:00
import re
2006-11-16 15:02:15 +00:00
from bb import data , utils
import bb
class NoProvider ( Exception ) :
""" Exception raised when no provider of a build dependency can be found """
class NoRProvider ( Exception ) :
""" Exception raised when no provider of a runtime dependency can be found """
2007-09-02 14:10:08 +00:00
def sortPriorities ( pn , dataCache , pkg_pn = None ) :
2006-11-16 15:02:15 +00:00
"""
2007-09-02 14:10:08 +00:00
Reorder pkg_pn by file priority and default preference
2006-11-16 15:02:15 +00:00
"""
2007-09-02 14:10:08 +00:00
2006-11-16 15:02:15 +00:00
if not pkg_pn :
pkg_pn = dataCache . pkg_pn
files = pkg_pn [ pn ]
priorities = { }
for f in files :
priority = dataCache . bbfile_priority [ f ]
2007-09-02 14:10:08 +00:00
preference = dataCache . pkg_dp [ f ]
2006-11-16 15:02:15 +00:00
if priority not in priorities :
2007-09-02 14:10:08 +00:00
priorities [ priority ] = { }
if preference not in priorities [ priority ] :
priorities [ priority ] [ preference ] = [ ]
priorities [ priority ] [ preference ] . append ( f )
2006-11-16 15:02:15 +00:00
tmp_pn = [ ]
2009-06-11 20:10:04 +00:00
for pri in sorted ( priorities , lambda a , b : a - b ) :
2007-09-02 14:10:08 +00:00
tmp_pref = [ ]
2009-06-11 20:10:04 +00:00
for pref in sorted ( priorities [ pri ] , lambda a , b : b - a ) :
2007-09-02 14:10:08 +00:00
tmp_pref . extend ( priorities [ pri ] [ pref ] )
tmp_pn = [ tmp_pref ] + tmp_pn
return tmp_pn
2010-01-12 20:31:18 +00:00
def preferredVersionMatch ( pe , pv , pr , preferred_e , preferred_v , preferred_r ) :
"""
Check if the version pe , pv , pr is the preferred one .
2010-03-24 23:56:12 +00:00
If there is preferred version defined and ends with ' % ' , then pv has to start with that version after removing the ' % '
2010-01-12 20:31:18 +00:00
"""
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
2007-09-02 14:10:08 +00:00
def findPreferredProvider ( pn , cfgData , dataCache , pkg_pn = None , item = None ) :
"""
Find the first provider in pkg_pn with a PREFERRED_VERSION set .
"""
2006-11-16 15:02:15 +00:00
preferred_file = None
2007-10-21 22:35:46 +00:00
preferred_ver = None
2006-11-16 15:02:15 +00:00
localdata = data . createCopy ( cfgData )
2007-08-08 22:28:17 +00:00
bb . data . setVar ( ' OVERRIDES ' , " pn- %s : %s : %s " % ( pn , pn , data . getVar ( ' OVERRIDES ' , localdata ) ) , localdata )
2006-11-16 15:02:15 +00:00
bb . data . update_data ( localdata )
preferred_v = bb . data . getVar ( ' PREFERRED_VERSION_ %s ' % pn , localdata , True )
if preferred_v :
2007-04-01 15:04:49 +00:00
m = re . match ( ' ( \ d+:)*(.*)(_.*)* ' , preferred_v )
2006-11-16 15:02:15 +00:00
if m :
2007-04-01 15:04:49 +00:00
if m . group ( 1 ) :
preferred_e = int ( 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
2006-11-16 15:02:15 +00:00
else :
2007-04-01 15:04:49 +00:00
preferred_e = None
2006-11-16 15:02:15 +00:00
preferred_r = None
2007-09-02 14:10:08 +00:00
for file_set in pkg_pn :
2006-11-16 15:02:15 +00:00
for f in file_set :
2010-03-24 23:56:12 +00:00
pe , pv , pr = dataCache . pkg_pepvpr [ f ]
2010-01-12 20:31:18 +00:00
if preferredVersionMatch ( pe , pv , pr , preferred_e , preferred_v , preferred_r ) :
2006-11-16 15:02:15 +00:00
preferred_file = f
2007-04-01 15:04:49 +00:00
preferred_ver = ( pe , pv , pr )
2006-11-16 15:02:15 +00:00
break
if preferred_file :
break ;
if preferred_r :
pv_str = ' %s - %s ' % ( preferred_v , preferred_r )
else :
pv_str = preferred_v
2007-04-01 15:04:49 +00:00
if not ( preferred_e is None ) :
pv_str = ' %s : %s ' % ( preferred_e , pv_str )
2006-11-16 15:02:15 +00:00
itemstr = " "
if item :
itemstr = " (for item %s ) " % item
if preferred_file is None :
bb . msg . note ( 1 , bb . msg . domain . Provider , " preferred version %s of %s not available %s " % ( pv_str , pn , itemstr ) )
else :
bb . msg . debug ( 1 , bb . msg . domain . Provider , " selecting %s as PREFERRED_VERSION %s of package %s %s " % ( preferred_file , pv_str , pn , itemstr ) )
2007-10-21 22:35:46 +00:00
return ( preferred_ver , preferred_file )
2007-09-02 14:10:08 +00:00
2006-11-16 15:02:15 +00:00
2007-09-02 14:10:08 +00:00
def findLatestProvider ( pn , cfgData , dataCache , file_set ) :
"""
Return the highest version of the providers in file_set .
Take default preferences into account .
"""
2006-11-16 15:02:15 +00:00
latest = None
latest_p = 0
latest_f = None
2007-09-02 14:10:08 +00:00
for file_name in file_set :
2010-03-24 23:56:12 +00:00
pe , pv , pr = dataCache . pkg_pepvpr [ file_name ]
2006-11-16 15:02:15 +00:00
dp = dataCache . pkg_dp [ file_name ]
2007-04-01 15:04:49 +00:00
if ( latest is None ) or ( ( latest_p == dp ) and ( utils . vercmp ( latest , ( pe , pv , pr ) ) < 0 ) ) or ( dp > latest_p ) :
latest = ( pe , pv , pr )
2006-11-16 15:02:15 +00:00
latest_f = file_name
latest_p = dp
2007-09-02 14:10:08 +00:00
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 ] )
2006-11-16 15:02:15 +00:00
if preferred_file is None :
preferred_file = latest_f
preferred_ver = latest
2007-09-02 14:10:08 +00:00
return ( latest , latest_f , preferred_ver , preferred_file )
2006-11-16 15:02:15 +00:00
2007-08-15 08:39:19 +00:00
def _filterProviders ( providers , item , cfgData , dataCache ) :
2006-11-16 15:02:15 +00:00
"""
2010-03-24 23:56:12 +00:00
Take a list of providers and filter / reorder according to the
2006-11-16 15:02:15 +00:00
environment variables and previous build results
"""
eligible = [ ]
preferred_versions = { }
2007-09-02 14:10:08 +00:00
sortpkg_pn = { }
2006-11-16 15:02:15 +00:00
2010-03-24 23:56:12 +00:00
# The order of providers depends on the order of the files on the disk
2007-08-15 08:39:19 +00:00
# up to here. Sort pkg_pn to make dependency issues reproducible rather
# than effectively random.
providers . sort ( )
2006-11-16 15:02:15 +00:00
# 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 )
2010-03-22 15:09:07 +00:00
bb . msg . debug ( 1 , bb . msg . domain . Provider , " providers for %s are: %s " % ( item , pkg_pn . keys ( ) ) )
2006-11-16 15:02:15 +00:00
2007-09-02 14:10:08 +00:00
# First add PREFERRED_VERSIONS
2010-03-22 15:09:07 +00:00
for pn in pkg_pn :
2007-09-02 14:10:08 +00:00
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 ] )
2010-07-01 21:24:26 +00:00
# Now add latest versions
2010-03-22 15:09:07 +00:00
for pn in sortpkg_pn :
2007-09-02 14:10:08 +00:00
if pn in preferred_versions and preferred_versions [ pn ] [ 1 ] :
continue
preferred_versions [ pn ] = findLatestProvider ( pn , cfgData , dataCache , sortpkg_pn [ pn ] [ 0 ] )
2006-11-16 15:02:15 +00:00
eligible . append ( preferred_versions [ pn ] [ 1 ] )
if len ( eligible ) == 0 :
bb . msg . error ( bb . msg . domain . Provider , " 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
2007-09-02 14:10:08 +00:00
return eligible
2007-08-15 08:39:19 +00:00
def filterProviders ( providers , item , cfgData , dataCache ) :
"""
2010-03-24 23:56:12 +00:00
Take a list of providers and filter / reorder according to the
2007-08-15 08:39:19 +00:00
environment variables and previous build results
Takes a " normal " target item
"""
2007-09-02 14:10:08 +00:00
eligible = _filterProviders ( providers , item , cfgData , dataCache )
2007-08-15 08:39:19 +00:00
prefervar = bb . data . getVar ( ' PREFERRED_PROVIDER_ %s ' % item , cfgData , 1 )
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 :
bb . msg . note ( 2 , bb . msg . domain . Provider , " selecting %s to satisfy %s due to PREFERRED_PROVIDERS " % ( pn , item ) )
eligible . remove ( p )
eligible = [ p ] + eligible
foundUnique = True
break
2007-09-02 14:10:08 +00:00
bb . msg . debug ( 1 , bb . msg . domain . Provider , " sorted providers for %s are: %s " % ( item , eligible ) )
2007-08-15 08:39:19 +00:00
return eligible , foundUnique
def filterProvidersRunTime ( providers , item , cfgData , dataCache ) :
"""
2010-03-24 23:56:12 +00:00
Take a list of providers and filter / reorder according to the
2007-08-15 08:39:19 +00:00
environment variables and previous build results
Takes a " runtime " target item
"""
2007-09-02 14:10:08 +00:00
eligible = _filterProviders ( providers , item , cfgData , dataCache )
2007-08-15 08:39:19 +00:00
# Should use dataCache.preferred here?
preferred = [ ]
2008-05-04 23:22:24 +00:00
preferred_vars = [ ]
2007-08-15 08:39:19 +00:00
for p in eligible :
pn = dataCache . pkg_fn [ p ]
provides = dataCache . pn_provides [ pn ]
for provide in provides :
2008-10-06 08:19:42 +00:00
bb . msg . note ( 2 , bb . msg . domain . Provider , " checking PREFERRED_PROVIDER_ %s " % ( provide ) )
2007-08-15 08:39:19 +00:00
prefervar = bb . data . getVar ( ' PREFERRED_PROVIDER_ %s ' % provide , cfgData , 1 )
if prefervar == pn :
2008-10-06 08:19:42 +00:00
var = " PREFERRED_PROVIDER_ %s = %s " % ( provide , prefervar )
2008-05-04 23:22:24 +00:00
bb . msg . note ( 2 , bb . msg . domain . Provider , " selecting %s to satisfy runtime %s due to %s " % ( pn , item , var ) )
preferred_vars . append ( var )
2007-08-15 08:39:19 +00:00
eligible . remove ( p )
eligible = [ p ] + eligible
preferred . append ( p )
break
numberPreferred = len ( preferred )
2008-05-04 23:22:24 +00:00
if numberPreferred > 1 :
2008-10-06 08:19:42 +00:00
bb . msg . error ( bb . msg . domain . Provider , " Conflicting PREFERRED_PROVIDER entries were found which resulted in an attempt to select multiple providers ( %s ) for runtime dependecy %s \n The entries resulting in this conflict were: %s " % ( preferred , item , preferred_vars ) )
2008-05-04 23:22:24 +00:00
2007-09-02 14:10:08 +00:00
bb . msg . debug ( 1 , bb . msg . domain . Provider , " sorted providers for %s are: %s " % ( item , eligible ) )
2007-08-15 08:39:19 +00:00
return eligible , numberPreferred
2006-11-16 15:02:15 +00:00
2009-07-23 14:59:17 +00:00
regexp_cache = { }
2006-11-16 15:02:15 +00:00
def getRuntimeProviders ( dataCache , rdepend ) :
"""
Return any providers of runtime dependency
"""
rproviders = [ ]
if rdepend in dataCache . rproviders :
2010-03-24 23:56:12 +00:00
rproviders + = dataCache . rproviders [ rdepend ]
2006-11-16 15:02:15 +00:00
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 :
2009-07-23 15:20:02 +00:00
pattern = pattern . replace ( ' + ' , " \ + " )
2009-07-23 14:59:17 +00:00
if pattern in regexp_cache :
regexp = regexp_cache [ pattern ]
else :
try :
regexp = re . compile ( pattern )
except :
bb . msg . error ( bb . msg . domain . Provider , " Error parsing re expression: %s " % pattern )
raise
regexp_cache [ pattern ] = regexp
2006-11-16 15:02:15 +00:00
if regexp . match ( rdepend ) :
rproviders + = dataCache . packages_dynamic [ pattern ]
return rproviders