aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-06-11 14:49:52 +0300
committerGitHub <noreply@github.com>2017-06-11 14:49:52 +0300
commitb8f02047bec9fd2d1a36db82df5fed14ef386cd6 (patch)
treeb4f2e99205f3b3846a086610802ad023227a35ae
parent22cfd44221ada3219d9096e15dc8b00d32e0f9f6 (diff)
parent868d85d2e567b0f5cfb49858eb0f2ac96f7d5749 (diff)
downloadmeson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.zip
meson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.tar.gz
meson-b8f02047bec9fd2d1a36db82df5fed14ef386cd6.tar.bz2
Merge pull request #1900 from centricular/abstract-extdeps
dependencies: Add a new class ExternalDependency
-rw-r--r--.appveyor.yml2
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/vs2010backend.py32
-rw-r--r--mesonbuild/backend/vs2017backend.py4
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers.py2
-rw-r--r--mesonbuild/dependencies/__init__.py5
-rw-r--r--mesonbuild/dependencies/base.py185
-rw-r--r--mesonbuild/dependencies/dev.py111
-rw-r--r--mesonbuild/dependencies/misc.py80
-rw-r--r--mesonbuild/dependencies/platform.py16
-rw-r--r--mesonbuild/dependencies/ui.py220
-rw-r--r--mesonbuild/interpreter.py3
-rw-r--r--mesonbuild/mesonmain.py4
-rw-r--r--mesonbuild/modules/gnome.py2
-rwxr-xr-xrun_project_tests.py29
-rwxr-xr-xrun_tests.py18
-rwxr-xr-xrun_unittests.py156
-rw-r--r--test cases/frameworks/15 llvm/meson.build7
-rw-r--r--test cases/frameworks/16 sdl2/meson.build10
-rw-r--r--test cases/frameworks/16 sdl2/sdl2prog.c33
-rw-r--r--test cases/frameworks/4 qt/meson.build6
-rw-r--r--test cases/linuxlike/5 dependency versions/meson.build12
-rw-r--r--test cases/osx/4 framework/meson.build9
24 files changed, 496 insertions, 454 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 1e20a37..6551445 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -55,6 +55,8 @@ skip_commits:
install:
- cmd: set "ORIG_PATH=%PATH%"
+ # Boost 1.56.0: https://www.appveyor.com/docs/build-environment/#boost
+ #- cmd: set "BOOST_ROOT=C:\Libraries\boost"
# Use the x86 python only when building for x86 for the cpython tests.
# For all other archs (including, say, arm), use the x64 python.
- ps: (new-object net.webclient).DownloadFile('https://www.dropbox.com/s/bbzvepq85hv47x1/ninja.exe?dl=1', 'C:\projects\meson\ninja.exe')
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 3044ce6..05d6e03 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -429,7 +429,7 @@ class Backend:
break
commands += ['--pkg', dep.name]
elif isinstance(dep, dependencies.ExternalLibrary):
- commands += dep.get_lang_args('vala')
+ commands += dep.get_link_args('vala')
else:
commands += dep.get_compile_args()
# Qt needs -fPIC for executables
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index fafde8f..d4a7a19 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -29,26 +29,24 @@ from ..environment import Environment
def autodetect_vs_version(build):
vs_version = os.getenv('VisualStudioVersion', None)
- if vs_version:
- if vs_version == '14.0':
- from mesonbuild.backend.vs2015backend import Vs2015Backend
- return Vs2015Backend(build)
- if vs_version == '15.0':
- from mesonbuild.backend.vs2017backend import Vs2017Backend
- return Vs2017Backend(build)
- raise MesonException('Could not detect Visual Studio (unknown Visual Studio version: "{}")!\n'
- 'Please specify the exact backend to use.'.format(vs_version))
-
vs_install_dir = os.getenv('VSINSTALLDIR', None)
- if not vs_install_dir:
- raise MesonException('Could not detect Visual Studio (neither VisualStudioVersion nor VSINSTALLDIR set in '
- 'environment)!\nPlease specify the exact backend to use.')
-
+ if not vs_version and not vs_install_dir:
+ raise MesonException('Could not detect Visual Studio: VisualStudioVersion and VSINSTALLDIR are unset!\n'
+ 'Are we inside a Visual Studio build environment? '
+ 'You can also try specifying the exact backend to use.')
+ # VisualStudioVersion is set since Visual Studio 12.0, but sometimes
+ # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR
+ if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir:
+ from mesonbuild.backend.vs2015backend import Vs2015Backend
+ return Vs2015Backend(build)
+ if vs_version == '15.0' or 'Visual Studio 17' in vs_install_dir or \
+ 'Visual Studio\\2017' in vs_install_dir:
+ from mesonbuild.backend.vs2017backend import Vs2017Backend
+ return Vs2017Backend(build)
if 'Visual Studio 10.0' in vs_install_dir:
return Vs2010Backend(build)
-
- raise MesonException('Could not detect Visual Studio (unknown VSINSTALLDIR: "{}")!\n'
- 'Please specify the exact backend to use.'.format(vs_install_dir))
+ raise MesonException('Could not detect Visual Studio using VisualStudioVersion: {!r} or VSINSTALLDIR: {!r}!\n'
+ 'Please specify the exact backend to use.'.format(vs_version, vs_install_dir))
def split_o_flags_args(args):
"""
diff --git a/mesonbuild/backend/vs2017backend.py b/mesonbuild/backend/vs2017backend.py
index 35d56f3..fe1d7c7 100644
--- a/mesonbuild/backend/vs2017backend.py
+++ b/mesonbuild/backend/vs2017backend.py
@@ -24,4 +24,6 @@ class Vs2017Backend(Vs2010Backend):
self.platform_toolset = 'v141'
self.vs_version = '2017'
# WindowsSDKVersion should be set by command prompt.
- self.windows_target_platform_version = os.getenv('WindowsSDKVersion', None).rstrip('\\')
+ sdk_version = os.environ.get('WindowsSDKVersion', None)
+ if sdk_version:
+ self.windows_target_platform_version = sdk_version.rstrip('\\')
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 2c55ed4..ba30fec 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -806,7 +806,7 @@ class BuildTarget(Target):
self.external_deps.append(extpart)
# Deps of deps.
self.add_deps(dep.ext_deps)
- elif isinstance(dep, dependencies.Dependency):
+ elif isinstance(dep, dependencies.ExternalDependency):
self.external_deps.append(dep)
self.process_sourcelist(dep.get_sources())
elif isinstance(dep, BuildTarget):
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index c9cfb46..977b7c4 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -1773,7 +1773,7 @@ class ValaCompiler(Compiler):
for d in extra_dirs:
vapi = os.path.join(d, libname + '.vapi')
if os.path.isfile(vapi):
- return vapi
+ return [vapi]
mlog.debug('Searched {!r} and {!r} wasn\'t found'.format(extra_dirs, libname))
return None
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py
index ec11152..3d41a2b 100644
--- a/mesonbuild/dependencies/__init__.py
+++ b/mesonbuild/dependencies/__init__.py
@@ -13,8 +13,9 @@
# limitations under the License.
from .base import ( # noqa: F401
- Dependency, DependencyException, DependencyMethods, ExternalProgram, ExternalLibrary, ExtraFrameworkDependency,
- InternalDependency, PkgConfigDependency, find_external_dependency, get_dep_identifier, packages)
+ Dependency, DependencyException, DependencyMethods, ExternalProgram,
+ ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency,
+ PkgConfigDependency, find_external_dependency, get_dep_identifier, packages)
from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency
from .misc import BoostDependency, Python3Dependency, ThreadDependency
from .platform import AppleFrameworks
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 139ff39..14ec41e 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -52,10 +52,17 @@ class DependencyMethods(Enum):
class Dependency:
def __init__(self, type_name, kwargs):
self.name = "null"
- self.language = None
+ self.version = 'none'
+ self.language = None # None means C-like
self.is_found = False
self.type_name = type_name
- method = DependencyMethods(kwargs.get('method', 'auto'))
+ self.compile_args = []
+ self.link_args = []
+ self.sources = []
+ method = kwargs.get('method', 'auto')
+ if method not in [e.value for e in DependencyMethods]:
+ raise DependencyException('method {!r} is invalid'.format(method))
+ method = DependencyMethods(method)
# Set the detection method. If the method is set to auto, use any available method.
# If method is set to a specific string, allow only that detection method.
@@ -64,7 +71,7 @@ class Dependency:
elif method in self.get_methods():
self.methods = [method]
else:
- raise MesonException(
+ raise DependencyException(
'Unsupported detection method: {}, allowed methods are {}'.format(
method.value,
mlog.format_list(map(lambda x: x.value, [DependencyMethods.AUTO] + self.get_methods()))))
@@ -74,10 +81,10 @@ class Dependency:
return s.format(self.__class__.__name__, self.name, self.is_found)
def get_compile_args(self):
- return []
+ return self.compile_args
def get_link_args(self):
- return []
+ return self.link_args
def found(self):
return self.is_found
@@ -85,7 +92,7 @@ class Dependency:
def get_sources(self):
"""Source files that need to be added to the target.
As an example, gtest-all.cc when using GTest."""
- return []
+ return self.sources
def get_methods(self):
return [DependencyMethods.AUTO]
@@ -93,6 +100,9 @@ class Dependency:
def get_name(self):
return self.name
+ def get_version(self):
+ return self.version
+
def get_exe_args(self, compiler):
return []
@@ -100,7 +110,7 @@ class Dependency:
return False
def get_pkgconfig_variable(self, variable_name):
- raise MesonException('Tried to get a pkg-config variable from a non-pkgconfig dependency.')
+ raise NotImplementedError('{!r} is not a pkgconfig dependency'.format(self.name))
class InternalDependency(Dependency):
@@ -115,41 +125,52 @@ class InternalDependency(Dependency):
self.sources = sources
self.ext_deps = ext_deps
- def get_compile_args(self):
- return self.compile_args
- def get_link_args(self):
- return self.link_args
+class ExternalDependency(Dependency):
+ def __init__(self, type_name, environment, language, kwargs):
+ super().__init__(type_name, kwargs)
+ self.env = environment
+ self.name = type_name # default
+ self.is_found = False
+ self.language = language
+ if language and language not in self.env.coredata.compilers:
+ m = self.name.capitalize() + ' requires a {} compiler'
+ raise DependencyException(m.format(language.capitalize()))
+ self.version_reqs = kwargs.get('version', None)
+ self.required = kwargs.get('required', True)
+ self.silent = kwargs.get('silent', False)
+ self.static = kwargs.get('static', False)
+ if not isinstance(self.static, bool):
+ raise DependencyException('Static keyword must be boolean')
+ # Is this dependency for cross-compilation?
+ if 'native' in kwargs and self.env.is_cross_build():
+ self.want_cross = not kwargs['native']
+ else:
+ self.want_cross = self.env.is_cross_build()
+ # Set the compiler that will be used by this dependency
+ # This is only used for configuration checks
+ if self.want_cross:
+ compilers = self.env.coredata.cross_compilers
+ else:
+ compilers = self.env.coredata.compilers
+ self.compiler = compilers.get(self.language or 'c', None)
- def get_version(self):
- return self.version
+ def get_compiler(self):
+ return self.compiler
-class PkgConfigDependency(Dependency):
+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.
class_pkgbin = None
def __init__(self, name, environment, kwargs):
- Dependency.__init__(self, 'pkgconfig', kwargs)
+ super().__init__('pkgconfig', environment, None, kwargs)
+ self.name = name
self.is_libtool = False
- self.version_reqs = kwargs.get('version', None)
- self.required = kwargs.get('required', True)
- self.static = kwargs.get('static', False)
- self.silent = kwargs.get('silent', False)
- if not isinstance(self.static, bool):
- raise DependencyException('Static keyword must be boolean')
# Store a copy of the pkg-config path on the object itself so it is
# stored in the pickled coredata and recovered.
self.pkgbin = None
- self.cargs = []
- self.libs = []
- if 'native' in kwargs and environment.is_cross_build():
- self.want_cross = not kwargs['native']
- else:
- self.want_cross = environment.is_cross_build()
- self.name = name
- self.modversion = 'none'
# When finding dependencies for cross-compiling, we don't care about
# the 'native' pkg-config
@@ -175,7 +196,6 @@ class PkgConfigDependency(Dependency):
else:
self.pkgbin = PkgConfigDependency.class_pkgbin
- self.is_found = False
if not self.pkgbin:
if self.required:
raise DependencyException('Pkg-config not found.')
@@ -187,7 +207,7 @@ class PkgConfigDependency(Dependency):
mlog.debug('Determining dependency {!r} with pkg-config executable '
'{!r}'.format(name, self.pkgbin))
- ret, self.modversion = self._call_pkgbin(['--modversion', name])
+ ret, self.version = self._call_pkgbin(['--modversion', name])
if ret != 0:
if self.required:
raise DependencyException('{} dependency {!r} not found'
@@ -202,10 +222,10 @@ class PkgConfigDependency(Dependency):
if isinstance(self.version_reqs, str):
self.version_reqs = [self.version_reqs]
(self.is_found, not_found, found) = \
- version_compare_many(self.modversion, self.version_reqs)
+ version_compare_many(self.version, self.version_reqs)
if not self.is_found:
found_msg += [mlog.red('NO'),
- 'found {!r} but need:'.format(self.modversion),
+ 'found {!r} but need:'.format(self.version),
', '.join(["'{}'".format(e) for e in not_found])]
if found:
found_msg += ['; matched:',
@@ -214,9 +234,9 @@ class PkgConfigDependency(Dependency):
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.modversion))
+ raise DependencyException(m.format(name, not_found, self.version))
return
- found_msg += [mlog.green('YES'), self.modversion]
+ found_msg += [mlog.green('YES'), self.version]
# Fetch cargs to be used while using this dependency
self._set_cargs()
# Fetch the libraries and library paths needed for using this
@@ -240,7 +260,7 @@ class PkgConfigDependency(Dependency):
if ret != 0:
raise DependencyException('Could not generate cargs for %s:\n\n%s' %
(self.name, out))
- self.cargs = out.split()
+ self.compile_args = out.split()
def _set_libs(self):
libcmd = [self.name, '--libs']
@@ -250,7 +270,7 @@ class PkgConfigDependency(Dependency):
if ret != 0:
raise DependencyException('Could not generate libs for %s:\n\n%s' %
(self.name, out))
- self.libs = []
+ self.link_args = []
for lib in out.split():
if lib.endswith(".la"):
shared_libname = self.extract_libtool_shlib(lib)
@@ -264,7 +284,7 @@ class PkgConfigDependency(Dependency):
'library path' % lib)
lib = shared_lib
self.is_libtool = True
- self.libs.append(lib)
+ self.link_args.append(lib)
def get_pkgconfig_variable(self, variable_name):
ret, out = self._call_pkgbin(['--variable=' + variable_name, self.name])
@@ -278,18 +298,6 @@ class PkgConfigDependency(Dependency):
mlog.debug('Got pkgconfig variable %s : %s' % (variable_name, variable))
return variable
- def get_modversion(self):
- return self.modversion
-
- def get_version(self):
- return self.modversion
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
def get_methods(self):
return [DependencyMethods.PKGCONFIG]
@@ -319,9 +327,6 @@ class PkgConfigDependency(Dependency):
mlog.log('Found Pkg-config:', mlog.red('NO'))
return pkgbin
- def found(self):
- return self.is_found
-
def extract_field(self, la_file, fieldname):
with open(la_file) as f:
for line in f:
@@ -500,52 +505,37 @@ class ExternalProgram:
return self.name
-class ExternalLibrary(Dependency):
- # TODO: Add `language` support to all Dependency objects so that languages
- # can be exposed for dependencies that support that (i.e., not pkg-config)
- def __init__(self, name, link_args, language, silent=False):
- super().__init__('external', {})
+class ExternalLibrary(ExternalDependency):
+ def __init__(self, name, link_args, environment, language, silent=False):
+ super().__init__('external', environment, language, {})
self.name = name
self.language = language
self.is_found = False
- self.link_args = []
- self.lang_args = []
if link_args:
self.is_found = True
- if not isinstance(link_args, list):
- link_args = [link_args]
- self.lang_args = {language: link_args}
- # We special-case Vala for now till the Dependency object gets
- # proper support for exposing the language it was written in.
- # Without this, vala-specific link args will end up in the C link
- # args list if you link to a Vala library.
- # This hack use to be in CompilerHolder.find_library().
- if language != 'vala':
- self.link_args = link_args
+ self.link_args = link_args
if not silent:
if self.is_found:
mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'))
else:
mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
- def found(self):
- return self.is_found
-
- def get_name(self):
- return self.name
-
- def get_link_args(self):
+ def get_link_args(self, language=None):
+ '''
+ External libraries detected using a compiler must only be used with
+ compatible code. For instance, Vala libraries (.vapi files) cannot be
+ used with C code, and not all Rust library types can be linked with
+ C-like code. Note that C++ libraries *can* be linked with C code with
+ a C++ linker (and vice-versa).
+ '''
+ if self.language == 'vala' and language != 'vala':
+ return []
return self.link_args
- def get_lang_args(self, lang):
- if lang in self.lang_args:
- return self.lang_args[lang]
- return []
-
-class ExtraFrameworkDependency(Dependency):
- def __init__(self, name, required, path, kwargs):
- Dependency.__init__(self, 'extraframeworks', kwargs)
+class ExtraFrameworkDependency(ExternalDependency):
+ def __init__(self, name, required, path, env, lang, kwargs):
+ super().__init__('extraframeworks', env, lang, kwargs)
self.name = None
self.required = required
self.detect(name, path)
@@ -570,6 +560,7 @@ class ExtraFrameworkDependency(Dependency):
continue
self.path = p
self.name = d
+ self.is_found = True
return
if not self.found() and self.required:
raise DependencyException('Framework dependency %s not found.' % (name, ))
@@ -584,9 +575,6 @@ class ExtraFrameworkDependency(Dependency):
return ['-F' + self.path, '-framework', self.name.split('.')[0]]
return []
- def found(self):
- return self.name is not None
-
def get_version(self):
return 'unknown'
@@ -611,7 +599,7 @@ def get_dep_identifier(name, kwargs, want_cross):
return identifier
-def find_external_dependency(name, environment, kwargs):
+def find_external_dependency(name, env, kwargs):
required = kwargs.get('required', True)
if not isinstance(required, bool):
raise DependencyException('Keyword "required" must be a boolean.')
@@ -619,20 +607,20 @@ def find_external_dependency(name, environment, kwargs):
raise DependencyException('Keyword "method" must be a string.')
lname = name.lower()
if lname in packages:
- dep = packages[lname](environment, kwargs)
+ dep = packages[lname](env, kwargs)
if required and not dep.found():
raise DependencyException('Dependency "%s" not found' % name)
return dep
pkg_exc = None
pkgdep = None
try:
- pkgdep = PkgConfigDependency(name, environment, kwargs)
+ pkgdep = PkgConfigDependency(name, env, kwargs)
if pkgdep.found():
return pkgdep
except Exception as e:
pkg_exc = e
if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency(name, required, None, kwargs)
+ 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)
@@ -642,16 +630,3 @@ def find_external_dependency(name, environment, kwargs):
raise pkg_exc
mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
return pkgdep
-
-def dependency_get_compiler(language, environment, kwargs):
- if 'native' in kwargs and environment.is_cross_build():
- want_cross = not kwargs['native']
- else:
- want_cross = environment.is_cross_build()
-
- if want_cross:
- compilers = environment.coredata.cross_compilers
- else:
- compilers = environment.coredata.compilers
-
- return compilers.get(language, None)
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index 76d6691..d7a7181 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -22,29 +22,20 @@ import shutil
from .. import mlog
from .. import mesonlib
from ..mesonlib import version_compare, Popen_safe
-from .base import Dependency, DependencyException, PkgConfigDependency, dependency_get_compiler
+from .base import DependencyException, ExternalDependency, PkgConfigDependency
-class GTestDependency(Dependency):
+class GTestDependency(ExternalDependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'gtest', kwargs)
- self.env = environment
+ super().__init__('gtest', environment, 'cpp', kwargs)
self.main = kwargs.get('main', False)
- self.name = 'gtest'
- self.include_dir = '/usr/include'
self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
-
- self.cpp_compiler = dependency_get_compiler('cpp', environment, kwargs)
- if self.cpp_compiler is None:
- raise DependencyException('Tried to use gtest but a C++ compiler is not defined.')
self.detect()
- def found(self):
- return self.is_found
-
def detect(self):
- gtest_detect = self.cpp_compiler.find_library("gtest", self.env, [])
- gtest_main_detect = self.cpp_compiler.find_library("gtest_main", self.env, [])
- if gtest_detect and gtest_main_detect:
+ self.version = '1.something_maybe'
+ gtest_detect = self.compiler.find_library("gtest", self.env, [])
+ gtest_main_detect = self.compiler.find_library("gtest_main", self.env, [])
+ if gtest_detect and (not self.main or gtest_main_detect):
self.is_found = True
self.compile_args = []
self.link_args = gtest_detect
@@ -64,7 +55,6 @@ class GTestDependency(Dependency):
else:
mlog.log('Dependency GTest found:', mlog.red('NO'))
self.is_found = False
- return self.is_found
def detect_srcdir(self):
for s in self.src_dirs:
@@ -78,37 +68,17 @@ class GTestDependency(Dependency):
return True
return False
- def get_compile_args(self):
- arr = []
- if self.include_dir != '/usr/include':
- arr.append('-I' + self.include_dir)
- if hasattr(self, 'src_include_dir'):
- arr.append('-I' + self.src_include_dir)
- return arr
-
- def get_link_args(self):
- return self.link_args
-
- def get_version(self):
- return '1.something_maybe'
-
- def get_sources(self):
- return self.sources
-
def need_threads(self):
return True
-class GMockDependency(Dependency):
+class GMockDependency(ExternalDependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'gmock', kwargs)
+ super().__init__('gmock', environment, 'cpp', kwargs)
+ self.version = '1.something_maybe'
# GMock may be a library or just source.
# Work with both.
- self.name = 'gmock'
- cpp_compiler = dependency_get_compiler('cpp', environment, kwargs)
- if cpp_compiler is None:
- raise DependencyException('Tried to use gmock but a C++ compiler is not defined.')
- gmock_detect = cpp_compiler.find_library("gmock", environment, [])
+ gmock_detect = self.compiler.find_library("gmock", self.env, [])
if gmock_detect:
self.is_found = True
self.compile_args = []
@@ -133,29 +103,12 @@ class GMockDependency(Dependency):
self.sources = [all_src]
mlog.log('Dependency GMock found:', mlog.green('YES'), '(building self)')
return
-
mlog.log('Dependency GMock found:', mlog.red('NO'))
self.is_found = False
- def get_version(self):
- return '1.something_maybe'
-
- def get_compile_args(self):
- return self.compile_args
-
- def get_sources(self):
- return self.sources
-
- def get_link_args(self):
- return self.link_args
-
- def found(self):
- return self.is_found
-
-
-class LLVMDependency(Dependency):
- """LLVM dependency.
+class LLVMDependency(ExternalDependency):
+ """
LLVM uses a special tool, llvm-config, which has arguments for getting
c args, cxx args, and ldargs as well as version.
"""
@@ -182,15 +135,11 @@ class LLVMDependency(Dependency):
__cpp_blacklist = {'-DNDEBUG'}
def __init__(self, environment, kwargs):
- super().__init__('llvm-config', kwargs)
# It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
# the C linker works fine if only using the C API.
- self.language = 'cpp'
- self.cargs = []
- self.libs = []
+ super().__init__('llvm-config', environment, 'cpp', kwargs)
self.modules = []
-
- required = kwargs.get('required', True)
+ # FIXME: Support multiple version requirements ala PkgConfigDependency
req_version = kwargs.get('version', None)
if self.llvmconfig is None:
self.check_llvmconfig(req_version)
@@ -201,14 +150,14 @@ class LLVMDependency(Dependency):
else:
mlog.log("No llvm-config found; can't detect dependency")
mlog.log('Dependency LLVM found:', mlog.red('NO'))
- if required:
+ if self.required:
raise DependencyException('Dependency LLVM not found')
return
p, out, err = Popen_safe([self.llvmconfig, '--version'])
if p.returncode != 0:
mlog.debug('stdout: {}\nstderr: {}'.format(out, err))
- if required:
+ if self.required:
raise DependencyException('Dependency LLVM not found')
return
else:
@@ -220,12 +169,13 @@ class LLVMDependency(Dependency):
[self.llvmconfig, '--libs', '--ldflags', '--system-libs'])[:2]
if p.returncode != 0:
raise DependencyException('Could not generate libs for LLVM.')
- self.libs = shlex.split(out)
+ self.link_args = shlex.split(out)
p, out = Popen_safe([self.llvmconfig, '--cppflags'])[:2]
if p.returncode != 0:
raise DependencyException('Could not generate includedir for LLVM.')
- self.cargs = list(mesonlib.OrderedSet(shlex.split(out)).difference(self.__cpp_blacklist))
+ cargs = mesonlib.OrderedSet(shlex.split(out))
+ self.compile_args = list(cargs.difference(self.__cpp_blacklist))
p, out = Popen_safe([self.llvmconfig, '--components'])[:2]
if p.returncode != 0:
@@ -237,21 +187,12 @@ class LLVMDependency(Dependency):
if mod not in self.modules:
mlog.log('LLVM module', mod, 'found:', mlog.red('NO'))
self.is_found = False
- if required:
+ if self.required:
raise DependencyException(
'Could not find required LLVM Component: {}'.format(mod))
else:
mlog.log('LLVM module', mod, 'found:', mlog.green('YES'))
- def get_version(self):
- return self.version
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
@classmethod
def check_llvmconfig(cls, version_req):
"""Try to find the highest version of llvm-config."""
@@ -261,6 +202,8 @@ class LLVMDependency(Dependency):
out = out.strip()
if p.returncode != 0:
continue
+ # FIXME: As soon as some llvm-config is found, version checks
+ # in further dependnecy() calls will be ignored
if version_req:
if version_compare(out, version_req, strict=True):
if cls.__best_found and version_compare(out, '<={}'.format(cls.__best_found), strict=True):
@@ -288,8 +231,12 @@ class LLVMDependency(Dependency):
class ValgrindDependency(PkgConfigDependency):
- def __init__(self, environment, kwargs):
- PkgConfigDependency.__init__(self, 'valgrind', environment, kwargs)
+ '''
+ Consumers of Valgrind usually only need the compile args and do not want to
+ link to its (static) libraries.
+ '''
+ def __init__(self, env, kwargs):
+ super().__init__('valgrind', env, None, kwargs)
def get_link_args(self):
return []
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 6a76ba6..c24acf0 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -23,25 +23,19 @@ from .. import mlog
from .. import mesonlib
from ..environment import detect_cpu_family
-from .base import Dependency, DependencyException, DependencyMethods, ExtraFrameworkDependency, PkgConfigDependency
+from .base import DependencyException, DependencyMethods
+from .base import ExternalDependency, ExtraFrameworkDependency, PkgConfigDependency
-class BoostDependency(Dependency):
+class BoostDependency(ExternalDependency):
# Some boost libraries have different names for
# their sources and libraries. This dict maps
# between the two.
name2lib = {'test': 'unit_test_framework'}
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'boost', kwargs)
- self.name = 'boost'
- self.environment = environment
+ super().__init__('boost', environment, 'cpp', kwargs)
self.libdir = ''
- self.static = kwargs.get('static', False)
- if 'native' in kwargs and environment.is_cross_build():
- self.want_cross = not kwargs['native']
- else:
- self.want_cross = environment.is_cross_build()
try:
self.boost_root = os.environ['BOOST_ROOT']
if not os.path.isabs(self.boost_root):
@@ -72,7 +66,7 @@ class BoostDependency(Dependency):
self.detect_version()
self.requested_modules = self.get_requested(kwargs)
module_str = ', '.join(self.requested_modules)
- if self.version is not None:
+ if self.is_found:
self.detect_src_modules()
self.detect_lib_modules()
self.validate_requested()
@@ -83,9 +77,6 @@ class BoostDependency(Dependency):
mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info)
else:
mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO'))
- if 'cpp' not in self.environment.coredata.compilers:
- raise DependencyException('Tried to use Boost but a C++ compiler is not defined.')
- self.cpp_compiler = self.environment.coredata.compilers['cpp']
def detect_win_root(self):
globtext = 'c:\\local\\boost_*'
@@ -130,13 +121,13 @@ class BoostDependency(Dependency):
# names in order to handle cases like cross-compiling where we
# might have a different sysroot.
if not include_dir.endswith(('/usr/include', '/usr/local/include')):
- args.append("".join(self.cpp_compiler.get_include_args(include_dir, True)))
+ args.append("".join(self.compiler.get_include_args(include_dir, True)))
return args
def get_requested(self, kwargs):
candidates = kwargs.get('modules', [])
- if isinstance(candidates, str):
- return [candidates]
+ if not isinstance(candidates, list):
+ candidates = [candidates]
for c in candidates:
if not isinstance(c, str):
raise DependencyException('Boost module argument is not a string.')
@@ -145,19 +136,13 @@ class BoostDependency(Dependency):
def validate_requested(self):
for m in self.requested_modules:
if m not in self.src_modules:
- raise DependencyException('Requested Boost module "%s" not found.' % m)
-
- def found(self):
- return self.version is not None
-
- def get_version(self):
- return self.version
+ msg = 'Requested Boost module {!r} not found'
+ raise DependencyException(msg.format(m))
def detect_version(self):
try:
ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp'))
except FileNotFoundError:
- self.version = None
return
with ifile:
for line in ifile:
@@ -165,8 +150,8 @@ class BoostDependency(Dependency):
ver = line.split()[-1]
ver = ver[1:-1]
self.version = ver.replace('_', '.')
+ self.is_found = True
return
- self.version = None
def detect_src_modules(self):
for entry in os.listdir(self.boost_inc_subdir):
@@ -180,7 +165,7 @@ class BoostDependency(Dependency):
return self.detect_lib_modules_nix()
def detect_lib_modules_win(self):
- arch = detect_cpu_family(self.environment.coredata.compilers)
+ arch = detect_cpu_family(self.env.coredata.compilers)
# Guess the libdir
if arch == 'x86':
gl = 'lib32*'
@@ -254,10 +239,10 @@ class BoostDependency(Dependency):
module = BoostDependency.name2lib.get(module, module)
libname = 'boost_' + module
# The compiler's library detector is the most reliable so use that first.
- default_detect = self.cpp_compiler.find_library(libname, self.environment, [])
+ default_detect = self.compiler.find_library(libname, self.env, [])
if default_detect is not None:
if module == 'unit_testing_framework':
- emon_args = self.cpp_compiler.find_library('boost_test_exec_monitor')
+ emon_args = self.compiler.find_library('boost_test_exec_monitor')
else:
emon_args = None
args += default_detect
@@ -286,9 +271,9 @@ class BoostDependency(Dependency):
return 'thread' in self.requested_modules
-class ThreadDependency(Dependency):
+class ThreadDependency(ExternalDependency):
def __init__(self, environment, kwargs):
- super().__init__('threads', {})
+ super().__init__('threads', environment, None, {})
self.name = 'threads'
self.is_found = True
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES'))
@@ -300,19 +285,18 @@ class ThreadDependency(Dependency):
return 'unknown'
-class Python3Dependency(Dependency):
+class Python3Dependency(ExternalDependency):
def __init__(self, environment, kwargs):
- super().__init__('python3', kwargs)
+ super().__init__('python3', environment, None, kwargs)
self.name = 'python3'
- self.is_found = False
# We can only be sure that it is Python 3 at this point
self.version = '3'
if DependencyMethods.PKGCONFIG in self.methods:
try:
pkgdep = PkgConfigDependency('python3', environment, kwargs)
if pkgdep.found():
- self.cargs = pkgdep.cargs
- self.libs = pkgdep.libs
+ self.compile_args = pkgdep.get_compile_args()
+ self.link_args = pkgdep.get_link_args()
self.version = pkgdep.get_version()
self.is_found = True
return
@@ -324,10 +308,11 @@ class Python3Dependency(Dependency):
elif mesonlib.is_osx() and DependencyMethods.EXTRAFRAMEWORK in self.methods:
# In OSX the Python 3 framework does not have a version
# number in its name.
- fw = ExtraFrameworkDependency('python', False, None, kwargs)
+ fw = ExtraFrameworkDependency('python', False, None, self.env,
+ self.language, kwargs)
if fw.found():
- self.cargs = fw.get_compile_args()
- self.libs = fw.get_link_args()
+ 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'))
@@ -359,23 +344,17 @@ class Python3Dependency(Dependency):
return
inc = sysconfig.get_path('include')
platinc = sysconfig.get_path('platinclude')
- self.cargs = ['-I' + inc]
+ self.compile_args = ['-I' + inc]
if inc != platinc:
- self.cargs.append('-I' + platinc)
+ self.compile_args.append('-I' + platinc)
# Nothing exposes this directly that I coulf find
basedir = sysconfig.get_config_var('base')
vernum = sysconfig.get_config_var('py_version_nodot')
- self.libs = ['-L{}/libs'.format(basedir),
- '-lpython{}'.format(vernum)]
+ self.link_args = ['-L{}/libs'.format(basedir),
+ '-lpython{}'.format(vernum)]
self.version = sysconfig.get_config_var('py_version_short')
self.is_found = True
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
def get_methods(self):
if mesonlib.is_windows():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG]
@@ -383,6 +362,3 @@ class Python3Dependency(Dependency):
return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK]
else:
return [DependencyMethods.PKGCONFIG]
-
- def get_version(self):
- return self.version
diff --git a/mesonbuild/dependencies/platform.py b/mesonbuild/dependencies/platform.py
index cd46412..95ab727 100644
--- a/mesonbuild/dependencies/platform.py
+++ b/mesonbuild/dependencies/platform.py
@@ -17,25 +17,21 @@
from .. import mesonlib
-from .base import Dependency, DependencyException
+from .base import ExternalDependency, DependencyException
-class AppleFrameworks(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'appleframeworks', kwargs)
+class AppleFrameworks(ExternalDependency):
+ def __init__(self, env, kwargs):
+ super().__init__('appleframeworks', env, None, kwargs)
modules = kwargs.get('modules', [])
if isinstance(modules, str):
modules = [modules]
if not modules:
raise DependencyException("AppleFrameworks dependency requires at least one module.")
self.frameworks = modules
-
- def get_link_args(self):
- args = []
+ # FIXME: Use self.compiler to check if the frameworks are available
for f in self.frameworks:
- args.append('-framework')
- args.append(f)
- return args
+ self.link_args += ['-framework', f]
def found(self):
return mesonlib.is_osx()
diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index 3174176..8537a7e 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -26,24 +26,22 @@ from .. import mesonlib
from ..mesonlib import MesonException, Popen_safe, version_compare
from ..environment import for_windows
-from .base import (Dependency, DependencyException, DependencyMethods,
- ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency)
+from .base import DependencyException, DependencyMethods
+from .base import ExternalDependency, ExternalProgram
+from .base import ExtraFrameworkDependency, PkgConfigDependency
-class GLDependency(Dependency):
+class GLDependency(ExternalDependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'gl', kwargs)
- self.is_found = False
- self.cargs = []
- self.linkargs = []
+ super().__init__('gl', environment, None, kwargs)
if DependencyMethods.PKGCONFIG in self.methods:
try:
pcdep = PkgConfigDependency('gl', environment, kwargs)
if pcdep.found():
self.type_name = 'pkgconfig'
self.is_found = True
- self.cargs = pcdep.get_compile_args()
- self.linkargs = pcdep.get_link_args()
+ self.compile_args = pcdep.get_compile_args()
+ self.link_args = pcdep.get_link_args()
self.version = pcdep.get_version()
return
except Exception:
@@ -51,21 +49,19 @@ class GLDependency(Dependency):
if DependencyMethods.SYSTEM in self.methods:
if mesonlib.is_osx():
self.is_found = True
- self.linkargs = ['-framework', 'OpenGL']
- self.version = '1' # FIXME
+ # FIXME: Use AppleFrameworks dependency
+ self.link_args = ['-framework', 'OpenGL']
+ # FIXME: Detect version using self.compiler
+ self.version = '1'
return
if mesonlib.is_windows():
self.is_found = True
- self.linkargs = ['-lopengl32']
- self.version = '1' # FIXME: unfixable?
+ # FIXME: Use self.compiler.find_library()
+ self.link_args = ['-lopengl32']
+ # FIXME: Detect version using self.compiler
+ self.version = '1'
return
- def get_link_args(self):
- return self.linkargs
-
- def get_version(self):
- return self.version
-
def get_methods(self):
if mesonlib.is_osx() or mesonlib.is_windows():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
@@ -73,10 +69,9 @@ class GLDependency(Dependency):
return [DependencyMethods.PKGCONFIG]
-class GnuStepDependency(Dependency):
+class GnuStepDependency(ExternalDependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'gnustep', kwargs)
- self.required = kwargs.get('required', True)
+ super().__init__('gnustep', environment, 'objc', kwargs)
self.modules = kwargs.get('modules', [])
self.detect()
@@ -85,11 +80,9 @@ class GnuStepDependency(Dependency):
try:
gp = Popen_safe([self.confprog, '--help'])[0]
except (FileNotFoundError, PermissionError):
- self.args = None
mlog.log('Dependency GnuStep found:', mlog.red('NO'), '(no gnustep-config)')
return
if gp.returncode != 0:
- self.args = None
mlog.log('Dependency GnuStep found:', mlog.red('NO'))
return
if 'gui' in self.modules:
@@ -100,12 +93,13 @@ class GnuStepDependency(Dependency):
if fp.returncode != 0:
raise DependencyException('Error getting objc-args: %s %s' % (flagtxt, flagerr))
args = flagtxt.split()
- self.args = self.filter_arsg(args)
+ self.compile_args = self.filter_args(args)
fp, libtxt, liberr = Popen_safe([self.confprog, arg])
if fp.returncode != 0:
raise DependencyException('Error getting objc-lib args: %s %s' % (libtxt, liberr))
- self.libs = self.weird_filter(libtxt.split())
+ self.link_args = self.weird_filter(libtxt.split())
self.version = self.detect_version()
+ self.is_found = True
mlog.log('Dependency', mlog.bold('GnuStep'), 'found:',
mlog.green('YES'), self.version)
@@ -115,7 +109,7 @@ is sometimes mixed among the subprocess output. I have no idea
why. As a hack filter out everything that is not a flag."""
return [e for e in elems if e.startswith('-')]
- def filter_arsg(self, args):
+ def filter_args(self, args):
"""gnustep-config returns a bunch of garbage args such
as -O2 and so on. Drop everything that is not needed."""
result = []
@@ -157,25 +151,10 @@ why. As a hack filter out everything that is not a flag."""
''.format(self.confprog, var))
return o.strip()
- def found(self):
- return self.args is not None
-
- def get_version(self):
- return self.version
-
- def get_compile_args(self):
- if self.args is None:
- return []
- return self.args
-
- def get_link_args(self):
- return self.libs
-
-class QtBaseDependency(Dependency):
+class QtBaseDependency(ExternalDependency):
def __init__(self, name, env, kwargs):
- Dependency.__init__(self, name, kwargs)
- self.name = name
+ super().__init__(name, env, 'cpp', kwargs)
self.qtname = name.capitalize()
self.qtver = name[-1]
if self.qtver == "4":
@@ -184,16 +163,7 @@ class QtBaseDependency(Dependency):
self.qtpkgname = self.qtname
self.root = '/usr'
self.bindir = None
- self.silent = kwargs.get('silent', False)
- # We store the value of required here instead of passing it on to
- # PkgConfigDependency etc because we want to try the qmake-based
- # fallback as well.
- self.required = kwargs.pop('required', True)
- kwargs['required'] = False
mods = kwargs.get('modules', [])
- self.cargs = []
- self.largs = []
- self.is_found = False
if isinstance(mods, str):
mods = [mods]
if not mods:
@@ -207,16 +177,16 @@ class QtBaseDependency(Dependency):
methods = []
# Prefer pkg-config, then fallback to `qmake -query`
if DependencyMethods.PKGCONFIG in self.methods:
- self._pkgconfig_detect(mods, env, kwargs)
+ 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, env, kwargs)
+ 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.cargs = []
- self.largs = []
+ self.compile_args = []
+ self.link_args = []
from_text = '(checked {})'.format(mlog.format_list(methods))
self.version = 'none'
if self.required:
@@ -244,24 +214,27 @@ class QtBaseDependency(Dependency):
rcc = ExternalProgram('rcc-' + self.name, silent=True)
return moc, uic, rcc
- def _pkgconfig_detect(self, mods, env, kwargs):
+ def _pkgconfig_detect(self, mods, kwargs):
+ # We set the value of required to False so that we can try the
+ # qmake-based fallback if pkg-config fails.
+ kwargs['required'] = False
modules = OrderedDict()
for module in mods:
- modules[module] = PkgConfigDependency(self.qtpkgname + module, env, kwargs)
- self.is_found = True
+ modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env, kwargs)
for m in modules.values():
if not m.found():
self.is_found = False
return
- self.cargs += m.get_compile_args()
- self.largs += m.get_link_args()
- self.version = m.modversion
+ self.compile_args += m.get_compile_args()
+ self.link_args += m.get_link_args()
+ self.is_found = True
+ self.version = m.version
# Try to detect moc, uic, rcc
if 'Core' in modules:
core = modules['Core']
else:
corekwargs = {'required': 'false', 'silent': 'true'}
- core = PkgConfigDependency(self.qtpkgname + 'Core', env, corekwargs)
+ core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs)
# Used by self.compilers_detect()
self.bindir = self.get_pkgconfig_host_bins(core)
if not self.bindir:
@@ -270,16 +243,16 @@ class QtBaseDependency(Dependency):
if prefix:
self.bindir = os.path.join(prefix, 'bin')
- def _find_qmake(self, qmake, env):
+ def _find_qmake(self, qmake):
# Even when cross-compiling, if we don't get a cross-info qmake, we
# fallback to using the qmake in PATH because that's what we used to do
- if env.is_cross_build():
- qmake = env.cross_info.config['binaries'].get('qmake', qmake)
+ if self.env.is_cross_build():
+ qmake = self.env.cross_info.config['binaries'].get('qmake', qmake)
return ExternalProgram(qmake, silent=True)
- def _qmake_detect(self, mods, env, kwargs):
+ def _qmake_detect(self, mods, kwargs):
for qmake in ('qmake-' + self.name, 'qmake'):
- self.qmake = self._find_qmake(qmake, env)
+ self.qmake = self._find_qmake(qmake)
if not self.qmake.found():
continue
# Check that the qmake is for qt5
@@ -293,6 +266,7 @@ class QtBaseDependency(Dependency):
break
else:
# Didn't find qmake :(
+ self.is_found = False
return
self.version = re.search(self.qtver + '(\.\d+)+', stdo).group(0)
# Query library path, header path, and binary path
@@ -308,15 +282,15 @@ class QtBaseDependency(Dependency):
if mesonlib.is_osx():
return self._framework_detect(qvars, mods, kwargs)
incdir = qvars['QT_INSTALL_HEADERS']
- self.cargs.append('-I' + incdir)
+ self.compile_args.append('-I' + incdir)
libdir = qvars['QT_INSTALL_LIBS']
# Used by self.compilers_detect()
self.bindir = self.get_qmake_host_bins(qvars)
self.is_found = True
for module in mods:
mincdir = os.path.join(incdir, 'Qt' + module)
- self.cargs.append('-I' + mincdir)
- if for_windows(env.is_cross_build(), env):
+ self.compile_args.append('-I' + mincdir)
+ if for_windows(self.env.is_cross_build(), self.env):
libfile = os.path.join(libdir, self.qtpkgname + module + '.lib')
if not os.path.isfile(libfile):
# MinGW can link directly to .dll
@@ -329,19 +303,20 @@ class QtBaseDependency(Dependency):
if not os.path.isfile(libfile):
self.is_found = False
break
- self.largs.append(libfile)
+ self.link_args.append(libfile)
return qmake
def _framework_detect(self, qvars, modules, kwargs):
libdir = qvars['QT_INSTALL_LIBS']
for m in modules:
fname = 'Qt' + m
- fwdep = ExtraFrameworkDependency(fname, kwargs.get('required', True), libdir, kwargs)
+ fwdep = ExtraFrameworkDependency(fname, False, libdir, self.env,
+ self.language, kwargs)
self.cargs.append('-F' + libdir)
if fwdep.found():
self.is_found = True
- self.cargs += fwdep.get_compile_args()
- self.largs += fwdep.get_link_args()
+ self.compile_args += fwdep.get_compile_args()
+ self.link_args += fwdep.get_link_args()
# Used by self.compilers_detect()
self.bindir = self.get_qmake_host_bins(qvars)
@@ -353,24 +328,9 @@ class QtBaseDependency(Dependency):
else:
return qvars['QT_INSTALL_BINS']
- def get_version(self):
- return self.version
-
- def get_compile_args(self):
- return self.cargs
-
- def get_sources(self):
- return []
-
- def get_link_args(self):
- return self.largs
-
def get_methods(self):
return [DependencyMethods.PKGCONFIG, DependencyMethods.QMAKE]
- def found(self):
- return self.is_found
-
def get_exe_args(self, compiler):
# Originally this was -fPIE but nowadays the default
# for upstream and distros seems to be -reduce-relocations
@@ -408,20 +368,18 @@ class Qt5Dependency(QtBaseDependency):
# There are three different ways of depending on SDL2:
# sdl2-config, pkg-config and OSX framework
-class SDL2Dependency(Dependency):
+class SDL2Dependency(ExternalDependency):
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'sdl2', kwargs)
- self.is_found = False
- self.cargs = []
- self.linkargs = []
+ super().__init__('sdl2', environment, None, kwargs)
if DependencyMethods.PKGCONFIG in self.methods:
try:
+ kwargs['required'] = False
pcdep = PkgConfigDependency('sdl2', environment, kwargs)
if pcdep.found():
self.type_name = 'pkgconfig'
self.is_found = True
- self.cargs = pcdep.get_compile_args()
- self.linkargs = pcdep.get_link_args()
+ self.compile_args = pcdep.get_compile_args()
+ self.link_args = pcdep.get_link_args()
self.version = pcdep.get_version()
return
except Exception as e:
@@ -431,9 +389,9 @@ class SDL2Dependency(Dependency):
sdlconf = shutil.which('sdl2-config')
if sdlconf:
stdo = Popen_safe(['sdl2-config', '--cflags'])[1]
- self.cargs = stdo.strip().split()
+ self.compile_args = stdo.strip().split()
stdo = Popen_safe(['sdl2-config', '--libs'])[1]
- self.linkargs = stdo.strip().split()
+ self.link_args = stdo.strip().split()
stdo = Popen_safe(['sdl2-config', '--version'])[1]
self.version = stdo.strip()
self.is_found = True
@@ -443,27 +401,16 @@ class SDL2Dependency(Dependency):
mlog.debug('Could not find sdl2-config binary, trying next.')
if DependencyMethods.EXTRAFRAMEWORK in self.methods:
if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency('sdl2', kwargs.get('required', True), None, kwargs)
+ fwdep = ExtraFrameworkDependency('sdl2', False, None, self.env,
+ self.language, kwargs)
if fwdep.found():
self.is_found = True
- self.cargs = fwdep.get_compile_args()
- self.linkargs = fwdep.get_link_args()
+ self.compile_args = fwdep.get_compile_args()
+ self.link_args = fwdep.get_link_args()
self.version = '2' # FIXME
return
mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO'))
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.linkargs
-
- def found(self):
- return self.is_found
-
- def get_version(self):
- return self.version
-
def get_methods(self):
if mesonlib.is_osx():
return [DependencyMethods.PKGCONFIG, DependencyMethods.SDLCONFIG, DependencyMethods.EXTRAFRAMEWORK]
@@ -471,18 +418,15 @@ class SDL2Dependency(Dependency):
return [DependencyMethods.PKGCONFIG, DependencyMethods.SDLCONFIG]
-class WxDependency(Dependency):
+class WxDependency(ExternalDependency):
wx_found = None
def __init__(self, environment, kwargs):
- Dependency.__init__(self, 'wx', kwargs)
- self.is_found = False
- # FIXME: use version instead of modversion
- self.modversion = 'none'
+ super().__init__('wx', environment, None, kwargs)
+ self.version = 'none'
if WxDependency.wx_found is None:
self.check_wxconfig()
if not WxDependency.wx_found:
- # FIXME: this message could be printed after Dependncy found
mlog.log("Neither wx-config-3.0 nor wx-config found; can't detect dependency")
return
@@ -490,15 +434,14 @@ class WxDependency(Dependency):
p, out = Popen_safe([self.wxc, '--version'])[0:2]
if p.returncode != 0:
mlog.log('Dependency wxwidgets found:', mlog.red('NO'))
- self.cargs = []
- self.libs = []
else:
- self.modversion = out.strip()
+ self.version = out.strip()
+ # FIXME: Support multiple version reqs like PkgConfigDependency
version_req = kwargs.get('version', None)
if version_req is not None:
- if not version_compare(self.modversion, version_req, strict=True):
+ if not version_compare(self.version, version_req, strict=True):
mlog.log('Wxwidgets version %s does not fullfill requirement %s' %
- (self.modversion, version_req))
+ (self.version, version_req))
return
mlog.log('Dependency wxwidgets found:', mlog.green('YES'))
self.is_found = True
@@ -509,38 +452,26 @@ class WxDependency(Dependency):
# FIXME: this error should only be raised if required is true
if p.returncode != 0:
raise DependencyException('Could not generate cargs for wxwidgets.')
- self.cargs = out.split()
+ self.compile_args = out.split()
# FIXME: this error should only be raised if required is true
p, out = Popen_safe([self.wxc, '--libs'] + self.requested_modules)[0:2]
if p.returncode != 0:
raise DependencyException('Could not generate libs for wxwidgets.')
- self.libs = out.split()
+ self.link_args = out.split()
def get_requested(self, kwargs):
modules = 'modules'
if modules not in kwargs:
return []
candidates = kwargs[modules]
- if isinstance(candidates, str):
- return [candidates]
+ if not isinstance(candidates, list):
+ candidates = [candidates]
for c in candidates:
if not isinstance(c, str):
- raise DependencyException('wxwidgets module argument is not a string.')
+ raise DependencyException('wxwidgets module argument is not a string')
return candidates
- def get_modversion(self):
- return self.modversion
-
- def get_version(self):
- return self.modversion
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
def check_wxconfig(self):
for wxc in ['wx-config-3.0', 'wx-config']:
try:
@@ -555,6 +486,3 @@ class WxDependency(Dependency):
pass
WxDependency.wxconfig_found = False
mlog.log('Found wx-config:', mlog.red('NO'))
-
- def found(self):
- return self.is_found
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 621047c..afe4bf3 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -973,7 +973,8 @@ class CompilerHolder(InterpreterObject):
if required and not linkargs:
l = self.compiler.language.capitalize()
raise InterpreterException('{} library {!r} not found'.format(l, libname))
- lib = dependencies.ExternalLibrary(libname, linkargs, self.compiler.language)
+ lib = dependencies.ExternalLibrary(libname, linkargs, self.environment,
+ self.compiler.language)
return ExternalLibraryHolder(lib)
def has_argument_method(self, args, kwargs):
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index dacc478..603be18 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -312,7 +312,11 @@ def run(mainfile, args):
else:
mlog.log(mlog.red('\nMeson encountered an error:'))
mlog.log(e)
+ if os.environ.get('MESON_FORCE_BACKTRACE'):
+ raise
else:
+ if os.environ.get('MESON_FORCE_BACKTRACE'):
+ raise
traceback.print_exc()
return 1
return 0
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 6644ba7..e134acf 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -68,7 +68,7 @@ class GnomeModule(ExtensionModule):
if native_glib_version is None:
glib_dep = PkgConfigDependency('glib-2.0', state.environment,
{'native': True})
- native_glib_version = glib_dep.get_modversion()
+ native_glib_version = glib_dep.get_version()
return native_glib_version
def __print_gresources_warning(self, state):
diff --git a/run_project_tests.py b/run_project_tests.py
index 822286b..66d7eb0 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -34,7 +34,7 @@ import time
import multiprocessing
import concurrent.futures as conc
import re
-from run_unittests import get_fake_options
+from run_unittests import get_fake_options, run_configure_inprocess
from run_tests import get_backend_commands, get_backend_args_for_dir, Backend
from run_tests import ensure_backend_detects_changes
@@ -249,18 +249,6 @@ def log_text_file(logfile, testdir, stdo, stde):
executor.shutdown()
raise StopException()
-def run_configure_inprocess(commandlist):
- old_stdout = sys.stdout
- sys.stdout = mystdout = StringIO()
- old_stderr = sys.stderr
- sys.stderr = mystderr = StringIO()
- try:
- returncode = mesonmain.run(commandlist[0], commandlist[1:])
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
- return returncode, mystdout.getvalue(), mystderr.getvalue()
-
def run_test_inprocess(testdir):
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
@@ -383,7 +371,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
return TestResult(validate_install(testdir, install_dir, compiler), BuildStep.validate, stdo, stde, mesonlog, gen_time, build_time, test_time)
def gather_tests(testdir):
- tests = [t.replace('\\', '/').split('/', 2)[2] for t in glob(os.path.join(testdir, '*'))]
+ tests = [t.replace('\\', '/').split('/', 2)[2] for t in glob(testdir + '/*')]
testlist = [(int(t.split()[0]), t) for t in tests]
testlist.sort()
tests = [os.path.join(testdir, t[1]) for t in testlist]
@@ -437,7 +425,6 @@ def detect_tests_to_run():
('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()),
('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()),
- ('framework', 'frameworks', mesonlib.is_osx() or mesonlib.is_windows() or mesonlib.is_cygwin()),
('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()),
('C#', 'csharp', backend is not Backend.ninja or not shutil.which('mcs')),
('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')),
@@ -446,9 +433,17 @@ def detect_tests_to_run():
('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objc_compiler()),
('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')),
('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
- ('python3', 'python3', backend is not Backend.ninja or not shutil.which('python3')),
+ ('python3', 'python3', backend is not Backend.ninja),
]
- return [(name, gather_tests('test cases/' + subdir), skip) for name, subdir, skip in all_tests]
+ gathered_tests = [(name, gather_tests('test cases/' + subdir), skip) for name, subdir, skip in all_tests]
+ if mesonlib.is_windows():
+ # TODO: Set BOOST_ROOT in .appveyor.yml
+ gathered_tests += [('framework', ['test cases/frameworks/1 boost'], 'BOOST_ROOT' not in os.environ)]
+ elif mesonlib.is_osx() or mesonlib.is_cygwin():
+ gathered_tests += [('framework', gather_tests('test cases/frameworks'), True)]
+ else:
+ gathered_tests += [('framework', gather_tests('test cases/frameworks'), False)]
+ return gathered_tests
def run_tests(all_tests, log_name_base, extra_args):
global stop, executor, futures
diff --git a/run_tests.py b/run_tests.py
index 00c2595..1549979 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -22,7 +22,9 @@ import subprocess
import tempfile
import platform
from mesonbuild import mesonlib
+from mesonbuild import mesonmain
from mesonbuild.environment import detect_ninja
+from io import StringIO
from enum import Enum
from glob import glob
@@ -118,9 +120,23 @@ def get_fake_options(prefix):
def should_run_linux_cross_tests():
return shutil.which('arm-linux-gnueabihf-gcc-6') and not platform.machine().startswith('arm')
+def run_configure_inprocess(commandlist):
+ old_stdout = sys.stdout
+ sys.stdout = mystdout = StringIO()
+ old_stderr = sys.stderr
+ sys.stderr = mystderr = StringIO()
+ try:
+ returncode = mesonmain.run(commandlist[0], commandlist[1:])
+ finally:
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+ return returncode, mystdout.getvalue(), mystderr.getvalue()
+
class FakeEnvironment(object):
def __init__(self):
self.cross_info = None
+ self.coredata = lambda: None
+ self.coredata.compilers = {}
def is_cross_build(self):
return False
@@ -162,7 +178,7 @@ if __name__ == '__main__':
os.environ.pop('platform')
# Run tests
print('Running unittests.\n')
- units = ['InternalTests', 'AllPlatformTests']
+ units = ['InternalTests', 'AllPlatformTests', 'FailureTests']
if mesonlib.is_linux():
units += ['LinuxlikeTests']
if should_run_linux_cross_tests():
diff --git a/run_unittests.py b/run_unittests.py
index 8a9ac0a..dbfd638 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -25,16 +25,19 @@ import unittest
from configparser import ConfigParser
from glob import glob
from pathlib import PurePath
+
+import mesonbuild.mlog
import mesonbuild.compilers
import mesonbuild.environment
import mesonbuild.mesonlib
from mesonbuild.mesonlib import is_windows, is_osx, is_cygwin
from mesonbuild.environment import Environment
+from mesonbuild.dependencies import DependencyException
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
from run_tests import exe_suffix, get_fake_options, FakeEnvironment
from run_tests import get_builddir_target_args, get_backend_commands, Backend
-from run_tests import ensure_backend_detects_changes
+from run_tests import ensure_backend_detects_changes, run_configure_inprocess
def get_dynamic_section_entry(fname, entry):
@@ -401,8 +404,8 @@ class BasePlatformTests(unittest.TestCase):
# Get the backend
# FIXME: Extract this from argv?
self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja'))
- self.meson_command = [sys.executable, os.path.join(src_root, 'meson.py'),
- '--backend=' + self.backend.name]
+ self.meson_args = [os.path.join(src_root, 'meson.py'), '--backend=' + self.backend.name]
+ self.meson_command = [sys.executable] + self.meson_args
self.mconf_command = [sys.executable, os.path.join(src_root, 'mesonconf.py')]
self.mintro_command = [sys.executable, os.path.join(src_root, 'mesonintrospect.py')]
self.mtest_command = [sys.executable, os.path.join(src_root, 'mesontest.py'), '-C', self.builddir]
@@ -452,7 +455,7 @@ class BasePlatformTests(unittest.TestCase):
raise subprocess.CalledProcessError(p.returncode, command)
return output
- def init(self, srcdir, extra_args=None, default_args=True):
+ def init(self, srcdir, extra_args=None, default_args=True, inprocess=False):
self.assertTrue(os.path.exists(srcdir))
if extra_args is None:
extra_args = []
@@ -462,14 +465,27 @@ class BasePlatformTests(unittest.TestCase):
if default_args:
args += ['--prefix', self.prefix,
'--libdir', self.libdir]
- try:
- self._run(self.meson_command + args + extra_args)
- except unittest.SkipTest:
- raise unittest.SkipTest('Project requested skipping: ' + srcdir)
- except:
- self._print_meson_log()
- raise
self.privatedir = os.path.join(self.builddir, 'meson-private')
+ if inprocess:
+ try:
+ out = run_configure_inprocess(self.meson_args + args + extra_args)[1]
+ except:
+ self._print_meson_log()
+ raise
+ finally:
+ # Close log file to satisfy Windows file locking
+ mesonbuild.mlog.shutdown()
+ mesonbuild.mlog.log_dir = None
+ mesonbuild.mlog.log_file = None
+ else:
+ try:
+ out = self._run(self.meson_command + args + extra_args)
+ except unittest.SkipTest:
+ raise unittest.SkipTest('Project requested skipping: ' + srcdir)
+ except:
+ self._print_meson_log()
+ raise
+ return out
def build(self, target=None, extra_args=None):
if extra_args is None:
@@ -1196,6 +1212,124 @@ int main(int argc, char **argv) {
self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path))
+class FailureTests(BasePlatformTests):
+ '''
+ Tests that test failure conditions. Build files here should be dynamically
+ generated and static tests should go into `test cases/failing*`.
+ This is useful because there can be many ways in which a particular
+ function can fail, and creating failing tests for all of them is tedious
+ and slows down testing.
+ '''
+ dnf = "[Dd]ependency.*not found"
+
+ def setUp(self):
+ super().setUp()
+ self.srcdir = os.path.realpath(tempfile.mkdtemp())
+ self.mbuild = os.path.join(self.srcdir, 'meson.build')
+
+ def tearDown(self):
+ super().tearDown()
+ shutil.rmtree(self.srcdir)
+
+ def assertMesonRaises(self, contents, match, extra_args=None, langs=None):
+ '''
+ Assert that running meson configure on the specified @contents raises
+ a error message matching regex @match.
+ '''
+ if langs is None:
+ langs = []
+ with open(self.mbuild, 'w') as f:
+ f.write("project('failure test', 'c', 'cpp')\n")
+ for lang in langs:
+ f.write("add_languages('{}', required : false)\n".format(lang))
+ f.write(contents)
+ # Force tracebacks so we can detect them properly
+ os.environ['MESON_FORCE_BACKTRACE'] = '1'
+ with self.assertRaisesRegex(DependencyException, match, msg=contents):
+ # Must run in-process or we'll get a generic CalledProcessError
+ self.init(self.srcdir, extra_args=extra_args, inprocess=True)
+
+ def assertMesonOutputs(self, contents, match, extra_args=None, langs=None):
+ '''
+ Assert that running meson configure on the specified @contents outputs
+ something that matches regex @match.
+ '''
+ if langs is None:
+ langs = []
+ with open(self.mbuild, 'w') as f:
+ f.write("project('output test', 'c', 'cpp')\n")
+ for lang in langs:
+ f.write("add_languages('{}', required : false)\n".format(lang))
+ f.write(contents)
+ # Run in-process for speed and consistency with assertMesonRaises
+ out = self.init(self.srcdir, extra_args=extra_args, inprocess=True)
+ self.assertRegex(out, match)
+
+ def test_dependency(self):
+ if not shutil.which('pkg-config'):
+ raise unittest.SkipTest('pkg-config not found')
+ a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"),
+ ("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"),
+ ("dependency('zlib', version : 1)", "[Vv]ersion.*string or list"),
+ ("dependency('zlib', required : 1)", "[Rr]equired.*boolean"),
+ ("dependency('zlib', method : 1)", "[Mm]ethod.*string"),
+ ("dependency('zlibfail')", self.dnf),)
+ for contents, match in a:
+ self.assertMesonRaises(contents, match)
+
+ def test_apple_frameworks_dependency(self):
+ if not is_osx():
+ raise unittest.SkipTest('only run on macOS')
+ self.assertMesonRaises("dependency('appleframeworks')",
+ "requires at least one module")
+
+ def test_sdl2_notfound_dependency(self):
+ # Want to test failure, so skip if available
+ if shutil.which('sdl2-config'):
+ raise unittest.SkipTest('sdl2-config found')
+ self.assertMesonRaises("dependency('sdl2', method : 'sdlconfig')", self.dnf)
+ self.assertMesonRaises("dependency('sdl2', method : 'pkg-config')", self.dnf)
+
+ def test_gnustep_notfound_dependency(self):
+ # Want to test failure, so skip if available
+ if shutil.which('gnustep-config'):
+ raise unittest.SkipTest('gnustep-config found')
+ self.assertMesonRaises("dependency('gnustep')",
+ "(requires a Objc compiler|{})".format(self.dnf),
+ langs = ['objc'])
+
+ def test_wx_notfound_dependency(self):
+ # Want to test failure, so skip if available
+ if shutil.which('wx-config-3.0') or shutil.which('wx-config'):
+ raise unittest.SkipTest('wx-config or wx-config-3.0 found')
+ self.assertMesonRaises("dependency('wxwidgets')", self.dnf)
+ self.assertMesonOutputs("dependency('wxwidgets', required : false)",
+ "nor wx-config found")
+
+ def test_wx_dependency(self):
+ if not shutil.which('wx-config-3.0') and not shutil.which('wx-config'):
+ raise unittest.SkipTest('Neither wx-config nor wx-config-3.0 found')
+ self.assertMesonRaises("dependency('wxwidgets', modules : 1)",
+ "module argument is not a string")
+
+ def test_llvm_dependency(self):
+ self.assertMesonRaises("dependency('llvm', modules : 'fail')",
+ "(required.*fail|{})".format(self.dnf))
+
+ def test_boost_notfound_dependency(self):
+ # Can be run even if Boost is found or not
+ self.assertMesonRaises("dependency('boost', modules : 1)",
+ "module.*not a string")
+ self.assertMesonRaises("dependency('boost', modules : 'fail')",
+ "(fail.*not found|{})".format(self.dnf))
+
+ def test_boost_BOOST_ROOT_dependency(self):
+ # Test BOOST_ROOT; can be run even if Boost is found or not
+ os.environ['BOOST_ROOT'] = 'relative/path'
+ self.assertMesonRaises("dependency('boost')",
+ "(BOOST_ROOT.*absolute|{})".format(self.dnf))
+
+
class WindowsTests(BasePlatformTests):
'''
Tests that should run on Cygwin, MinGW, and MSVC
diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build
index 582ff37..af7f8c6 100644
--- a/test cases/frameworks/15 llvm/meson.build
+++ b/test cases/frameworks/15 llvm/meson.build
@@ -7,4 +7,11 @@ llvm_dep = dependency(
required : true,
)
+d = dependency('llvm', modules : 'not-found', required : false)
+assert(d.found() == false, 'not-found llvm module found')
+
+# XXX: Version checks are broken, see FIXME in LLVMDependency
+#d = dependency('llvm', version : '<0.1', required : false)
+#assert(d.found() == false, 'ancient llvm module found')
+
executable('sum', 'sum.c', dependencies : llvm_dep)
diff --git a/test cases/frameworks/16 sdl2/meson.build b/test cases/frameworks/16 sdl2/meson.build
new file mode 100644
index 0000000..c79bd46
--- /dev/null
+++ b/test cases/frameworks/16 sdl2/meson.build
@@ -0,0 +1,10 @@
+project('sdl2 test', 'c')
+
+sdl2_dep = dependency('sdl2', version : '>=2.0.0')
+
+e = executable('sdl2prog', 'sdl2prog.c', dependencies : sdl2_dep)
+
+test('sdl2test', e)
+
+# Ensure that we can find it with sdl2-config too
+configdep = dependency('sdl2', method : 'sdlconfig')
diff --git a/test cases/frameworks/16 sdl2/sdl2prog.c b/test cases/frameworks/16 sdl2/sdl2prog.c
new file mode 100644
index 0000000..b67aab4
--- /dev/null
+++ b/test cases/frameworks/16 sdl2/sdl2prog.c
@@ -0,0 +1,33 @@
+/* vim: set sts=4 sw=4 et : */
+
+#include <stdio.h>
+#include <SDL_version.h>
+
+int main(int argc, char *argv[]) {
+ SDL_version compiled;
+ SDL_version linked;
+
+ SDL_VERSION(&compiled);
+ SDL_GetVersion(&linked);
+
+ if (compiled.major != linked.major) {
+ fprintf(stderr, "Compiled major '%u' != linked major '%u'",
+ compiled.major, linked.major);
+ return -1;
+ }
+
+ if (compiled.minor != linked.minor) {
+ fprintf(stderr, "Compiled minor '%u' != linked minor '%u'",
+ compiled.minor, linked.minor);
+ return -2;
+ }
+#if 0
+ /* Disabled because sometimes this is 'micro' and sometimes 'patch' */
+ if (compiled.micro != linked.micro) {
+ fprintf(stderr, "Compiled micro '%u' != linked micro '%u'",
+ compiled.micro, linked.micro);
+ return -3;
+ }
+#endif
+ return 0;
+}
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
index 468b9c9..d9cab6f 100644
--- a/test cases/frameworks/4 qt/meson.build
+++ b/test cases/frameworks/4 qt/meson.build
@@ -8,16 +8,22 @@ foreach qt : ['qt4', 'qt5']
if qt == 'qt5'
qt_modules += qt5_modules
endif
+
# Test that invalid modules are indeed not found
fakeqtdep = dependency(qt, modules : ['DefinitelyNotFound'], required : false, method : get_option('method'))
if fakeqtdep.found()
error('Invalid qt dep incorrectly found!')
endif
+
# Test that partially-invalid modules are indeed not found
fakeqtdep = dependency(qt, modules : ['Core', 'DefinitelyNotFound'], required : false, method : get_option('method'))
if fakeqtdep.found()
error('Invalid qt dep incorrectly found!')
endif
+
+ # Ensure that the "no-Core-module-specified" code branch is hit
+ nocoredep = dependency(qt, modules : ['Gui'], required : qt == 'qt5', method : get_option('method'))
+
# If qt4 modules are found, test that. qt5 is required.
qtdep = dependency(qt, modules : qt_modules, required : qt == 'qt5', method : get_option('method'))
if qtdep.found()
diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build
index 5c2c262..ad513f2 100644
--- a/test cases/linuxlike/5 dependency versions/meson.build
+++ b/test cases/linuxlike/5 dependency versions/meson.build
@@ -90,9 +90,15 @@ if meson.is_cross_build()
assert(native_prefix != cross_prefix, 'native prefix == cross_prefix == ' + native_prefix)
endif
+objc_found = add_languages('objc', required : false)
+
foreach d : ['sdl2', 'gnustep', 'wx', 'gl', 'python3', 'boost', 'gtest', 'gmock']
- dep = dependency(d, required : false)
- if dep.found()
- dep.version()
+ if d == 'gnustep' and not objc_found
+ message('Skipping gnustep because no ObjC compiler found')
+ else
+ dep = dependency(d, required : false)
+ if dep.found()
+ dep.version()
+ endif
endif
endforeach
diff --git a/test cases/osx/4 framework/meson.build b/test cases/osx/4 framework/meson.build
index 8d93bf9..460b480 100644
--- a/test cases/osx/4 framework/meson.build
+++ b/test cases/osx/4 framework/meson.build
@@ -10,8 +10,13 @@
project('xcode framework test', 'c', default_options : ['libdir=libtest'])
-dep_libs = [dependency('appleframeworks', modules : ['OpenGL'], required : true)]
-dep_main = [dependency('appleframeworks', modules : ['Foundation'], required : true)]
+dep_libs = dependency('appleframeworks', modules : ['OpenGL'], required : false)
+if not dep_libs.found()
+ error('OpenGL framework not found')
+endif
+assert(dep_libs.type_name() == 'appleframeworks', 'type_name is wrong')
+
+dep_main = dependency('appleframeworks', modules : ['Foundation'])
stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs)
exe = executable('prog', 'prog.c', install : true, dependencies: dep_main)