aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2016-11-29 00:57:01 +0530
committerJussi Pakkanen <jpakkane@gmail.com>2016-12-03 21:46:20 +0200
commite1c9d94708fe4b13986fa61aa3fa308f3b6e8a70 (patch)
tree6f6e57749addb4f687c6aba3f39a68f35a5c6e34
parent2f804e9074f391e8efbf4a2deb9f1cc3ebaaaf2e (diff)
downloadmeson-e1c9d94708fe4b13986fa61aa3fa308f3b6e8a70.zip
meson-e1c9d94708fe4b13986fa61aa3fa308f3b6e8a70.tar.gz
meson-e1c9d94708fe4b13986fa61aa3fa308f3b6e8a70.tar.bz2
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
-rw-r--r--mesonbuild/backend/ninjabackend.py8
-rw-r--r--mesonbuild/dependencies.py25
-rw-r--r--mesonbuild/interpreter.py3
-rw-r--r--mesonbuild/mesonlib.py29
-rw-r--r--test cases/failing/37 pkgconfig dependency impossible conditions/meson.build3
-rw-r--r--test cases/linuxlike/5 dependency versions/meson.build11
6 files changed, 59 insertions, 20 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index bd65cbe..d0267bc 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -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')
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 4e87e4e..a092732 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -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
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index ef99511..e9273e4 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -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
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 4d9cc69..4670685 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -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:
diff --git a/test cases/failing/37 pkgconfig dependency impossible conditions/meson.build b/test cases/failing/37 pkgconfig dependency impossible conditions/meson.build
new file mode 100644
index 0000000..54d434c
--- /dev/null
+++ b/test cases/failing/37 pkgconfig dependency impossible conditions/meson.build
@@ -0,0 +1,3 @@
+project('impossible-dep-test', 'c', version : '1.0')
+
+dependency('zlib', version : ['>=1.0', '<1.0'])
diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build
index 1de87c8..7f29564 100644
--- a/test cases/linuxlike/5 dependency versions/meson.build
+++ b/test cases/linuxlike/5 dependency versions/meson.build
@@ -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)