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
pull/1133/head
Nirbheek Chauhan 8 years ago committed by Jussi Pakkanen
parent 2f804e9074
commit e1c9d94708
  1. 8
      mesonbuild/backend/ninjabackend.py
  2. 25
      mesonbuild/dependencies.py
  3. 3
      mesonbuild/interpreter.py
  4. 29
      mesonbuild/mesonlib.py
  5. 3
      test cases/failing/37 pkgconfig dependency impossible conditions/meson.build
  6. 11
      test cases/linuxlike/5 dependency versions/meson.build

@ -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…
Cancel
Save