aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2017-10-18 22:39:05 -0700
committerDylan Baker <dylan@pnwbakers.com>2017-11-23 19:54:47 -0800
commitcda0e33650341f0a82c7d4164607fd74805e670f (patch)
tree51cb10f73de233dd6ee6a0c4edcc6cc30a197118
parentaee038173e28096cf59e69ca7c1f9e5df5217094 (diff)
downloadmeson-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.py94
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.