aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml2
-rw-r--r--docs/markdown/Gnome-module.md4
-rw-r--r--docs/markdown/Release-notes-for-0.41.0.md10
-rw-r--r--docs/markdown/Release-notes-for-0.42.0.md13
-rw-r--r--docs/sitemap.txt1
-rw-r--r--man/meson.12
-rw-r--r--man/mesonconf.12
-rw-r--r--man/mesonintrospect.12
-rw-r--r--man/mesontest.12
-rw-r--r--man/wraptool.12
-rw-r--r--mesonbuild/backend/backends.py11
-rw-r--r--mesonbuild/backend/ninjabackend.py43
-rw-r--r--mesonbuild/backend/vs2010backend.py38
-rw-r--r--mesonbuild/backend/vs2017backend.py4
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/compilers.py86
-rw-r--r--mesonbuild/coredata.py2
-rw-r--r--mesonbuild/dependencies/__init__.py5
-rw-r--r--mesonbuild/dependencies/base.py188
-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.py226
-rw-r--r--mesonbuild/interpreter.py13
-rw-r--r--mesonbuild/mesonmain.py4
-rw-r--r--mesonbuild/mintro.py2
-rw-r--r--mesonbuild/modules/gnome.py67
-rw-r--r--mesonbuild/scripts/dist.py36
-rw-r--r--mesonbuild/scripts/yelphelper.py15
-rwxr-xr-xrun_project_tests.py63
-rwxr-xr-xrun_tests.py25
-rwxr-xr-xrun_unittests.py254
-rw-r--r--test cases/common/127 cpp and asm/retval-arm.S7
-rw-r--r--test cases/common/127 cpp and asm/retval-x86.S7
-rw-r--r--test cases/common/127 cpp and asm/retval-x86_64.S7
-rw-r--r--test cases/common/141 c cpp and asm/retval-arm.S7
-rw-r--r--test cases/common/141 c cpp and asm/retval-x86.S8
-rw-r--r--test cases/common/141 c cpp and asm/retval-x86_64.S7
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml1
-rw-r--r--test cases/frameworks/10 gtk-doc/include/foo-version.h.in29
-rw-r--r--test cases/frameworks/10 gtk-doc/include/meson.build10
-rw-r--r--test cases/frameworks/10 gtk-doc/meson.build4
-rw-r--r--test cases/frameworks/13 yelp/help/meson.build8
-rw-r--r--test cases/frameworks/13 yelp/installed_files.txt7
-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/frameworks/9 wxwidgets/meson.build1
-rw-r--r--test cases/linuxlike/5 dependency versions/meson.build14
-rw-r--r--test cases/osx/4 framework/meson.build9
-rw-r--r--test cases/unit/10 d dedup/meson.build6
-rw-r--r--test cases/unit/10 d dedup/prog.c14
-rw-r--r--test cases/unit/9 -L -l order/first.pc13
-rw-r--r--test cases/unit/9 -L -l order/meson.build6
-rw-r--r--test cases/unit/9 -L -l order/prog.c5
-rw-r--r--test cases/unit/9 -L -l order/second.pc13
-rw-r--r--test cases/vala/16 mixed dependence/meson.build6
-rw-r--r--test cases/vala/7 shared library/lib/meson.build10
-rw-r--r--test cases/windows/1 basic/prog.c2
60 files changed, 994 insertions, 594 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/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index 61b88ad..e709fd5 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -127,9 +127,11 @@ This also creates two targets for translations `help-$project-update-po` and `he
* `sources`: list of pages
* `media`: list of media such as images
-* `symlink_media`: if media should be symlinked (requires newish yelp) defaults to `false`
+* `symlink_media`: if media should be symlinked not copied (defaults to `true` since 0.42.0)
* `languages`: list of languages for translations
+Note that very old versions of yelp may not support symlinked media; At least 3.10 should work.
+
*Added 0.36.0*
### gnome.gtkdoc()
diff --git a/docs/markdown/Release-notes-for-0.41.0.md b/docs/markdown/Release-notes-for-0.41.0.md
index 6e46828..1ddde95 100644
--- a/docs/markdown/Release-notes-for-0.41.0.md
+++ b/docs/markdown/Release-notes-for-0.41.0.md
@@ -1,21 +1,17 @@
---
title: Release 0.41
-short-description: Release notes for 0.41 (preliminary)
+short-description: Release notes for 0.41
...
-**Preliminary, 0.41.0 has not been released yet.**
-
# New features
-Add features here as code is merged to master.
-
## Dependency Handler for LLVM
Native support for linking against LLVM using the `dependency` function.
## vcs_tag keyword fallback is is now optional
-The `fallback` keyword in `vcs_tag` is now optional. If not given, its value
+The `fallback` keyword in `vcs_tag()` is now optional. If not given, its value
defaults to the return value of `meson.project_version()`.
## Better quoting of special characters in ninja command invocations
@@ -60,7 +56,7 @@ Targets for building rust now take a `rust_args` keyword.
Code coverage can be generated for tests by passing the `--cov` argument to
the `run_tests.py` test runner. Note, since multiple processes are used,
-coverage must be combined before producing a report (`coverage3 combine`.)
+coverage must be combined before producing a report (`coverage3 combine`).
## Reproducible builds
diff --git a/docs/markdown/Release-notes-for-0.42.0.md b/docs/markdown/Release-notes-for-0.42.0.md
new file mode 100644
index 0000000..dcb86c3
--- /dev/null
+++ b/docs/markdown/Release-notes-for-0.42.0.md
@@ -0,0 +1,13 @@
+---
+title: Release 0.42
+short-description: Release notes for 0.42 (preliminary)
+...
+
+**Preliminary, 0.42.0 has not been released yet.**
+
+# New features
+
+## Distribution tarballs from Mercurial repositories
+
+Creating distribution tarballs can now be made out of projects based on
+Mercurial. As before, this remains possible only with the Ninja backend.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 7246749..9831b93 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -58,6 +58,7 @@ index.md
Shipping-prebuilt-binaries-as-wraps.md
fallback-wraptool.md
Release-notes.md
+ Release-notes-for-0.42.0.md
Release-notes-for-0.41.0.md
Release-notes-for-0.40.0.md
Release-notes-for-0.39.0.md
diff --git a/man/meson.1 b/man/meson.1
index 185e097..1cd60b6 100644
--- a/man/meson.1
+++ b/man/meson.1
@@ -1,4 +1,4 @@
-.TH MESON "1" "April 2017" "meson 0.40.1" "User Commands"
+.TH MESON "1" "June 2017" "meson 0.41.1" "User Commands"
.SH NAME
meson - a high productivity build system
.SH DESCRIPTION
diff --git a/man/mesonconf.1 b/man/mesonconf.1
index 388d46b..6bb9d39 100644
--- a/man/mesonconf.1
+++ b/man/mesonconf.1
@@ -1,4 +1,4 @@
-.TH MESONCONF "1" "April 2017" "mesonconf 0.40.1" "User Commands"
+.TH MESONCONF "1" "June 2017" "mesonconf 0.41.1" "User Commands"
.SH NAME
mesonconf - a tool to configure Meson builds
.SH DESCRIPTION
diff --git a/man/mesonintrospect.1 b/man/mesonintrospect.1
index 4c64d6e..1918b4f 100644
--- a/man/mesonintrospect.1
+++ b/man/mesonintrospect.1
@@ -1,4 +1,4 @@
-.TH MESONCONF "1" "April 2017" "mesonintrospect 0.40.1" "User Commands"
+.TH MESONCONF "1" "June 2017" "mesonintrospect 0.41.1" "User Commands"
.SH NAME
mesonintrospect - a tool to extract information about a Meson build
.SH DESCRIPTION
diff --git a/man/mesontest.1 b/man/mesontest.1
index 5731a9e..cf21fe7 100644
--- a/man/mesontest.1
+++ b/man/mesontest.1
@@ -1,4 +1,4 @@
-.TH MESON "1" "April 2017" "meson 0.40.1" "User Commands"
+.TH MESON "1" "June 2017" "meson 0.41.1" "User Commands"
.SH NAME
mesontest - test tool for the Meson build system
.SH DESCRIPTION
diff --git a/man/wraptool.1 b/man/wraptool.1
index 84cb03c..73c2568 100644
--- a/man/wraptool.1
+++ b/man/wraptool.1
@@ -1,4 +1,4 @@
-.TH WRAPTOOL "1" "April 2017" "meson 0.40.1" "User Commands"
+.TH WRAPTOOL "1" "June 2017" "meson 0.41.1" "User Commands"
.SH NAME
wraptool - source dependency downloader
.SH DESCRIPTION
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 3044ce6..1dd128b 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -294,6 +294,15 @@ class Backend:
raise MesonException(m.format(target.name))
return l
+ def determine_rpath_dirs(self, target):
+ link_deps = target.get_all_link_deps()
+ result = []
+ for ld in link_deps:
+ prospective = self.get_target_dir(ld)
+ if prospective not in result:
+ result.append(prospective)
+ return result
+
def object_filename_from_source(self, target, source, is_unity):
if isinstance(source, mesonlib.File):
source = source.fname
@@ -429,7 +438,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/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 3638621..761d508 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -510,12 +510,12 @@ int dummy;
cmd_type = 'meson_exe.py custom'
else:
cmd_type = 'custom'
-
if target.depfile is not None:
rel_dfile = os.path.join(self.get_target_dir(target), target.depfile)
abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target))
os.makedirs(abs_pdir, exist_ok=True)
elem.add_item('DEPFILE', rel_dfile)
+ cmd = self.replace_paths(target, cmd)
elem.add_item('COMMAND', cmd)
elem.add_item('description', desc.format(target.name, cmd_type))
elem.write(outfile)
@@ -564,7 +564,9 @@ int dummy;
else:
cmd.append(target.command)
cmd += arg_strings
+
elem.add_dep(deps)
+ cmd = self.replace_paths(target, cmd)
elem.add_item('COMMAND', cmd)
elem.add_item('description', 'Running external command %s.' % target.name)
elem.add_item('pool', 'console')
@@ -1098,7 +1100,13 @@ int dummy;
args += ['--library=' + target.name]
# Outputted header
hname = os.path.join(self.get_target_dir(target), target.vala_header)
- args += ['-H', hname, '--use-header']
+ args += ['-H', hname]
+ if self.is_unity(target):
+ # Without this the declarations will get duplicated in the .c
+ # files and cause a build failure when all of them are
+ # #include-d in one .c file.
+ # https://github.com/mesonbuild/meson/issues/1969
+ args += ['--use-header']
valac_outputs.append(hname)
# Outputted vapi file
vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi)
@@ -1683,6 +1691,16 @@ rule FORTRAN_DEP_HACK
continue
self.generate_genlist_for_target(genlist, target, outfile)
+ def replace_paths(self, target, args):
+ source_target_dir = self.get_target_source_dir(target)
+ relout = self.get_target_private_dir(target)
+ args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
+ for x in args]
+ args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args]
+ args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.')
+ for x in args]
+ return args
+
def generate_genlist_for_target(self, genlist, target, outfile):
generator = genlist.get_generator()
exe = generator.get_exe()
@@ -1716,11 +1734,7 @@ rule FORTRAN_DEP_HACK
if sole_output == '':
outfilelist = outfilelist[len(generator.outputs):]
relout = self.get_target_private_dir(target)
- args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
- for x in args]
- args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args]
- args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.')
- for x in args]
+ args = self.replace_paths(target, args)
cmdlist = exe_arr + self.replace_extra_args(args, genlist)
elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename)
if generator.depfile is not None:
@@ -2328,11 +2342,13 @@ rule FORTRAN_DEP_HACK
commands += target.link_args
# External deps must be last because target link libraries may depend on them.
for dep in target.get_external_deps():
- commands += dep.get_link_args()
+ # Extend without reordering or de-dup to preserve `-L -l` sets
+ # https://github.com/mesonbuild/meson/issues/1718
+ commands.extend_direct(dep.get_link_args())
for d in target.get_dependencies():
if isinstance(d, build.StaticLibrary):
for dep in d.get_external_deps():
- commands += dep.get_link_args()
+ commands.extend_direct(dep.get_link_args())
# Add link args for c_* or cpp_* build options. Currently this only
# adds c_winlibs and cpp_winlibs when building for Windows. This needs
# to be after all internal and external libraries so that unresolved
@@ -2368,15 +2384,6 @@ rule FORTRAN_DEP_HACK
elem.add_item('LINK_ARGS', commands)
return elem
- def determine_rpath_dirs(self, target):
- link_deps = target.get_all_link_deps()
- result = []
- for ld in link_deps:
- prospective = self.get_target_dir(ld)
- if prospective not in result:
- result.append(prospective)
- return result
-
def get_dependency_filename(self, t):
if isinstance(t, build.SharedLibrary):
return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols')
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index fafde8f..57b0437 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):
"""
@@ -910,11 +908,13 @@ class Vs2010Backend(backends.Backend):
extra_link_args += target.link_args
# External deps must be last because target link libraries may depend on them.
for dep in target.get_external_deps():
- extra_link_args += dep.get_link_args()
+ # Extend without reordering or de-dup to preserve `-L -l` sets
+ # https://github.com/mesonbuild/meson/issues/1718
+ extra_link_args.extend_direct(dep.get_link_args())
for d in target.get_dependencies():
if isinstance(d, build.StaticLibrary):
for dep in d.get_external_deps():
- extra_link_args += dep.get_link_args()
+ extra_link_args.extend_direct(dep.get_link_args())
# Add link args for c_* or cpp_* build options. Currently this only
# adds c_winlibs and cpp_winlibs when building for Windows. This needs
# to be after all internal and external libraries so that unresolved
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 7ce6fa6..c73ba3a 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -807,7 +807,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 833071e..979a5ac 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -430,6 +430,17 @@ class CompilerArgs(list):
to recursively search for symbols in the libraries. This is not needed
with other linkers.
'''
+
+ # A standalone argument must never be deduplicated because it is
+ # defined by what comes _after_ it. Thus dedupping this:
+ # -D FOO -D BAR
+ # would yield either
+ # -D FOO BAR
+ # or
+ # FOO -D BAR
+ # both of which are invalid.
+ if arg in cls.dedup2_prefixes:
+ return 0
if arg in cls.dedup2_args or \
arg.startswith(cls.dedup2_prefixes) or \
arg.endswith(cls.dedup2_suffixes):
@@ -465,6 +476,19 @@ class CompilerArgs(list):
self.insert(i + 1, '-Wl,--end-group')
return self.compiler.unix_args_to_native(self)
+ def append_direct(self, arg):
+ '''
+ Append the specified argument without any reordering or de-dup
+ '''
+ super().append(arg)
+
+ def extend_direct(self, iterable):
+ '''
+ Extend using the elements in the specified iterable without any
+ reordering or de-dup
+ '''
+ super().extend(iterable)
+
def __add__(self, args):
new = CompilerArgs(self, self.compiler)
new += args
@@ -731,35 +755,35 @@ class Compiler:
raise EnvironmentException('Language %s does not support linking whole archives.' % self.language)
def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
- if not rpath_paths and not install_rpath:
- return []
- # The rpaths we write must be relative, because otherwise
- # they have different length depending on the build
- # directory. This breaks reproducible builds.
- rel_rpaths = []
- for p in rpath_paths:
- if p == from_dir:
- relative = '' # relpath errors out in this case
- else:
- relative = os.path.relpath(p, from_dir)
- rel_rpaths.append(relative)
- paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths])
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
- args = ['-Wl,-rpath,' + paths]
- if get_compiler_is_linuxlike(self):
- # Rpaths to use while linking must be absolute. These are not
- # written to the binary. Needed only with GNU ld:
- # https://sourceware.org/bugzilla/show_bug.cgi?id=16936
- # Not needed on Windows or other platforms that don't use RPATH
- # https://github.com/mesonbuild/meson/issues/1897
- lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
- args += ['-Wl,-rpath-link,' + lpaths]
- return args
+ if not rpath_paths and not install_rpath:
+ return []
+ # The rpaths we write must be relative, because otherwise
+ # they have different length depending on the build
+ # directory. This breaks reproducible builds.
+ rel_rpaths = []
+ for p in rpath_paths:
+ if p == from_dir:
+ relative = '' # relpath errors out in this case
+ else:
+ relative = os.path.relpath(p, from_dir)
+ rel_rpaths.append(relative)
+ paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths])
+ if len(paths) < len(install_rpath):
+ padding = 'X' * (len(install_rpath) - len(paths))
+ if not paths:
+ paths = padding
+ else:
+ paths = paths + ':' + padding
+ args = ['-Wl,-rpath,' + paths]
+ if get_compiler_is_linuxlike(self):
+ # Rpaths to use while linking must be absolute. These are not
+ # written to the binary. Needed only with GNU ld:
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=16936
+ # Not needed on Windows or other platforms that don't use RPATH
+ # https://github.com/mesonbuild/meson/issues/1897
+ lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
+ args += ['-Wl,-rpath-link,' + lpaths]
+ return args
class CCompiler(Compiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
@@ -1029,7 +1053,7 @@ class CCompiler(Compiler):
def _links_wrapper(self, code, env, extra_args, dependencies):
"Shares common code between self.links and self.run"
args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link')
- return self.compile(code, args.to_native())
+ return self.compile(code, args)
def links(self, code, env, extra_args=None, dependencies=None):
with self._links_wrapper(code, env, extra_args, dependencies) as p:
@@ -1773,7 +1797,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/coredata.py b/mesonbuild/coredata.py
index 7bc20f8..80ad94f 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -19,7 +19,7 @@ from .mesonlib import MesonException, commonpath
from .mesonlib import default_libdir, default_libexecdir, default_prefix
import ast
-version = '0.41.0.dev1'
+version = '0.42.0.dev1'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode']
class UserOption:
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..fdb5ab8 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,40 @@ 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).
+ '''
+ # Using a vala library in a non-vala target, or a non-vala library in a vala target
+ # XXX: This should be extended to other non-C linkers such as Rust
+ if (self.language == 'vala' and language != 'vala') or \
+ (language == 'vala' and self.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 +563,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 +578,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 +602,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 +610,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 +633,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..f991d3c 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, 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..7cc8bb4 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)
- self.cargs.append('-F' + libdir)
+ fwdep = ExtraFrameworkDependency(fname, False, libdir, self.env,
+ self.language, kwargs)
+ self.compile_args.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,17 @@ 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()
+ else:
+ self.wxc = WxDependency.wx_found
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 +436,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 +454,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:
@@ -549,12 +482,9 @@ class WxDependency(Dependency):
mlog.log('Found wx-config:', mlog.bold(shutil.which(wxc)),
'(%s)' % out.strip())
self.wxc = wxc
- WxDependency.wx_found = True
+ WxDependency.wx_found = wxc
return
except (FileNotFoundError, PermissionError):
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..7f279c1 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):
@@ -1010,10 +1011,9 @@ class CompilerHolder(InterpreterObject):
return []
ModuleState = namedtuple('ModuleState', [
- 'build_to_src', 'subdir', 'environment', 'project_name',
- 'project_version', 'compilers', 'targets', 'data', 'headers',
- 'man', 'global_args', 'project_args', 'build_machine',
- 'host_machine', 'target_machine'])
+ 'build_to_src', 'subdir', 'environment', 'project_name', 'project_version',
+ 'backend', 'compilers', 'targets', 'data', 'headers', 'man', 'global_args',
+ 'project_args', 'build_machine', 'host_machine', 'target_machine'])
class ModuleHolder(InterpreterObject):
def __init__(self, modname, module, interpreter):
@@ -1039,6 +1039,9 @@ class ModuleHolder(InterpreterObject):
environment=self.interpreter.environment,
project_name=self.interpreter.build.project_name,
project_version=self.interpreter.build.dep_manifest[self.interpreter.active_projectname],
+ # The backend object is under-used right now, but we will need it:
+ # https://github.com/mesonbuild/meson/issues/1419
+ backend=self.interpreter.backend,
compilers=self.interpreter.build.compilers,
targets=self.interpreter.build.targets,
data=self.interpreter.build.data,
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/mintro.py b/mesonbuild/mintro.py
index 525a41d..5e672bb 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -158,7 +158,7 @@ def list_buildsystem_files(coredata, builddata):
def list_deps(coredata):
result = []
- for d in coredata.deps:
+ for d in coredata.deps.values():
if d.found():
args = {'compile_args': d.get_compile_args(),
'link_args': d.get_link_args()}
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 6644ba7..fe85aa0 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):
@@ -288,15 +288,25 @@ class GnomeModule(ExtensionModule):
def _get_link_args(self, state, lib, depends=None, include_rpath=False,
use_gir_args=False):
+ # Construct link args
if gir_has_extra_lib_arg() and use_gir_args:
- link_command = ['--extra-library=%s' % lib.name]
+ link_command = ['--extra-library=' + lib.name]
else:
- link_command = ['-l%s' % lib.name]
+ link_command = ['-l' + lib.name]
if isinstance(lib, build.SharedLibrary):
- libdir = os.path.join(state.environment.get_build_dir(), lib.subdir)
- link_command += ['-L%s' % libdir]
+ libdir = os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(lib))
+ link_command.append('-L' + libdir)
+ # Needed for the following binutils bug:
+ # https://github.com/mesonbuild/meson/issues/1911
+ # However, g-ir-scanner does not understand -Wl,-rpath
+ # so we need to use -L instead
+ for d in state.backend.determine_rpath_dirs(lib):
+ d = os.path.join(state.environment.get_build_dir(), d)
+ link_command.append('-L' + d)
+ if include_rpath:
+ link_command.append('-Wl,-rpath,' + d)
if include_rpath:
- link_command += ['-Wl,-rpath %s' % libdir]
+ link_command.append('-Wl,-rpath,' + libdir)
if depends:
depends.append(lib)
return link_command
@@ -359,7 +369,8 @@ class GnomeModule(ExtensionModule):
gi_includes.update([girdir])
elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
for incd in dep.get_include_dirs():
- cflags.update(incd.get_incdirs())
+ for idir in incd.get_incdirs():
+ cflags.update(["-I%s" % idir])
else:
mlog.log('dependency %s not handled to build gir files' % dep)
continue
@@ -435,19 +446,21 @@ class GnomeModule(ExtensionModule):
'Gir includes must be str, GirTarget, or list of them')
cflags = []
- if state.global_args.get('c'):
- cflags += state.global_args['c']
- if state.project_args.get('c'):
- cflags += state.project_args['c']
- if 'c' in state.compilers:
- compiler = state.compilers['c']
+ for lang, compiler in girtarget.compilers.items():
+ # XXX: Can you use g-i with any other language?
+ if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'):
+ break
+ else:
+ lang = None
+ compiler = None
+ if lang and compiler:
+ if state.global_args.get(lang):
+ cflags += state.global_args[lang]
+ if state.project_args.get(lang):
+ cflags += state.project_args[lang]
sanitize = compiler.get_options().get('b_sanitize')
if sanitize:
cflags += compilers.sanitizer_compile_args(sanitize)
- if cflags:
- scan_command += ['--cflags-begin']
- scan_command += cflags
- scan_command += ['--cflags-end']
if kwargs.get('symbol_prefix'):
sym_prefix = kwargs.pop('symbol_prefix')
if not isinstance(sym_prefix, str):
@@ -510,9 +523,12 @@ class GnomeModule(ExtensionModule):
# ldflags will be misinterpreted by gir scanner (showing
# spurious dependencies) but building GStreamer fails if they
# are not used here.
- cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends,
- use_gir_args=True)
- scan_command += list(cflags)
+ dep_cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends,
+ use_gir_args=True)
+ cflags += list(dep_cflags)
+ scan_command += ['--cflags-begin']
+ scan_command += cflags
+ scan_command += ['--cflags-end']
# need to put our output directory first as we need to use the
# generated libraries instead of any possibly installed system/prefix
# ones.
@@ -536,6 +552,13 @@ class GnomeModule(ExtensionModule):
scan_command += ['--program', girtarget]
elif isinstance(girtarget, build.SharedLibrary):
libname = girtarget.get_basename()
+ # Needed for the following binutils bug:
+ # https://github.com/mesonbuild/meson/issues/1911
+ # However, g-ir-scanner does not understand -Wl,-rpath
+ # so we need to use -L instead
+ for d in state.backend.determine_rpath_dirs(girtarget):
+ d = os.path.join(state.environment.get_build_dir(), d)
+ scan_command.append('-L' + d)
scan_command += ['--library', libname]
scankwargs = {'output': girfile,
'input': libsources,
@@ -598,7 +621,7 @@ class GnomeModule(ExtensionModule):
langs = mesonlib.stringlistify(kwargs.pop('languages', []))
media = mesonlib.stringlistify(kwargs.pop('media', []))
- symlinks = kwargs.pop('symlink_media', False)
+ symlinks = kwargs.pop('symlink_media', True)
if not isinstance(symlinks, bool):
raise MesonException('symlink_media must be a boolean')
@@ -679,6 +702,8 @@ class GnomeModule(ExtensionModule):
for inc_dir in src_dir.get_incdirs():
header_dirs.append(os.path.join(state.environment.get_source_dir(),
src_dir.get_curdir(), inc_dir))
+ header_dirs.append(os.path.join(state.environment.get_build_dir(),
+ src_dir.get_curdir(), inc_dir))
else:
header_dirs.append(src_dir)
diff --git a/mesonbuild/scripts/dist.py b/mesonbuild/scripts/dist.py
index 325a882..cb3bbe2 100644
--- a/mesonbuild/scripts/dist.py
+++ b/mesonbuild/scripts/dist.py
@@ -13,6 +13,7 @@
# limitations under the License.
+import lzma
import os
import shutil
import subprocess
@@ -29,10 +30,11 @@ def create_hash(fname):
m = hashlib.sha256()
m.update(open(fname, 'rb').read())
with open(hashname, 'w') as f:
- f.write('%s %s\n' % (m.hexdigest(), os.path.split(fname)[-1]))
+ f.write('%s %s\n' % (m.hexdigest(), os.path.basename(fname)))
+
def create_zip(zipfilename, packaging_dir):
- prefix = os.path.split(packaging_dir)[0]
+ prefix = os.path.dirname(packaging_dir)
removelen = len(prefix) + 1
with zipfile.ZipFile(zipfilename,
'w',
@@ -70,7 +72,8 @@ def process_submodules(dirname):
continue
del_gitfiles(os.path.join(dirname, v))
-def create_dist(dist_name, src_root, bld_root, dist_sub):
+
+def create_dist_git(dist_name, src_root, bld_root, dist_sub):
distdir = os.path.join(dist_sub, dist_name)
if os.path.exists(distdir):
shutil.rmtree(distdir)
@@ -81,13 +84,29 @@ def create_dist(dist_name, src_root, bld_root, dist_sub):
xzname = distdir + '.tar.xz'
# Should use shutil but it got xz support only in 3.5.
with tarfile.open(xzname, 'w:xz') as tf:
- tf.add(distdir, os.path.split(distdir)[1])
+ tf.add(distdir, dist_name)
# Create only .tar.xz for now.
# zipname = distdir + '.zip'
# create_zip(zipname, distdir)
shutil.rmtree(distdir)
return (xzname, )
+
+def create_dist_hg(dist_name, src_root, bld_root, dist_sub):
+ os.makedirs(dist_sub, exist_ok=True)
+
+ tarname = os.path.join(dist_sub, dist_name + '.tar')
+ xzname = tarname + '.xz'
+ subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar', tarname])
+ with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
+ shutil.copyfileobj(tf, xf)
+ os.unlink(tarname)
+ # Create only .tar.xz for now.
+ # zipname = os.path.join(dist_sub, dist_name + '.zip')
+ # subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname])
+ return (xzname, )
+
+
def check_dist(packagename, meson_command):
print('Testing distribution package %s.' % packagename)
unpackdir = tempfile.mkdtemp()
@@ -132,10 +151,13 @@ def run(args):
dist_name = build.project_name + '-' + build.project_version
- if not os.path.isdir(os.path.join(src_root, '.git')):
- print('Dist currently only works with Git repos.')
+ if os.path.isdir(os.path.join(src_root, '.git')):
+ names = create_dist_git(dist_name, src_root, bld_root, dist_sub)
+ elif os.path.isdir(os.path.join(src_root, '.hg')):
+ names = create_dist_hg(dist_name, src_root, bld_root, dist_sub)
+ else:
+ print('Dist currently only works with Git or Mercurial repos.')
return 1
- names = create_dist(dist_name, src_root, bld_root, dist_sub)
if names is None:
return 1
error_count = 0
diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py
index 47dfb71..978a870 100644
--- a/mesonbuild/scripts/yelphelper.py
+++ b/mesonbuild/scripts/yelphelper.py
@@ -74,13 +74,24 @@ def install_help(srcdir, blddir, sources, media, langs, install_dir, destdir, pr
if not os.path.exists(infile):
if lang == 'C':
mlog.warning('Media file "%s" did not exist in C directory' % m)
+ continue
elif symlinks:
srcfile = os.path.join(c_install_dir, m)
mlog.log('Symlinking %s to %s.' % (outfile, srcfile))
if '/' in m or '\\' in m:
os.makedirs(os.path.dirname(outfile), exist_ok=True)
- os.symlink(srcfile, outfile)
- continue
+ try:
+ try:
+ os.symlink(srcfile, outfile)
+ except FileExistsError:
+ os.remove(outfile)
+ os.symlink(srcfile, outfile)
+ continue
+ except (NotImplementedError, OSError):
+ mlog.warning('Symlinking not supported, falling back to copying')
+ else:
+ # Lang doesn't have media file so copy it over 'C' one
+ infile = os.path.join(srcdir, 'C', m)
mlog.log('Installing %s to %s' % (infile, outfile))
if '/' in m or '\\' in m:
os.makedirs(os.path.dirname(outfile), exist_ok=True)
diff --git a/run_project_tests.py b/run_project_tests.py
index 822286b..76216a4 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
@@ -214,7 +214,8 @@ def validate_install(srcdir, installdir, compiler):
expected[platform_fix_name(line.strip())] = False
# Check if expected files were found
for fname in expected:
- if os.path.exists(os.path.join(installdir, fname)):
+ file_path = os.path.join(installdir, fname)
+ if os.path.exists(file_path) or os.path.islink(file_path):
expected[fname] = True
for (fname, found) in expected.items():
if not found:
@@ -249,17 +250,22 @@ 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 bold(text):
+ return mlog.bold(text).get_text(mlog.colorize_console)
+
+
+def green(text):
+ return mlog.green(text).get_text(mlog.colorize_console)
+
+
+def red(text):
+ return mlog.red(text).get_text(mlog.colorize_console)
+
+
+def yellow(text):
+ return mlog.yellow(text).get_text(mlog.colorize_console)
+
def run_test_inprocess(testdir):
old_stdout = sys.stdout
@@ -383,7 +389,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 +443,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 +451,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
@@ -479,10 +492,12 @@ def run_tests(all_tests, log_name_base, extra_args):
for name, test_cases, skipped in all_tests:
current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))})
+ print()
if skipped:
- print('\nNot running %s tests.\n' % name)
+ print(bold('Not running %s tests.' % name))
else:
- print('\nRunning %s tests.\n' % name)
+ print(bold('Running %s tests.' % name))
+ print()
futures = []
for t in test_cases:
# Jenkins screws us over by automatically sorting test cases by name
@@ -498,7 +513,7 @@ def run_tests(all_tests, log_name_base, extra_args):
sys.stdout.flush()
result = result.result()
if result is None or 'MESON_SKIP_TEST' in result.stdo:
- print('Skipping:', t)
+ print(yellow('Skipping:'), t)
current_test = ET.SubElement(current_suite, 'testcase', {'name': testname,
'classname': name})
ET.SubElement(current_test, 'skipped', {})
@@ -506,7 +521,7 @@ def run_tests(all_tests, log_name_base, extra_args):
else:
without_install = "" if len(install_commands) > 0 else " (without install)"
if result.msg != '':
- print('Failed test{} during {}: {!r}'.format(without_install, result.step.name, t))
+ print(red('Failed test{} during {}: {!r}'.format(without_install, result.step.name, t)))
print('Reason:', result.msg)
failing_tests += 1
if result.step == BuildStep.configure and result.mlog != no_meson_log_msg:
@@ -652,9 +667,9 @@ if __name__ == '__main__':
pass
for f in pbfiles:
os.unlink(f)
- print('\nTotal passed tests:', passing_tests)
- print('Total failed tests:', failing_tests)
- print('Total skipped tests:', skipped_tests)
+ print('\nTotal passed tests:', green(str(passing_tests)))
+ print('Total failed tests:', red(str(failing_tests)))
+ print('Total skipped tests:', yellow(str(skipped_tests)))
if failing_tests > 0:
print('\nMesonlogs of failing tests\n')
for l in failing_logs:
diff --git a/run_tests.py b/run_tests.py
index 00c2595..040f958 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -22,7 +22,10 @@ import subprocess
import tempfile
import platform
from mesonbuild import mesonlib
+from mesonbuild import mesonmain
+from mesonbuild import mlog
from mesonbuild.environment import detect_ninja
+from io import StringIO
from enum import Enum
from glob import glob
@@ -118,9 +121,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
@@ -161,8 +178,9 @@ if __name__ == '__main__':
if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86':
os.environ.pop('platform')
# Run tests
- print('Running unittests.\n')
- units = ['InternalTests', 'AllPlatformTests']
+ print(mlog.bold('Running unittests.').get_text(mlog.colorize_console))
+ print()
+ units = ['InternalTests', 'AllPlatformTests', 'FailureTests']
if mesonlib.is_linux():
units += ['LinuxlikeTests']
if should_run_linux_cross_tests():
@@ -184,7 +202,8 @@ if __name__ == '__main__':
returncode += subprocess.call([sys.executable, 'run_unittests.py', '-v'] + units, env=env)
# Ubuntu packages do not have a binary without -6 suffix.
if should_run_linux_cross_tests():
- print('Running cross compilation tests.\n')
+ print(mlog.bold('Running cross compilation tests.').get_text(mlog.colorize_console))
+ print()
returncode += subprocess.call([sys.executable, 'run_cross_test.py', 'cross/ubuntu-armhf.txt'], env=env)
returncode += subprocess.call([sys.executable, 'run_project_tests.py'] + sys.argv[1:], env=env)
sys.exit(returncode)
diff --git a/run_unittests.py b/run_unittests.py
index 8a9ac0a..63462d8 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.mesonlib import is_windows, is_osx, is_cygwin, windows_proof_rmtree
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):
@@ -173,6 +176,16 @@ class InternalTests(unittest.TestCase):
l += ['-lbar']
self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar'])
+ ## Test that 'direct' append and extend works
+ l = cargsfunc(c, ['-Lfoodir', '-lfoo'])
+ self.assertEqual(l, ['-Lfoodir', '-lfoo'])
+ # Direct-adding a library and a libpath appends both correctly
+ l.extend_direct(['-Lbardir', '-lbar'])
+ self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar'])
+ # Direct-adding the same library again still adds it
+ l.append_direct('-lbar')
+ self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar'])
+
def test_commonpath(self):
from os.path import sep
commonpath = mesonbuild.mesonlib.commonpath
@@ -401,8 +414,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]
@@ -432,7 +445,7 @@ class BasePlatformTests(unittest.TestCase):
print(f.read())
def tearDown(self):
- shutil.rmtree(self.builddir)
+ windows_proof_rmtree(self.builddir)
os.environ = self.orig_env
super().tearDown()
@@ -452,7 +465,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 +475,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:
@@ -508,7 +534,7 @@ class BasePlatformTests(unittest.TestCase):
self._run(self.mconf_command + [arg, self.builddir])
def wipe(self):
- shutil.rmtree(self.builddir)
+ windows_proof_rmtree(self.builddir)
def utime(self, f):
ensure_backend_detects_changes(self.backend)
@@ -1135,18 +1161,50 @@ class AllPlatformTests(BasePlatformTests):
self.build()
self.run_tests()
- def test_dist(self):
+ def test_dist_git(self):
if not shutil.which('git'):
raise unittest.SkipTest('Git not found')
+
+ def git_init(project_dir):
+ subprocess.check_call(['git', 'init'], cwd=project_dir)
+ subprocess.check_call(['git', 'config',
+ 'user.name', 'Author Person'], cwd=project_dir)
+ subprocess.check_call(['git', 'config',
+ 'user.email', 'teh_coderz@example.com'], cwd=project_dir)
+ subprocess.check_call(['git', 'add', 'meson.build', 'distexe.c'], cwd=project_dir)
+ subprocess.check_call(['git', 'commit', '-a', '-m', 'I am a project'], cwd=project_dir)
+
try:
- self.dist_impl()
+ self.dist_impl(git_init)
except PermissionError:
# When run under Windows CI, something (virus scanner?)
# holds on to the git files so cleaning up the dir
# fails sometimes.
pass
- def dist_impl(self):
+ def test_dist_hg(self):
+ if not shutil.which('hg'):
+ raise unittest.SkipTest('Mercurial not found')
+ if self.backend is not Backend.ninja:
+ raise unittest.SkipTest('Dist is only supported with Ninja')
+
+ def hg_init(project_dir):
+ subprocess.check_call(['hg', 'init'], cwd=project_dir)
+ with open(os.path.join(project_dir, '.hg', 'hgrc'), 'w') as f:
+ print('[ui]', file=f)
+ print('username=Author Person <teh_coderz@example.com>', file=f)
+ subprocess.check_call(['hg', 'add', 'meson.build', 'distexe.c'], cwd=project_dir)
+ subprocess.check_call(['hg', 'commit', '-m', 'I am a project'], cwd=project_dir)
+
+ try:
+ self.dist_impl(hg_init)
+ except PermissionError:
+ # When run under Windows CI, something (virus scanner?)
+ # holds on to the hg files so cleaning up the dir
+ # fails sometimes.
+ pass
+
+ def dist_impl(self, vcs_init):
# Create this on the fly because having rogue .git directories inside
# the source tree leads to all kinds of trouble.
with tempfile.TemporaryDirectory() as project_dir:
@@ -1163,13 +1221,7 @@ int main(int argc, char **argv) {
return 0;
}
''')
- subprocess.check_call(['git', 'init'], cwd=project_dir)
- subprocess.check_call(['git', 'config',
- 'user.name', 'Author Person'], cwd=project_dir)
- subprocess.check_call(['git', 'config',
- 'user.email', 'teh_coderz@example.com'], cwd=project_dir)
- subprocess.check_call(['git', 'add', 'meson.build', 'distexe.c'], cwd=project_dir)
- subprocess.check_call(['git', 'commit', '-a', '-m', 'I am a project'], cwd=project_dir)
+ vcs_init(project_dir)
self.init(project_dir)
self.build('dist')
distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
@@ -1195,6 +1247,133 @@ int main(int argc, char **argv) {
for path in rpath.split(':'):
self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path))
+ def test_dash_d_dedup(self):
+ testdir = os.path.join(self.unit_test_dir, '10 d dedup')
+ self.init(testdir)
+ cmd = self.get_compdb()[0]['command']
+ self.assertTrue('-D FOO -D BAR' in cmd or
+ '"-D" "FOO" "-D" "BAR"' in cmd or
+ '/D FOO /D BAR' in cmd or
+ '"/D" "FOO" "/D" "BAR"' in cmd)
+
+
+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()
+ windows_proof_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):
'''
@@ -1611,6 +1790,31 @@ class LinuxlikeTests(BasePlatformTests):
env['LD_LIBRARY_PATH'] = installed_libdir
self.assertEqual(subprocess.call(installed_exe, env=env), 0)
+ def test_order_of_l_arguments(self):
+ testdir = os.path.join(self.unit_test_dir, '9 -L -l order')
+ os.environ['PKG_CONFIG_PATH'] = testdir
+ self.init(testdir)
+ # NOTE: .pc file has -Lfoo -lfoo -Lbar -lbar but pkg-config reorders
+ # the flags before returning them to -Lfoo -Lbar -lfoo -lbar
+ # but pkgconf seems to not do that. Sigh. Support both.
+ expected_order = [('-L/me/first', '-lfoo1'),
+ ('-L/me/second', '-lfoo2'),
+ ('-L/me/first', '-L/me/second'),
+ ('-lfoo1', '-lfoo2'),
+ ('-L/me/second', '-L/me/third'),
+ ('-L/me/third', '-L/me/fourth',),
+ ('-L/me/third', '-lfoo3'),
+ ('-L/me/fourth', '-lfoo4'),
+ ('-lfoo3', '-lfoo4'),
+ ]
+ with open(os.path.join(self.builddir, 'build.ninja')) as ifile:
+ for line in ifile:
+ if expected_order[0][0] in line:
+ for first, second in expected_order:
+ self.assertLess(line.index(first), line.index(second))
+ return
+ raise RuntimeError('Linker entries not found in the Ninja file.')
+
class LinuxArmCrossCompileTests(BasePlatformTests):
'''
Tests that verify cross-compilation to Linux/ARM
@@ -1644,7 +1848,7 @@ class RewriterTests(unittest.TestCase):
self.test_dir = os.path.join(src_root, 'test cases/rewrite')
def tearDown(self):
- shutil.rmtree(self.tmpdir)
+ windows_proof_rmtree(self.tmpdir)
def read_contents(self, fname):
with open(os.path.join(self.workdir, fname)) as f:
diff --git a/test cases/common/127 cpp and asm/retval-arm.S b/test cases/common/127 cpp and asm/retval-arm.S
index 8b37197..a892362 100644
--- a/test cases/common/127 cpp and asm/retval-arm.S
+++ b/test cases/common/127 cpp and asm/retval-arm.S
@@ -2,7 +2,10 @@
.text
.globl SYMBOL_NAME(get_retval)
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- mov r0, #0
- mov pc, lr
+ mov r0, #0
+ mov pc, lr
diff --git a/test cases/common/127 cpp and asm/retval-x86.S b/test cases/common/127 cpp and asm/retval-x86.S
index 06bd75c..f9e8190 100644
--- a/test cases/common/127 cpp and asm/retval-x86.S
+++ b/test cases/common/127 cpp and asm/retval-x86.S
@@ -2,7 +2,10 @@
.text
.globl SYMBOL_NAME(get_retval)
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- xorl %eax, %eax
- retl
+ xorl %eax, %eax
+ retl
diff --git a/test cases/common/127 cpp and asm/retval-x86_64.S b/test cases/common/127 cpp and asm/retval-x86_64.S
index 638921e..1a5f3eb 100644
--- a/test cases/common/127 cpp and asm/retval-x86_64.S
+++ b/test cases/common/127 cpp and asm/retval-x86_64.S
@@ -2,7 +2,10 @@
.text
.globl SYMBOL_NAME(get_retval)
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- xorl %eax, %eax
- retq
+ xorl %eax, %eax
+ retq
diff --git a/test cases/common/141 c cpp and asm/retval-arm.S b/test cases/common/141 c cpp and asm/retval-arm.S
index 8b37197..a892362 100644
--- a/test cases/common/141 c cpp and asm/retval-arm.S
+++ b/test cases/common/141 c cpp and asm/retval-arm.S
@@ -2,7 +2,10 @@
.text
.globl SYMBOL_NAME(get_retval)
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- mov r0, #0
- mov pc, lr
+ mov r0, #0
+ mov pc, lr
diff --git a/test cases/common/141 c cpp and asm/retval-x86.S b/test cases/common/141 c cpp and asm/retval-x86.S
index 06bd75c..3cb0237 100644
--- a/test cases/common/141 c cpp and asm/retval-x86.S
+++ b/test cases/common/141 c cpp and asm/retval-x86.S
@@ -2,7 +2,11 @@
.text
.globl SYMBOL_NAME(get_retval)
+/* Only supported on Linux with GAS */
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- xorl %eax, %eax
- retl
+ xorl %eax, %eax
+ retl
diff --git a/test cases/common/141 c cpp and asm/retval-x86_64.S b/test cases/common/141 c cpp and asm/retval-x86_64.S
index 638921e..1a5f3eb 100644
--- a/test cases/common/141 c cpp and asm/retval-x86_64.S
+++ b/test cases/common/141 c cpp and asm/retval-x86_64.S
@@ -2,7 +2,10 @@
.text
.globl SYMBOL_NAME(get_retval)
+# ifdef __linux__
+.type get_retval, %function
+#endif
SYMBOL_NAME(get_retval):
- xorl %eax, %eax
- retq
+ xorl %eax, %eax
+ retq
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
index d23b22f..028b808 100644
--- a/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml
@@ -34,6 +34,7 @@
</para>
</partintro>
<xi:include href="xml/foo.xml"/>
+ <xi:include href="xml/foo-version.xml"/>
</reference>
</book>
diff --git a/test cases/frameworks/10 gtk-doc/include/foo-version.h.in b/test cases/frameworks/10 gtk-doc/include/foo-version.h.in
new file mode 100644
index 0000000..30751cd
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/include/foo-version.h.in
@@ -0,0 +1,29 @@
+#pragma once
+
+/**
+ * SECTION:version
+ * @section_id: foo-version
+ * @short_description: <filename>foo-version.h</filename>
+ * @title: Foo Versioning
+ */
+
+/**
+ * FOO_MAJOR_VERSION:
+ *
+ * The major version of foo.
+ */
+#define FOO_MAJOR_VERSION (@FOO_MAJOR_VERSION@)
+
+/**
+ * FOO_MINOR_VERSION:
+ *
+ * The minor version of foo.
+ */
+#define FOO_MINOR_VERSION (@FOO_MINOR_VERSION@)
+
+/**
+ * FOO_MICRO_VERSION:
+ *
+ * The micro version of foo.
+ */
+#define FOO_MICRO_VERSION (@FOO_MICRO_VERSION@)
diff --git a/test cases/frameworks/10 gtk-doc/include/meson.build b/test cases/frameworks/10 gtk-doc/include/meson.build
new file mode 100644
index 0000000..4c85b80
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/include/meson.build
@@ -0,0 +1,10 @@
+cdata = configuration_data()
+parts = meson.project_version().split('.')
+cdata.set('FOO_MAJOR_VERSION', parts[0])
+cdata.set('FOO_MINOR_VERSION', parts[1])
+cdata.set('FOO_MICRO_VERSION', parts[2])
+configure_file(input : 'foo-version.h.in',
+ output : 'foo-version.h',
+ configuration : cdata,
+ install : true,
+ install_dir : get_option('includedir'))
diff --git a/test cases/frameworks/10 gtk-doc/meson.build b/test cases/frameworks/10 gtk-doc/meson.build
index 95eeefa..4cfcca1 100644
--- a/test cases/frameworks/10 gtk-doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/meson.build
@@ -1,4 +1,4 @@
-project('gtkdoctest', 'c')
+project('gtkdoctest', 'c', version : '1.0.0')
gnome = import('gnome')
@@ -6,6 +6,8 @@ assert(gnome.gtkdoc_html_dir('foobar') == 'share/gtkdoc/html/foobar', 'Gtkdoc in
inc = include_directories('include')
+subdir('include')
+
# We have to disable this test until this bug fix has landed to
# distros https://bugzilla.gnome.org/show_bug.cgi?id=753145
error('MESON_SKIP_TEST can not enable gtk-doc test until upstream fixes have landed.')
diff --git a/test cases/frameworks/13 yelp/help/meson.build b/test cases/frameworks/13 yelp/help/meson.build
index 7c6f01d..85bc980 100644
--- a/test cases/frameworks/13 yelp/help/meson.build
+++ b/test cases/frameworks/13 yelp/help/meson.build
@@ -3,5 +3,13 @@ gnome = import('gnome')
gnome.yelp('meson',
sources: 'index.page',
media: 'media/test.txt',
+ symlink_media: false,
+ languages: ['de', 'es'],
+)
+
+gnome.yelp('meson-symlink',
+ sources: 'index.page',
+ media: 'media/test.txt',
+ symlink_media: true,
languages: ['de', 'es'],
)
diff --git a/test cases/frameworks/13 yelp/installed_files.txt b/test cases/frameworks/13 yelp/installed_files.txt
index 59d2158..9fc097d 100644
--- a/test cases/frameworks/13 yelp/installed_files.txt
+++ b/test cases/frameworks/13 yelp/installed_files.txt
@@ -3,3 +3,10 @@ usr/share/help/C/meson/media/test.txt
usr/share/help/es/meson/index.page
usr/share/help/es/meson/media/test.txt
usr/share/help/de/meson/index.page
+usr/share/help/de/meson/media/test.txt
+usr/share/help/C/meson-symlink/index.page
+usr/share/help/C/meson-symlink/media/test.txt
+usr/share/help/es/meson-symlink/media/test.txt
+usr/share/help/es/meson-symlink/index.page
+usr/share/help/de/meson-symlink/index.page
+usr/share/help/de/meson-symlink/media/test.txt
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/frameworks/9 wxwidgets/meson.build b/test cases/frameworks/9 wxwidgets/meson.build
index c1fa367..da3aa26 100644
--- a/test cases/frameworks/9 wxwidgets/meson.build
+++ b/test cases/frameworks/9 wxwidgets/meson.build
@@ -1,5 +1,6 @@
project('wxwidgets test', 'cpp')
+wxd = dependency('wxwidgets', version : '>=5', required : false)
wxd = dependency('wxwidgets', version : '>=3.0.0', required : false)
if wxd.found()
diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build
index 5c2c262..d4140b7 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
-foreach d : ['sdl2', 'gnustep', 'wx', 'gl', 'python3', 'boost', 'gtest', 'gmock']
- dep = dependency(d, required : false)
- if dep.found()
- dep.version()
+objc_found = add_languages('objc', required : false)
+
+foreach d : ['sdl2', 'gnustep', 'wxwidgets', 'gl', 'python3', 'boost', 'gtest', 'gmock', 'valgrind']
+ 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)
diff --git a/test cases/unit/10 d dedup/meson.build b/test cases/unit/10 d dedup/meson.build
new file mode 100644
index 0000000..08f3a6c
--- /dev/null
+++ b/test cases/unit/10 d dedup/meson.build
@@ -0,0 +1,6 @@
+project('d dedup', 'c')
+
+add_project_arguments('-D', 'FOO', '-D', 'BAR', language : 'c')
+
+executable('prog', 'prog.c')
+
diff --git a/test cases/unit/10 d dedup/prog.c b/test cases/unit/10 d dedup/prog.c
new file mode 100644
index 0000000..505f122
--- /dev/null
+++ b/test cases/unit/10 d dedup/prog.c
@@ -0,0 +1,14 @@
+#include<stdio.h>
+
+#ifndef FOO
+#error FOO is not defined.
+#endif
+
+#ifndef BAR
+#error BAR is not defined.
+#endif
+
+int main(int argc, char **argv) {
+ printf("All is well.\n");
+ return 0;
+}
diff --git a/test cases/unit/9 -L -l order/first.pc b/test cases/unit/9 -L -l order/first.pc
new file mode 100644
index 0000000..3b811b2
--- /dev/null
+++ b/test cases/unit/9 -L -l order/first.pc
@@ -0,0 +1,13 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib/x86_64-linux-gnu
+sharedlibdir=${libdir}
+includedir=${prefix}/include
+
+Name: jonne
+Description: jonne library
+Version: 1.0.0
+
+Requires:
+Libs: -L/me/first -lfoo1 -L/me/second -lfoo2
+Cflags: -I${includedir}
diff --git a/test cases/unit/9 -L -l order/meson.build b/test cases/unit/9 -L -l order/meson.build
new file mode 100644
index 0000000..cfcf033
--- /dev/null
+++ b/test cases/unit/9 -L -l order/meson.build
@@ -0,0 +1,6 @@
+project('jonne', 'c')
+
+firstdep = dependency('first')
+seconddep = dependency('second')
+
+executable('lprog', 'prog.c', dependencies : [firstdep, seconddep])
diff --git a/test cases/unit/9 -L -l order/prog.c b/test cases/unit/9 -L -l order/prog.c
new file mode 100644
index 0000000..3a16ac3
--- /dev/null
+++ b/test cases/unit/9 -L -l order/prog.c
@@ -0,0 +1,5 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/test cases/unit/9 -L -l order/second.pc b/test cases/unit/9 -L -l order/second.pc
new file mode 100644
index 0000000..196824b
--- /dev/null
+++ b/test cases/unit/9 -L -l order/second.pc
@@ -0,0 +1,13 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib/x86_64-linux-gnu
+sharedlibdir=${libdir}
+includedir=${prefix}/include
+
+Name: jonne2
+Description: jonne2 library
+Version: 1.0.0
+
+Requires:
+Libs: -L/me/third -lfoo3 -L/me/fourth -lfoo4
+Cflags: -I${includedir}
diff --git a/test cases/vala/16 mixed dependence/meson.build b/test cases/vala/16 mixed dependence/meson.build
index e6967be..b44b47b 100644
--- a/test cases/vala/16 mixed dependence/meson.build
+++ b/test cases/vala/16 mixed dependence/meson.build
@@ -1,6 +1,10 @@
project('mixed dependence', 'vala', 'c')
-deps = [dependency('glib-2.0'), dependency('gobject-2.0')]
+cc = meson.get_compiler('c')
+
+deps = [dependency('glib-2.0'), dependency('gobject-2.0'),
+ # Should be ignored, see https://github.com/mesonbuild/meson/issues/1939
+ cc.find_library('z')]
mixer = static_library('mixer', 'mixer.vala', 'mixer-glue.c',
dependencies : deps)
diff --git a/test cases/vala/7 shared library/lib/meson.build b/test cases/vala/7 shared library/lib/meson.build
index 78646a8..edeeb96 100644
--- a/test cases/vala/7 shared library/lib/meson.build
+++ b/test cases/vala/7 shared library/lib/meson.build
@@ -1,4 +1,12 @@
-l = shared_library('valalib', 'mylib.vala', dependencies : valadeps)
+args = []
+# https://github.com/mesonbuild/meson/issues/1969
+if get_option('unity') == 'on'
+ vala_args = ['-H', 'mylib.h']
+endif
+
+l = shared_library('valalib', 'mylib.vala',
+ vala_args : args,
+ dependencies : valadeps)
shared_library('installed_vala_lib', 'mylib.vala',
dependencies : valadeps,
diff --git a/test cases/windows/1 basic/prog.c b/test cases/windows/1 basic/prog.c
index 8703980..58162a4 100644
--- a/test cases/windows/1 basic/prog.c
+++ b/test cases/windows/1 basic/prog.c
@@ -1,4 +1,4 @@
-#include <Windows.h>
+#include <windows.h>
int main(int argc, char **argv) {
return 0;