Allow many version conditions for pkg-config deps
Sometimes we want to restrict the acceptable versions to a list of versions, or a smallest-version + largest-version, or both. For instance, GStreamer's opencv plugin is only compatible with 3.1.0 >= opencv >= 2.3.0
This commit is contained in:
parent
2f804e9074
commit
e1c9d94708
|
@ -1017,9 +1017,11 @@ int dummy;
|
|||
args += valac.get_werror_args()
|
||||
for d in target.get_external_deps():
|
||||
if isinstance(d, dependencies.PkgConfigDependency):
|
||||
if d.name == 'glib-2.0' and d.version_requirement is not None \
|
||||
and d.version_requirement.startswith(('>=', '==')):
|
||||
args += ['--target-glib', d.version_requirement[2:]]
|
||||
if d.name == 'glib-2.0' and d.version_reqs is not None:
|
||||
for req in d.version_reqs:
|
||||
if req.startswith(('>=', '==')):
|
||||
args += ['--target-glib', req[2:]]
|
||||
break
|
||||
args += ['--pkg', d.name]
|
||||
elif isinstance(d, dependencies.ExternalLibrary):
|
||||
args += d.get_lang_args('vala')
|
||||
|
|
|
@ -23,7 +23,7 @@ import re
|
|||
import os, stat, glob, subprocess, shutil
|
||||
import sysconfig
|
||||
from collections import OrderedDict
|
||||
from . mesonlib import MesonException
|
||||
from . mesonlib import MesonException, version_compare, version_compare_many
|
||||
from . import mlog
|
||||
from . import mesonlib
|
||||
from .environment import detect_cpu_family, for_windows
|
||||
|
@ -135,22 +135,27 @@ class PkgConfigDependency(Dependency):
|
|||
self.modversion = 'none'
|
||||
return
|
||||
found_msg = ['%s dependency' % self.type_string, mlog.bold(name), 'found:']
|
||||
self.version_requirement = kwargs.get('version', None)
|
||||
if self.version_requirement is None:
|
||||
self.version_reqs = kwargs.get('version', None)
|
||||
if self.version_reqs is None:
|
||||
self.is_found = True
|
||||
else:
|
||||
if not isinstance(self.version_requirement, str):
|
||||
raise DependencyException('Version argument must be string.')
|
||||
self.is_found = mesonlib.version_compare(self.modversion, self.version_requirement)
|
||||
if not isinstance(self.version_reqs, (str, list)):
|
||||
raise DependencyException('Version argument must be string or list.')
|
||||
(self.is_found, not_found, found) = \
|
||||
version_compare_many(self.modversion, self.version_reqs)
|
||||
if not self.is_found:
|
||||
found_msg += [mlog.red('NO'), 'found {!r}'.format(self.modversion),
|
||||
'but need {!r}'.format(self.version_requirement)]
|
||||
found_msg += [mlog.red('NO'),
|
||||
'found {!r} but need:'.format(self.modversion),
|
||||
', '.join(["'{}'".format(e) for e in not_found])]
|
||||
if found:
|
||||
found_msg += ['; matched:',
|
||||
', '.join(["'{}'".format(e) for e in found])]
|
||||
if not self.silent:
|
||||
mlog.log(*found_msg)
|
||||
if self.required:
|
||||
raise DependencyException(
|
||||
'Invalid version of a dependency, needed %s %s found %s.' %
|
||||
(name, self.version_requirement, self.modversion))
|
||||
(name, not_found, self.modversion))
|
||||
return
|
||||
found_msg += [mlog.green('YES'), self.modversion]
|
||||
if not self.silent:
|
||||
|
@ -301,7 +306,7 @@ class WxDependency(Dependency):
|
|||
self.modversion = out.decode().strip()
|
||||
version_req = kwargs.get('version', None)
|
||||
if version_req is not None:
|
||||
if not mesonlib.version_compare(self.modversion, version_req):
|
||||
if not version_compare(self.modversion, version_req, strict=True):
|
||||
mlog.log('Wxwidgets version %s does not fullfill requirement %s' %\
|
||||
(self.modversion, version_req))
|
||||
return
|
||||
|
|
|
@ -1862,7 +1862,8 @@ requirements use the version keyword argument instead.''')
|
|||
if 'version' in kwargs:
|
||||
wanted = kwargs['version']
|
||||
found = cached_dep.get_version()
|
||||
if not cached_dep.found() or not mesonlib.version_compare(found, wanted):
|
||||
if not cached_dep.found() or \
|
||||
not mesonlib.version_compare_many(found, wanted)[0]:
|
||||
# Cached dep has the wrong version. Check if an external
|
||||
# dependency or a fallback dependency provides it.
|
||||
cached_dep = None
|
||||
|
|
|
@ -146,21 +146,26 @@ def detect_vcs(source_dir):
|
|||
return vcs
|
||||
return None
|
||||
|
||||
def grab_leading_numbers(vstr):
|
||||
def grab_leading_numbers(vstr, strict=False):
|
||||
result = []
|
||||
for x in vstr.split('.'):
|
||||
try:
|
||||
result.append(int(x))
|
||||
except ValueError:
|
||||
except ValueError as e:
|
||||
if strict:
|
||||
msg = 'Invalid version to compare against: {!r}; only ' \
|
||||
'numeric digits separated by "." are allowed: ' + str(e)
|
||||
raise MesonException(msg.format(vstr))
|
||||
break
|
||||
return result
|
||||
|
||||
numpart = re.compile('[0-9.]+')
|
||||
|
||||
def version_compare(vstr1, vstr2):
|
||||
def version_compare(vstr1, vstr2, strict=False):
|
||||
match = numpart.match(vstr1.strip())
|
||||
if match is None:
|
||||
raise MesonException('Uncomparable version string %s.' % vstr1)
|
||||
msg = 'Uncomparable version string {!r}.'
|
||||
raise MesonException(msg.format(vstr1))
|
||||
vstr1 = match.group(0)
|
||||
if vstr2.startswith('>='):
|
||||
cmpop = operator.ge
|
||||
|
@ -185,10 +190,22 @@ def version_compare(vstr1, vstr2):
|
|||
vstr2 = vstr2[1:]
|
||||
else:
|
||||
cmpop = operator.eq
|
||||
varr1 = grab_leading_numbers(vstr1)
|
||||
varr2 = grab_leading_numbers(vstr2)
|
||||
varr1 = grab_leading_numbers(vstr1, strict)
|
||||
varr2 = grab_leading_numbers(vstr2, strict)
|
||||
return cmpop(varr1, varr2)
|
||||
|
||||
def version_compare_many(vstr1, conditions):
|
||||
if not isinstance(conditions, (list, tuple)):
|
||||
conditions = [conditions]
|
||||
found = []
|
||||
not_found = []
|
||||
for req in conditions:
|
||||
if not version_compare(vstr1, req, strict=True):
|
||||
not_found.append(req)
|
||||
else:
|
||||
found.append(req)
|
||||
return (not_found == [], not_found, found)
|
||||
|
||||
def default_libdir():
|
||||
if is_debianlike():
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
project('impossible-dep-test', 'c', version : '1.0')
|
||||
|
||||
dependency('zlib', version : ['>=1.0', '<1.0'])
|
|
@ -10,6 +10,17 @@ assert(zlib.type_name() == 'pkgconfig', 'zlib should be of type "pkgconfig" not
|
|||
zlibver = dependency('zlib', version : '<1.0', required : false)
|
||||
assert(zlibver.found() == false, 'zlib <1.0 should not be found!')
|
||||
|
||||
# Find external dependencies with various version restrictions
|
||||
dependency('zlib', version : '>=1.0')
|
||||
dependency('zlib', version : '<=9999')
|
||||
dependency('zlib', version : '=' + zlib.version())
|
||||
|
||||
# Find external dependencies with multiple version restrictions
|
||||
dependency('zlib', version : ['>=1.0', '<=9999'])
|
||||
if dependency('zlib', version : ['<=1.0', '>=9999', '=' + zlib.version()], required : false).found()
|
||||
error('zlib <=1.0 >=9999 should not have been found')
|
||||
endif
|
||||
|
||||
# Test https://github.com/mesonbuild/meson/pull/610
|
||||
dependency('somebrokenlib', version : '>=2.0', required : false)
|
||||
dependency('somebrokenlib', version : '>=1.0', required : false)
|
||||
|
|
Loading…
Reference in New Issue