diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2017-10-18 22:39:05 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2017-11-23 19:54:47 -0800 |
commit | cda0e33650341f0a82c7d4164607fd74805e670f (patch) | |
tree | 51cb10f73de233dd6ee6a0c4edcc6cc30a197118 | |
parent | aee038173e28096cf59e69ca7c1f9e5df5217094 (diff) | |
download | meson-cda0e33650341f0a82c7d4164607fd74805e670f.zip meson-cda0e33650341f0a82c7d4164607fd74805e670f.tar.gz meson-cda0e33650341f0a82c7d4164607fd74805e670f.tar.bz2 |
Add ConfigToolDependency class
This class is meant abstract away some of the tedium of writing a config
tool wrapper dependency, and allow these instances to share some basic
code that they all need.
-rw-r--r-- | mesonbuild/dependencies/base.py | 94 |
1 files changed, 93 insertions, 1 deletions
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index adc28ee..b42d556 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -24,7 +24,9 @@ from enum import Enum from .. import mlog from .. import mesonlib -from ..mesonlib import MesonException, Popen_safe, version_compare_many, listify +from ..mesonlib import ( + MesonException, Popen_safe, version_compare_many, version_compare, listify +) # These must be defined in this file to avoid cyclical references. @@ -55,6 +57,8 @@ class DependencyMethods(Enum): EXTRAFRAMEWORK = 'extraframework' # Detect using the sysconfig module. SYSCONFIG = 'sysconfig' + # Specify using a "program"-config style tool + CONFIG_TOOL = 'config-tool' class Dependency: @@ -167,6 +171,94 @@ class ExternalDependency(Dependency): return self.compiler +class ConfigToolDependency(ExternalDependency): + + """Class representing dependencies found using a config tool.""" + + tools = None + tool_name = None + + def __init__(self, name, environment, language, kwargs): + super().__init__('config-tool', environment, language, kwargs) + self.name = name + self.tools = listify(kwargs.get('tools', self.tools)) + + req_version = kwargs.get('version', None) + tool, version = self.find_config(req_version) + self.config = tool + self.is_found = self.report_config(version, req_version) + if not self.is_found: + self.config = None + return + self.version = version + + def find_config(self, versions=None): + """Helper method that searchs for config tool binaries in PATH and + returns the one that best matches the given version requirements. + """ + if not isinstance(versions, list) and versions is not None: + versions = listify(versions) + + best_match = (None, None) + for tool in self.tools: + try: + p, out = Popen_safe([tool, '--version'])[:2] + except (FileNotFoundError, PermissionError): + continue + if p.returncode != 0: + continue + + out = out.strip() + # Some tools, like pcap-config don't supply a version, but also + # dont fail with --version, in that case just assume that there is + # only one verison and return it. + if not out: + return (tool, 'none') + if versions: + is_found = version_compare_many(out, versions)[0] + # This allows returning a found version without a config tool, + # which is useful to inform the user that you found version x, + # but y was required. + if not is_found: + tool = None + if best_match[1]: + if version_compare(out, '> {}'.format(best_match[1])): + best_match = (tool, out) + else: + best_match = (tool, out) + + return best_match + + def report_config(self, version, req_version): + """Helper method to print messages about the tool.""" + if self.config is None: + if version is not None: + mlog.log('found {} {!r} but need:'.format(self.tool_name, version), + req_version) + else: + mlog.log("No {} found; can't detect dependency".format(self.tool_name)) + mlog.log('Dependency {} found:'.format(self.name), mlog.red('NO')) + if self.required: + raise DependencyException('Dependency {} not found'.format(self.name)) + return False + mlog.log('Found {}:'.format(self.tool_name), mlog.bold(shutil.which(self.config)), + '({})'.format(version)) + mlog.log('Dependency {} found:'.format(self.name), mlog.green('YES')) + return True + + def get_config_value(self, args, stage): + p, out, _ = Popen_safe([self.config] + args) + if p.returncode != 0: + if self.required: + raise DependencyException('Could not generate {} for {}'.format( + stage, self.name)) + return [] + return shlex.split(out) + + def get_methods(self): + return [DependencyMethods.AUTO, DependencyMethods.CONFIG_TOOL] + + class PkgConfigDependency(ExternalDependency): # The class's copy of the pkg-config path. Avoids having to search for it # multiple times in the same Meson invocation. |