Merge pull request #3657 from jon-turney/consolidate-dependency-check-report

Consolidate reporting the result of a dependency check
pull/4014/head
Nirbheek Chauhan 6 years ago committed by GitHub
commit 41bb5941e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 241
      mesonbuild/dependencies/base.py
  2. 20
      mesonbuild/dependencies/boost.py
  3. 39
      mesonbuild/dependencies/dev.py
  4. 130
      mesonbuild/dependencies/misc.py
  5. 231
      mesonbuild/dependencies/ui.py
  6. 14
      run_unittests.py

@ -16,6 +16,7 @@
# Custom logic for several other packages are in separate files.
import copy
import functools
import os
import re
import stat
@ -265,6 +266,15 @@ class ExternalDependency(Dependency):
return new
def log_details(self):
return ''
def log_info(self):
return ''
def log_tried(self):
return ''
class NotFoundDependency(Dependency):
def __init__(self, environment):
@ -296,6 +306,8 @@ class ConfigToolDependency(ExternalDependency):
self.config = None
return
self.version = version
if getattr(self, 'finish_init', None):
self.finish_init(self)
def _sanitize_version(self, version):
"""Remove any non-numeric, non-point version suffixes."""
@ -307,7 +319,7 @@ class ConfigToolDependency(ExternalDependency):
return version
@classmethod
def factory(cls, name, environment, language, kwargs, tools, tool_name):
def factory(cls, name, environment, language, kwargs, tools, tool_name, finish_init=None):
"""Constructor for use in dependencies that can be found multiple ways.
In addition to the standard constructor values, this constructor sets
@ -322,7 +334,7 @@ class ConfigToolDependency(ExternalDependency):
def reduce(self):
return (cls._unpickle, (), self.__dict__)
sub = type('{}Dependency'.format(name.capitalize()), (cls, ),
{'tools': tools, 'tool_name': tool_name, '__reduce__': reduce})
{'tools': tools, 'tool_name': tool_name, '__reduce__': reduce, 'finish_init': staticmethod(finish_init)})
return sub(name, environment, language, kwargs)
@ -388,13 +400,9 @@ class ConfigToolDependency(ExternalDependency):
else:
mlog.log('Found', mlog.bold(self.tool_name), repr(req_version),
mlog.red('NO'))
mlog.log('Dependency', mlog.bold(self.name), 'found:', 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', mlog.bold(self.name), 'found:', mlog.green('YES'))
return True
def get_config_value(self, args, stage):
@ -422,6 +430,9 @@ class ConfigToolDependency(ExternalDependency):
mlog.debug('Got config-tool variable {} : {}'.format(variable_name, variable))
return variable
def log_tried(self):
return self.type_name
class PkgConfigDependency(ExternalDependency):
# The class's copy of the pkg-config path. Avoids having to search for it
@ -463,20 +474,12 @@ class PkgConfigDependency(ExternalDependency):
if self.required:
raise DependencyException('Pkg-config not found.')
return
if self.want_cross:
self.type_string = 'Cross'
else:
self.type_string = 'Native'
mlog.debug('Determining dependency {!r} with pkg-config executable '
'{!r}'.format(name, self.pkgbin.get_path()))
ret, self.version = self._call_pkgbin(['--modversion', name])
if ret != 0:
if self.required:
raise DependencyException('{} dependency {!r} not found'
''.format(self.type_string, name))
return
found_msg = [self.type_string + ' dependency', mlog.bold(name), 'found:']
if self.version_reqs is None:
self.is_found = True
else:
@ -487,14 +490,6 @@ class PkgConfigDependency(ExternalDependency):
(self.is_found, not_found, found) = \
version_compare_many(self.version, self.version_reqs)
if not self.is_found:
found_msg += [mlog.red('NO'),
'found {!r} but need:'.format(self.version),
', '.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:
m = 'Invalid version of dependency, need {!r} {!r} found {!r}.'
raise DependencyException(m.format(name, not_found, self.version))
@ -505,7 +500,6 @@ class PkgConfigDependency(ExternalDependency):
self._set_cargs()
# Fetch the libraries and library paths needed for using this
self._set_libs()
found_msg += [mlog.green('YES'), self.version]
except DependencyException as e:
if self.required:
raise
@ -513,12 +507,7 @@ class PkgConfigDependency(ExternalDependency):
self.compile_args = []
self.link_args = []
self.is_found = False
found_msg += [mlog.red('NO'), '; reason: {}'.format(str(e))]
# Print the found message only at the very end because fetching cflags
# and libs can also fail if other needed pkg-config files aren't found.
if not self.silent:
mlog.log(*found_msg)
self.reason = e
def __repr__(self):
s = '<{0} {1}: {2} {3}>'
@ -712,8 +701,8 @@ class PkgConfigDependency(ExternalDependency):
variable = ''
if ret != 0:
if self.required:
raise DependencyException('%s dependency %s not found.' %
(self.type_string, self.name))
raise DependencyException('dependency %s not found.' %
(self.name))
else:
variable = out.strip()
@ -797,6 +786,9 @@ class PkgConfigDependency(ExternalDependency):
# a path rather than the raw dlname
return os.path.basename(dlname)
def log_tried(self):
return self.type_name
class DubDependency(ExternalDependency):
class_dubbin = None
@ -818,7 +810,6 @@ class DubDependency(ExternalDependency):
if self.required:
raise DependencyException('DUB not found.')
self.is_found = False
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return
mlog.debug('Determining dependency {!r} with DUB executable '
@ -828,10 +819,7 @@ class DubDependency(ExternalDependency):
ret, res = self._call_dubbin(['describe', name])
if ret != 0:
if self.required:
raise DependencyException('Dependency {!r} not found'.format(name))
self.is_found = False
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return
j = json.loads(res)
@ -842,10 +830,7 @@ class DubDependency(ExternalDependency):
msg = ['Dependency', mlog.bold(name), 'found but it was compiled with']
msg += [mlog.bold(j['compiler']), 'and we are using', mlog.bold(comp)]
mlog.error(*msg)
if self.required:
raise DependencyException('Dependency {!r} not found'.format(name))
self.is_found = False
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return
self.version = package['version']
@ -853,7 +838,6 @@ class DubDependency(ExternalDependency):
break
# Check if package version meets the requirements
found_msg = ['Dependency', mlog.bold(name), 'found:']
if self.version_reqs is None:
self.is_found = True
else:
@ -864,21 +848,11 @@ class DubDependency(ExternalDependency):
(self.is_found, not_found, found) = \
version_compare_many(self.version, self.version_reqs)
if not self.is_found:
found_msg += [mlog.red('NO'),
'found {!r} but need:'.format(self.version),
', '.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:
m = 'Invalid version of dependency, need {!r} {!r} found {!r}.'
raise DependencyException(m.format(name, not_found, self.version))
return
found_msg += [mlog.green('YES'), self.version]
if self.pkg['targetFileName'].endswith('.a'):
self.static = True
@ -899,14 +873,8 @@ class DubDependency(ExternalDependency):
self.link_args.append(file)
if not found:
if self.required:
raise DependencyException('Dependency {!r} not found'.format(name))
self.is_found = False
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return
if not self.silent:
mlog.log(*found_msg)
self.is_found = False
return
def get_compiler(self):
return self.compiler
@ -952,7 +920,7 @@ class DubDependency(ExternalDependency):
@staticmethod
def get_methods():
return [DependencyMethods.PKGCONFIG, DependencyMethods.DUB]
return [DependencyMethods.DUB]
class ExternalProgram:
windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd')
@ -1229,10 +1197,6 @@ class ExtraFrameworkDependency(ExternalDependency):
if self.found():
self.compile_args = ['-I' + os.path.join(self.path, self.name, 'Headers')]
self.link_args = ['-F' + self.path, '-framework', self.name.split('.')[0]]
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.green('YES'),
os.path.join(self.path, self.name))
else:
mlog.log('Dependency', name, 'found:', mlog.red('NO'))
def detect(self, name, path):
lname = name.lower()
@ -1251,12 +1215,16 @@ class ExtraFrameworkDependency(ExternalDependency):
self.name = d
self.is_found = True
return
if not self.found() and self.required:
raise DependencyException('Framework dependency %s not found.' % (name, ))
def get_version(self):
return 'unknown'
def log_info(self):
return os.path.join(self.path, self.name)
def log_tried(self):
return 'framework'
def get_dep_identifier(name, kwargs, want_cross):
# Need immutable objects since the identifier will be used as a dict key
@ -1277,54 +1245,131 @@ def get_dep_identifier(name, kwargs, want_cross):
identifier += (key, value)
return identifier
display_name_map = {
'boost': 'Boost',
'dub': 'DUB',
'gmock': 'GMock',
'gtest': 'GTest',
'llvm': 'LLVM',
'mpi': 'MPI',
'openmp': 'OpenMP',
'wxwidgets': 'WxWidgets',
}
def find_external_dependency(name, env, kwargs):
assert(name)
required = kwargs.get('required', True)
if not isinstance(required, bool):
raise DependencyException('Keyword "required" must be a boolean.')
if not isinstance(kwargs.get('method', ''), str):
raise DependencyException('Keyword "method" must be a string.')
method = kwargs.get('method', '')
lname = name.lower()
if lname not in _packages_accept_language and 'language' in kwargs:
raise DependencyException('%s dependency does not accept "language" keyword argument' % (name, ))
# display the dependency name with correct casing
display_name = display_name_map.get(lname, lname)
# if this isn't a cross-build, it's uninteresting if native: is used or not
if not env.is_cross_build():
type_text = 'Dependency'
else:
type_text = 'Native' if kwargs.get('native', False) else 'Cross'
type_text += ' dependency'
# build a list of dependency methods to try
candidates = _build_external_dependency_list(name, env, kwargs)
pkg_exc = None
pkgdep = []
details = ''
for c in candidates:
# try this dependency method
try:
d = c()
pkgdep.append(d)
except Exception as e:
mlog.debug(str(e))
# store the first exception we see
if not pkg_exc:
pkg_exc = e
else:
details = d.log_details()
if details:
details = '(' + details + ') '
if 'language' in kwargs:
details += 'for ' + d.language + ' '
# if the dependency was found
if d.found():
info = d.log_info()
if info:
info = ', ' + info
mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.green('YES'), d.version + info)
return d
# otherwise, the dependency could not be found
tried_methods = [d.log_tried() for d in pkgdep if d.log_tried()]
if tried_methods:
tried = '{}'.format(mlog.format_list(tried_methods))
else:
tried = ''
mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.red('NO'),
'(tried {})'.format(tried) if tried else '')
if required:
# if exception(s) occurred, re-raise the first one (on the grounds that
# it came from a preferred dependency detection method)
if pkg_exc:
raise pkg_exc
# we have a list of failed ExternalDependency objects, so we can report
# the methods we tried to find the dependency
raise DependencyException('Dependency "%s" not found, tried %s' % (name, tried))
# return the last failed dependency object
if pkgdep:
return pkgdep[-1]
# this should never happen
raise DependencyException('Dependency "%s" not found, but no dependency object to return' % (name))
def _build_external_dependency_list(name, env, kwargs):
# Is there a specific dependency detector for this dependency?
lname = name.lower()
if lname in packages:
if lname not in _packages_accept_language and 'language' in kwargs:
raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, ))
# Create the dependency object using a factory class method, if one
# exists, otherwise it is just constructed directly.
# Create the list of dependency object constructors using a factory
# class method, if one exists, otherwise the list just consists of the
# constructor
if getattr(packages[lname], '_factory', None):
dep = packages[lname]._factory(env, kwargs)
else:
dep = packages[lname](env, kwargs)
if required and not dep.found():
raise DependencyException('Dependency "%s" not found' % name)
dep = [functools.partial(packages[lname], env, kwargs)]
return dep
if 'language' in kwargs:
# Remove check when PkgConfigDependency supports language.
raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, ))
if 'dub' == method:
dubdep = DubDependency(name, env, kwargs)
if required and not dubdep.found():
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return dubdep
pkg_exc = None
pkgdep = None
try:
pkgdep = PkgConfigDependency(name, env, kwargs)
if pkgdep.found():
return pkgdep
except Exception as e:
pkg_exc = e
candidates = []
# If it's explicitly requested, use the dub detection method (only)
if 'dub' == kwargs.get('method', ''):
candidates.append(functools.partial(DubDependency, name, env, kwargs))
return candidates
# TBD: other values of method should control what method(s) are used
# Otherwise, just use the pkgconfig dependency detector
candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
# On OSX, also try framework dependency detector
if mesonlib.is_osx():
fwdep = ExtraFrameworkDependency(name, False, None, env, None, kwargs)
if required and not fwdep.found():
m = 'Dependency {!r} not found, tried Extra Frameworks ' \
'and Pkg-Config:\n\n' + str(pkg_exc)
raise DependencyException(m.format(name))
return fwdep
if pkg_exc is not None:
raise pkg_exc
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return pkgdep
candidates.append(functools.partial(ExtraFrameworkDependency, name,
False, None, env, None, kwargs))
return candidates
def strip_system_libdirs(environment, link_args):

@ -132,7 +132,6 @@ class BoostDependency(ExternalDependency):
self.incdir = self.detect_nix_incdir()
if self.check_invalid_modules():
self.log_fail()
return
mlog.debug('Boost library root dir is', mlog.bold(self.boost_root))
@ -146,12 +145,6 @@ class BoostDependency(ExternalDependency):
self.detect_lib_modules()
mlog.debug('Boost library directory is', mlog.bold(self.libdir))
# 3. Report success or failure
if self.is_found:
self.log_success()
else:
self.log_fail()
def check_invalid_modules(self):
invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS]
@ -172,17 +165,14 @@ class BoostDependency(ExternalDependency):
else:
return False
def log_fail(self):
def log_details(self):
module_str = ', '.join(self.requested_modules)
mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO'))
return module_str
def log_success(self):
module_str = ', '.join(self.requested_modules)
def log_info(self):
if self.boost_root:
info = self.version + ', ' + self.boost_root
else:
info = self.version
mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info)
return self.boost_root
return ''
def detect_nix_roots(self):
return [os.path.abspath(os.path.join(x, '..'))

@ -45,7 +45,7 @@ class GTestDependency(ExternalDependency):
if self.main:
self.link_args += gtest_main_detect
self.sources = []
mlog.log('Dependency GTest found:', mlog.green('YES'), '(prebuilt)')
self.prebuilt = True
elif self.detect_srcdir():
self.is_found = True
self.compile_args = ['-I' + d for d in self.src_include_dirs]
@ -54,9 +54,8 @@ class GTestDependency(ExternalDependency):
self.sources = [self.all_src, self.main_src]
else:
self.sources = [self.all_src]
mlog.log('Dependency GTest found:', mlog.green('YES'), '(building self)')
self.prebuilt = False
else:
mlog.log('Dependency GTest found:', mlog.red('NO'))
self.is_found = False
def detect_srcdir(self):
@ -76,6 +75,12 @@ class GTestDependency(ExternalDependency):
def need_threads(self):
return True
def log_info(self):
if self.prebuilt:
return 'prebuilt'
else:
return 'building self'
class GMockDependency(ExternalDependency):
def __init__(self, environment, kwargs):
@ -89,7 +94,7 @@ class GMockDependency(ExternalDependency):
self.compile_args = []
self.link_args = gmock_detect
self.sources = []
mlog.log('Dependency GMock found:', mlog.green('YES'), '(prebuilt)')
self.prebuilt = True
return
for d in ['/usr/src/googletest/googlemock/src', '/usr/src/gmock/src', '/usr/src/gmock']:
@ -106,11 +111,17 @@ class GMockDependency(ExternalDependency):
self.sources = [all_src, main_src]
else:
self.sources = [all_src]
mlog.log('Dependency GMock found:', mlog.green('YES'), '(building self)')
self.prebuilt = False
return
mlog.log('Dependency GMock found:', mlog.red('NO'))
self.is_found = False
def log_info(self):
if self.prebuilt:
return 'prebuilt'
else:
return 'building self'
class LLVMDependency(ConfigToolDependency):
"""
@ -145,6 +156,7 @@ class LLVMDependency(ConfigToolDependency):
super().__init__('LLVM', environment, 'cpp', kwargs)
self.provided_modules = []
self.required_modules = set()
self.module_details = []
if not self.is_found:
return
self.static = kwargs.get('static', False)
@ -237,21 +249,30 @@ class LLVMDependency(ConfigToolDependency):
is required.
"""
for mod in sorted(set(modules)):
status = ''
if mod not in self.provided_modules:
mlog.log('LLVM module', mlog.bold(mod), 'found:', mlog.red('NO'),
'(optional)' if not required else '')
if required:
self.is_found = False
if self.required:
raise DependencyException(
'Could not find required LLVM Component: {}'.format(mod))
status = '(missing)'
else:
status = '(missing but optional)'
else:
self.required_modules.add(mod)
mlog.log('LLVM module', mlog.bold(mod), 'found:', mlog.green('YES'))
self.module_details.append(mod + status)
def need_threads(self):
return True
def log_details(self):
if self.module_details:
return 'modules: ' + ', '.join(self.module_details)
return ''
class ValgrindDependency(PkgConfigDependency):
'''

@ -14,6 +14,7 @@
# This file contains the detection logic for miscellaneous external dependencies.
import functools
import os
import re
import shlex
@ -37,7 +38,6 @@ class MPIDependency(ExternalDependency):
def __init__(self, environment, kwargs):
language = kwargs.get('language', 'c')
super().__init__('mpi', environment, language, kwargs)
required = kwargs.pop('required', True)
kwargs['required'] = False
kwargs['silent'] = True
self.is_found = False
@ -103,13 +103,6 @@ class MPIDependency(ExternalDependency):
self.is_found = True
self.version, self.compile_args, self.link_args = result
if self.is_found:
mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version)
else:
mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO'))
if required:
raise DependencyException('MPI dependency {!r} not found'.format(self.name))
def _filter_compile_args(self, args):
"""
MPI wrappers return a bunch of garbage args.
@ -267,10 +260,6 @@ class OpenMPDependency(ExternalDependency):
self.is_found = True
else:
mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
if self.is_found:
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES'), self.version)
else:
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO'))
def need_openmp(self):
return True
@ -326,10 +315,6 @@ class Python3Dependency(ExternalDependency):
self.compile_args = fw.get_compile_args()
self.link_args = fw.get_link_args()
self.is_found = True
if self.is_found:
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES'))
else:
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO'))
@staticmethod
def get_windows_python_arch():
@ -436,33 +421,29 @@ class PcapDependency(ExternalDependency):
@classmethod
def _factory(cls, environment, kwargs):
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('pcap', environment, kwargs)
if pcdep.found():
return pcdep
except Exception as e:
mlog.debug('Pcap not found via pkgconfig. Trying next, error was:', str(e))
candidates.append(functools.partial(PkgConfigDependency, 'pcap', environment, kwargs))
if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'pcap', environment, None, kwargs, ['pcap-config'], 'pcap-config')
if ctdep.found():
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
ctdep.version = cls.get_pcap_lib_version(ctdep)
return ctdep
except Exception as e:
mlog.debug('Pcap not found via pcap-config. Trying next, error was:', str(e))
return PcapDependency(environment, kwargs)
candidates.append(functools.partial(ConfigToolDependency.factory,
'pcap', environment, None,
kwargs, ['pcap-config'],
'pcap-config',
PcapDependency.tool_finish_init))
return candidates
@staticmethod
def tool_finish_init(ctdep):
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
ctdep.version = PcapDependency.get_pcap_lib_version(ctdep)
@staticmethod
def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
@staticmethod
def get_pcap_lib_version(ctdep):
@ -477,32 +458,29 @@ class CupsDependency(ExternalDependency):
@classmethod
def _factory(cls, environment, kwargs):
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('cups', environment, kwargs)
if pcdep.found():
return pcdep
except Exception as e:
mlog.debug('cups not found via pkgconfig. Trying next, error was:', str(e))
candidates.append(functools.partial(PkgConfigDependency, 'cups', environment, kwargs))
if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'cups', environment, None, kwargs, ['cups-config'], 'cups-config')
if ctdep.found():
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
return ctdep
except Exception as e:
mlog.debug('cups not found via cups-config. Trying next, error was:', str(e))
candidates.append(functools.partial(ConfigToolDependency.factory,
'cups', environment, None,
kwargs, ['cups-config'],
'cups-config', CupsDependency.tool_finish_init))
if DependencyMethods.EXTRAFRAMEWORK in methods:
if mesonlib.is_osx():
fwdep = ExtraFrameworkDependency('cups', False, None, environment,
kwargs.get('language', None), kwargs)
if fwdep.found():
return fwdep
mlog.log('Dependency', mlog.bold('cups'), 'found:', mlog.red('NO'))
candidates.append(functools.partial(
ExtraFrameworkDependency, 'cups', False, None, environment,
kwargs.get('language', None), kwargs))
return CupsDependency(environment, kwargs)
return candidates
@staticmethod
def tool_finish_init(ctdep):
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args')
@staticmethod
def get_methods():
@ -519,30 +497,22 @@ class LibWmfDependency(ExternalDependency):
@classmethod
def _factory(cls, environment, kwargs):
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
try:
kwargs['required'] = False
pcdep = PkgConfigDependency('libwmf', environment, kwargs)
if pcdep.found():
return pcdep
except Exception as e:
mlog.debug('LibWmf not found via pkgconfig. Trying next, error was:', str(e))
candidates.append(functools.partial(PkgConfigDependency, 'libwmf', environment, kwargs))
if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'libwmf', environment, None, kwargs, ['libwmf-config'], 'libwmf-config')
if ctdep.found():
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
return ctdep
except Exception as e:
mlog.debug('cups not found via libwmf-config. Trying next, error was:', str(e))
candidates.append(functools.partial(ConfigToolDependency.factory,
'libwmf', environment, None, kwargs, ['libwmf-config'], 'libwmf-config', LibWmfDependency.tool_finish_init))
return LibWmfDependency(environment, kwargs)
return candidates
@staticmethod
def tool_finish_init(ctdep):
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
@staticmethod
def get_methods():
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
else:
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]

@ -15,6 +15,7 @@
# This file contains the detection logic for external dependencies that
# are UI-related.
import functools
import os
import re
import subprocess
@ -37,32 +38,34 @@ from .base import ConfigToolDependency
class GLDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('gl', environment, None, kwargs)
if DependencyMethods.SYSTEM in self.methods:
if mesonlib.is_osx():
self.is_found = True
# FIXME: Use AppleFrameworks dependency
self.link_args = ['-framework', 'OpenGL']
# FIXME: Detect version using self.clib_compiler
self.version = '1'
return
if mesonlib.is_windows():
self.is_found = True
# FIXME: Use self.clib_compiler.find_library()
self.link_args = ['-lopengl32']
# FIXME: Detect version using self.clib_compiler
self.version = '1'
return
if mesonlib.is_osx():
self.is_found = True
# FIXME: Use AppleFrameworks dependency
self.link_args = ['-framework', 'OpenGL']
# FIXME: Detect version using self.clib_compiler
self.version = '1'
return
if mesonlib.is_windows():
self.is_found = True
# FIXME: Use self.clib_compiler.find_library()
self.link_args = ['-lopengl32']
# FIXME: Detect version using self.clib_compiler
self.version = '1'
return
@classmethod
def _factory(cls, environment, kwargs):
if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
try:
pcdep = PkgConfigDependency('gl', environment, kwargs)
if pcdep.found():
return pcdep
except Exception:
pass
return GLDependency(environment, kwargs)
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
candidates.append(functools.partial(PkgConfigDependency, 'gl', environment, kwargs))
if DependencyMethods.SYSTEM in methods:
candidates.append(functools.partial(GLDependency), environment, kwargs)
return candidates
@staticmethod
def get_methods():
@ -201,12 +204,10 @@ class QtBaseDependency(ExternalDependency):
self.bindir = None
self.private_headers = kwargs.get('private_headers', False)
mods = extract_as_list(kwargs, 'modules')
self.requested_modules = mods
if not mods:
raise DependencyException('No ' + self.qtname + ' modules specified.')
type_text = 'cross' if env.is_cross_build() else 'native'
found_msg = '{} {} {{}} dependency (modules: {}) found:' \
''.format(self.qtname, type_text, ', '.join(mods))
from_text = 'pkg-config'
self.from_text = 'pkg-config'
# Keep track of the detection methods used, for logging purposes.
methods = []
@ -215,25 +216,15 @@ class QtBaseDependency(ExternalDependency):
self._pkgconfig_detect(mods, kwargs)
methods.append('pkgconfig')
if not self.is_found and DependencyMethods.QMAKE in self.methods:
from_text = self._qmake_detect(mods, kwargs)
self.from_text = self._qmake_detect(mods, kwargs)
methods.append('qmake-' + self.name)
methods.append('qmake')
if not self.is_found:
# Reset compile args and link args
self.compile_args = []
self.link_args = []
from_text = '(checked {})'.format(mlog.format_list(methods))
self.from_text = mlog.format_list(methods)
self.version = 'none'
if self.required:
err_msg = '{} {} dependency not found {}' \
''.format(self.qtname, type_text, from_text)
raise DependencyException(err_msg)
if not self.silent:
mlog.log(found_msg.format(from_text), mlog.red('NO'))
return
from_text = '`{}`'.format(from_text)
if not self.silent:
mlog.log(found_msg.format(from_text), mlog.green('YES'))
def compilers_detect(self):
"Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH"
@ -414,6 +405,16 @@ class QtBaseDependency(ExternalDependency):
def get_private_includes(self, mod_inc_dir, module):
return tuple()
def log_details(self):
module_str = ', '.join(self.requested_modules)
return 'modules: ' + module_str
def log_info(self):
return '`{}`'.format(self.from_text)
def log_tried(self):
return self.from_text
class Qt4Dependency(QtBaseDependency):
def __init__(self, env, kwargs):
@ -452,33 +453,29 @@ class SDL2Dependency(ExternalDependency):
@classmethod
def _factory(cls, environment, kwargs):
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
try:
pcdep = PkgConfigDependency('sdl2', environment, kwargs)
if pcdep.found():
return pcdep
except Exception as e:
mlog.debug('SDL 2 not found via pkgconfig. Trying next, error was:', str(e))
candidates.append(functools.partial(PkgConfigDependency, 'sdl2', environment, kwargs))
if DependencyMethods.CONFIG_TOOL in methods:
try:
ctdep = ConfigToolDependency.factory(
'sdl2', environment, None, kwargs, ['sdl2-config'], 'sdl2-config')
if ctdep.found():
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
return ctdep
except Exception as e:
mlog.debug('SDL 2 not found via sdl2-config. Trying next, error was:', str(e))
candidates.append(functools.partial(ConfigToolDependency.factory,
'sdl2', environment, None,
kwargs, ['sdl2-config'],
'sdl2-config', SDL2Dependency.tool_finish_init))
if DependencyMethods.EXTRAFRAMEWORK in methods:
if mesonlib.is_osx():
fwdep = ExtraFrameworkDependency('sdl2', False, None, environment,
kwargs.get('language', None), kwargs)
if fwdep.found():
fwdep.version = '2' # FIXME
return fwdep
mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO'))
candidates.append(functools.partial(ExtraFrameworkDependency,
'sdl2', False, None, environment,
kwargs.get('language', None), kwargs))
# fwdep.version = '2' # FIXME
return candidates
return SDL2Dependency(environment, kwargs)
@staticmethod
def tool_finish_init(ctdep):
ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
@staticmethod
def get_methods():
@ -518,73 +515,73 @@ class VulkanDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('vulkan', environment, None, kwargs)
if DependencyMethods.SYSTEM in self.methods:
try:
self.vulkan_sdk = os.environ['VULKAN_SDK']
if not os.path.isabs(self.vulkan_sdk):
raise DependencyException('VULKAN_SDK must be an absolute path.')
except KeyError:
self.vulkan_sdk = None
if self.vulkan_sdk:
# TODO: this config might not work on some platforms, fix bugs as reported
# we should at least detect other 64-bit platforms (e.g. armv8)
try:
self.vulkan_sdk = os.environ['VULKAN_SDK']
if not os.path.isabs(self.vulkan_sdk):
raise DependencyException('VULKAN_SDK must be an absolute path.')
except KeyError:
self.vulkan_sdk = None
if self.vulkan_sdk:
# TODO: this config might not work on some platforms, fix bugs as reported
# we should at least detect other 64-bit platforms (e.g. armv8)
lib_name = 'vulkan'
if mesonlib.is_windows():
lib_name = 'vulkan-1'
lib_dir = 'Lib32'
inc_dir = 'Include'
if detect_cpu({}) == 'x86_64':
lib_dir = 'Lib'
else:
lib_name = 'vulkan'
if mesonlib.is_windows():
lib_name = 'vulkan-1'
lib_dir = 'Lib32'
inc_dir = 'Include'
if detect_cpu({}) == 'x86_64':
lib_dir = 'Lib'
else:
lib_name = 'vulkan'
lib_dir = 'lib'
inc_dir = 'include'
lib_dir = 'lib'
inc_dir = 'include'
# make sure header and lib are valid
inc_path = os.path.join(self.vulkan_sdk, inc_dir)
header = os.path.join(inc_path, 'vulkan', 'vulkan.h')
lib_path = os.path.join(self.vulkan_sdk, lib_dir)
find_lib = self.clib_compiler.find_library(lib_name, environment, lib_path)
# make sure header and lib are valid
inc_path = os.path.join(self.vulkan_sdk, inc_dir)
header = os.path.join(inc_path, 'vulkan', 'vulkan.h')
lib_path = os.path.join(self.vulkan_sdk, lib_dir)
find_lib = self.clib_compiler.find_library(lib_name, environment, lib_path)
if not find_lib:
raise DependencyException('VULKAN_SDK point to invalid directory (no lib)')
if not find_lib:
raise DependencyException('VULKAN_SDK point to invalid directory (no lib)')
if not os.path.isfile(header):
raise DependencyException('VULKAN_SDK point to invalid directory (no include)')
if not os.path.isfile(header):
raise DependencyException('VULKAN_SDK point to invalid directory (no include)')
self.type_name = 'vulkan_sdk'
self.is_found = True
self.compile_args.append('-I' + inc_path)
self.link_args.append('-L' + lib_path)
self.link_args.append('-l' + lib_name)
self.type_name = 'vulkan_sdk'
self.is_found = True
self.compile_args.append('-I' + inc_path)
self.link_args.append('-L' + lib_path)
self.link_args.append('-l' + lib_name)
# TODO: find a way to retrieve the version from the sdk?
# Usually it is a part of the path to it (but does not have to be)
self.version = '1'
# TODO: find a way to retrieve the version from the sdk?
# Usually it is a part of the path to it (but does not have to be)
self.version = '1'
return
else:
# simply try to guess it, usually works on linux
libs = self.clib_compiler.find_library('vulkan', environment, [])
if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment):
self.type_name = 'system'
self.is_found = True
self.version = 1 # TODO
for lib in libs:
self.link_args.append(lib)
return
else:
# simply try to guess it, usually works on linux
libs = self.clib_compiler.find_library('vulkan', environment, [])
if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment):
self.type_name = 'system'
self.is_found = True
self.version = 1 # TODO
for lib in libs:
self.link_args.append(lib)
return
@classmethod
def _factory(cls, environment, kwargs):
if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
try:
pcdep = PkgConfigDependency('vulkan', environment, kwargs)
if pcdep.found():
return pcdep
except Exception:
pass
methods = cls._process_method_kw(kwargs)
candidates = []
if DependencyMethods.PKGCONFIG in methods:
candidates.append(functools.partial(PkgConfigDependency, 'vulkan', environment, kwargs))
return VulkanDependency(environment, kwargs)
if DependencyMethods.PKGCONFIG in methods:
candidates.append(functools.partial(VulkanDependency, environment, kwargs))
return candidates
@staticmethod
def get_methods():

@ -3025,11 +3025,12 @@ class LinuxlikeTests(BasePlatformTests):
raise unittest.SkipTest('Qt not found with pkg-config')
testdir = os.path.join(self.framework_test_dir, '4 qt')
self.init(testdir, ['-Dmethod=pkg-config'])
# Confirm that the dependency was found with qmake
msg = 'Qt4 native `pkg-config` dependency (modules: Core, Gui) found: YES\n'
msg2 = 'Qt5 native `pkg-config` dependency (modules: Core, Gui) found: YES\n'
# Confirm that the dependency was found with pkg-config
mesonlog = self.get_meson_log()
self.assertTrue(msg in mesonlog or msg2 in mesonlog)
self.assertRegex('\n'.join(mesonlog),
r'Dependency qt4 \(modules: Core\) found: YES .*, `pkg-config`\n')
self.assertRegex('\n'.join(mesonlog),
r'Dependency qt5 \(modules: Core\) found: YES .*, `pkg-config`\n')
def test_qt5dependency_qmake_detection(self):
'''
@ -3047,10 +3048,9 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.framework_test_dir, '4 qt')
self.init(testdir, ['-Dmethod=qmake'])
# Confirm that the dependency was found with qmake
msg = 'Qt5 native `qmake-qt5` dependency (modules: Core) found: YES\n'
msg2 = 'Qt5 native `qmake` dependency (modules: Core) found: YES\n'
mesonlog = self.get_meson_log()
self.assertTrue(msg in mesonlog or msg2 in mesonlog)
self.assertRegex('\n'.join(mesonlog),
r'Dependency qt5 \(modules: Core\) found: YES .*, `(qmake|qmake-qt5)`\n')
def _test_soname_impl(self, libpath, install):
if is_cygwin() or is_osx():

Loading…
Cancel
Save