diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2016-11-29 00:57:01 +0530 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2016-12-03 21:46:20 +0200 |
commit | e1c9d94708fe4b13986fa61aa3fa308f3b6e8a70 (patch) | |
tree | 6f6e57749addb4f687c6aba3f39a68f35a5c6e34 | |
parent | 2f804e9074f391e8efbf4a2deb9f1cc3ebaaaf2e (diff) | |
download | meson-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.py | 8 | ||||
-rw-r--r-- | mesonbuild/dependencies.py | 25 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 3 | ||||
-rw-r--r-- | mesonbuild/mesonlib.py | 29 | ||||
-rw-r--r-- | test cases/failing/37 pkgconfig dependency impossible conditions/meson.build | 3 | ||||
-rw-r--r-- | test cases/linuxlike/5 dependency versions/meson.build | 11 |
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) |