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.
pull/2512/head
Dylan Baker 7 years ago
parent aee038173e
commit cda0e33650
  1. 94
      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.

Loading…
Cancel
Save