aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ci/install-dmd.ps12
-rw-r--r--ciimage/Dockerfile1
-rw-r--r--data/macros.meson1
-rw-r--r--docs/markdown/Dependencies.md21
-rw-r--r--docs/markdown/snippets/gpgme-config.md3
-rw-r--r--docs/markdown/snippets/sanity-check.md17
-rw-r--r--mesonbuild/ast/interpreter.py24
-rw-r--r--mesonbuild/ast/introspection.py6
-rw-r--r--mesonbuild/backend/backends.py1
-rw-r--r--mesonbuild/compilers/c.py51
-rw-r--r--mesonbuild/compilers/d.py10
-rw-r--r--mesonbuild/compilers/fortran.py48
-rw-r--r--mesonbuild/compilers/objc.py10
-rw-r--r--mesonbuild/compilers/objcpp.py13
-rw-r--r--mesonbuild/compilers/swift.py16
-rw-r--r--mesonbuild/compilers/vala.py21
-rw-r--r--mesonbuild/coredata.py262
-rw-r--r--mesonbuild/dependencies/__init__.py4
-rw-r--r--mesonbuild/dependencies/base.py24
-rw-r--r--mesonbuild/dependencies/misc.py78
-rw-r--r--mesonbuild/environment.py3
-rw-r--r--mesonbuild/interpreter.py5
-rw-r--r--mesonbuild/modules/python.py19
-rw-r--r--mesonbuild/msetup.py8
-rw-r--r--mesonbuild/mtest.py19
-rw-r--r--mesonbuild/optinterpreter.py9
-rw-r--r--mesonbuild/scripts/symbolextractor.py9
-rw-r--r--mesonbuild/scripts/vcstagger.py8
-rwxr-xr-xrun_cross_test.py2
-rwxr-xr-xrun_project_tests.py4
-rwxr-xr-xrun_unittests.py33
-rw-r--r--test cases/common/177 initial c_args/meson.build2
-rw-r--r--test cases/common/177 initial c_args/test_args.txt2
-rw-r--r--test cases/failing/85 gtest dependency with version/meson.build2
-rwxr-xr-xtest cases/frameworks/17 mpi/is_broken_ubuntu.py9
-rw-r--r--test cases/frameworks/17 mpi/main.f9051
-rw-r--r--test cases/frameworks/17 mpi/meson.build22
-rw-r--r--test cases/frameworks/27 gpgme/gpgme_prog.c8
-rw-r--r--test cases/frameworks/27 gpgme/meson.build21
-rw-r--r--test cases/python/1 basic/meson.build2
-rw-r--r--test cases/unit/55 introspection/meson.build8
-rw-r--r--test cases/unit/55 introspection/meson_options.txt2
-rw-r--r--test cases/unit/55 pkg_config_path option/extra_path/totally_made_up_dep.pc7
-rw-r--r--test cases/unit/55 pkg_config_path option/meson.build3
44 files changed, 602 insertions, 269 deletions
diff --git a/ci/install-dmd.ps1 b/ci/install-dmd.ps1
index aeacdf2..fd13317 100644
--- a/ci/install-dmd.ps1
+++ b/ci/install-dmd.ps1
@@ -9,8 +9,8 @@ $ProgressPreference = "SilentlyContinue"
$dmd_install = "C:\D"
$dmd_version_file = "C:\cache\DMD_LATEST"
-#echo "Fetching latest DMD version..."
if (!$Version) {
+ #echo "Fetching latest DMD version..."
$dmd_latest_url = "http://downloads.dlang.org/releases/LATEST"
$retries = 10
for ($i = 1; $i -le $retries; $i++) {
diff --git a/ciimage/Dockerfile b/ciimage/Dockerfile
index 980ed53..d5f4816 100644
--- a/ciimage/Dockerfile
+++ b/ciimage/Dockerfile
@@ -20,6 +20,7 @@ RUN sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" \
&& apt-get -y install --no-install-recommends wine-stable \
&& apt-get -y install llvm-dev libclang-dev \
&& apt-get -y install libgcrypt11-dev \
+&& apt-get -y install libgpgme-dev \
&& apt-get -y install libhdf5-dev \
&& dub fetch urld && dub build urld --compiler=gdc \
&& dub fetch dubtestproject \
diff --git a/data/macros.meson b/data/macros.meson
index 73a31ab..05d21e5 100644
--- a/data/macros.meson
+++ b/data/macros.meson
@@ -21,7 +21,6 @@
--sharedstatedir=%{_sharedstatedir} \
--wrap-mode=%{__meson_wrap_mode} \
--auto-features=%{__meson_auto_features} \
- -Db_ndebug=true \
%{_vpath_srcdir} %{_vpath_builddir} \
%{nil}}
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index 47fce8b..2789ee0 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -200,7 +200,7 @@ wmf_dep = dependency('libwmf', method : 'config-tool')
## Dependencies using config tools
[CUPS](#cups), [LLVM](#llvm), [pcap](#pcap), [WxWidgets](#wxwidgets),
-[libwmf](#libwmf), [GCrypt](#libgcrypt), and GnuStep either do not provide pkg-config
+[libwmf](#libwmf), [GCrypt](#libgcrypt), [GPGME](#gpgme), and GnuStep either do not provide pkg-config
modules or additionally can be detected via a config tool
(cups-config, llvm-config, libgcrypt-config, etc). Meson has native support for these
tools, and they can be found like other dependencies:
@@ -210,6 +210,7 @@ pcap_dep = dependency('pcap', version : '>=1.0')
cups_dep = dependency('cups', version : '>=1.4')
llvm_dep = dependency('llvm', version : '>=4.0')
libgcrypt_dep = dependency('libgcrypt', version: '>= 1.8')
+gpgme_dep = dependency('gpgme', version: '>= 1.0')
```
## AppleFrameworks
@@ -389,6 +390,12 @@ The `language` keyword may used.
`method` may be `auto`, `config-tool` or `pkg-config`.
+## GPGME
+
+*(added 0.51.0)*
+
+`method` may be `auto` or `config-tool`.
+
## Python3
Python3 is handled specially by meson:
@@ -483,6 +490,18 @@ Meson substitutes `modules` to `wx-config` invocation, it generates
- `compile_args` using `wx-config --cxxflags $modules...`
- `link_args` using `wx-config --libs $modules...`
+## Shaderc
+
+*(added 0.51.0)*
+
+Shaderc currently does not ship with any means of detection. Nevertheless, Meson
+can try to detect it using `pkg-config`, but will default to looking for the
+appropriate library manually. If the `static` keyword argument is `true`,
+`shaderc_combined` is preferred. Otherwise, `shaderc_shared` is preferred. Note
+that it is not possible to obtain the shaderc version using this method.
+
+`method` may be `auto`, `pkg-config` or `system`.
+
### Example
```meson
diff --git a/docs/markdown/snippets/gpgme-config.md b/docs/markdown/snippets/gpgme-config.md
new file mode 100644
index 0000000..08a7d38
--- /dev/null
+++ b/docs/markdown/snippets/gpgme-config.md
@@ -0,0 +1,3 @@
+## gpgme dependency now supports gpgme-config
+
+Previously, we could only detect GPGME with custom invocations of `gpgme-config`. Now we added support to Meson allowing us to use `dependency('gpgme')` instead.
diff --git a/docs/markdown/snippets/sanity-check.md b/docs/markdown/snippets/sanity-check.md
new file mode 100644
index 0000000..d5ed80d
--- /dev/null
+++ b/docs/markdown/snippets/sanity-check.md
@@ -0,0 +1,17 @@
+## Sanity checking compilers with user flags
+
+Sanity checks previously only used user-specified flags for cross compilers, but
+now do in all cases.
+
+All compilers meson might decide to use for the build are "sanity checked"
+before other tests are run. This usually involves building simple executable and
+trying to run it. Previously user flags (compilation and/or linking flags) were
+used for sanity checking cross compilers, but not native compilers. This is
+because such flags might be essential for a cross binary to succeed, but usually
+aren't for a native compiler.
+
+In recent releases, there has been an effort to minimize the special-casing of
+cross or native builds so as to make building more predictable in less-tested
+cases. Since this the user flags are necessary for cross, but not harmful for
+native, it makes more sense to use them in all sanity checks than use them in no
+sanity checks, so this is what we now do.
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 01277f0..f1602c0 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -153,8 +153,20 @@ class AstInterpreter(interpreterbase.InterpreterBase):
return True
def evaluate_arithmeticstatement(self, cur):
+ self.evaluate_statement(cur.left)
+ self.evaluate_statement(cur.right)
return 0
+ def evaluate_uminusstatement(self, cur):
+ self.evaluate_statement(cur.value)
+ return 0
+
+ def evaluate_ternary(self, node):
+ assert(isinstance(node, mparser.TernaryNode))
+ self.evaluate_statement(node.condition)
+ self.evaluate_statement(node.trueblock)
+ self.evaluate_statement(node.falseblock)
+
def evaluate_plusassign(self, node):
assert(isinstance(node, mparser.PlusAssignmentNode))
if node.var_name not in self.assignments:
@@ -177,6 +189,18 @@ class AstInterpreter(interpreterbase.InterpreterBase):
return args.arguments, args.kwargs
def evaluate_comparison(self, node):
+ self.evaluate_statement(node.left)
+ self.evaluate_statement(node.right)
+ return False
+
+ def evaluate_andstatement(self, cur):
+ self.evaluate_statement(cur.left)
+ self.evaluate_statement(cur.right)
+ return False
+
+ def evaluate_orstatement(self, cur):
+ self.evaluate_statement(cur.left)
+ self.evaluate_statement(cur.right)
return False
def evaluate_foreach(self, node):
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index 5745d29..5a12e29 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -20,7 +20,7 @@ from .. import compilers, environment, mesonlib, optinterpreter
from .. import coredata as cdata
from ..interpreterbase import InvalidArguments
from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary
-from ..mparser import ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode
+from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode
import os
build_target_functions = ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries']
@@ -142,6 +142,8 @@ class IntrospectionInterpreter(AstInterpreter):
condition_level = node.condition_level if hasattr(node, 'condition_level') else 0
if isinstance(required, ElementaryNode):
required = required.value
+ if not isinstance(required, bool):
+ required = False
self.dependencies += [{
'name': name,
'required': required,
@@ -189,6 +191,8 @@ class IntrospectionInterpreter(AstInterpreter):
# Make sure nothing can crash when creating the build class
kwargs_reduced = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs and k in ['install', 'build_by_default', 'build_always']}
+ kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()}
+ kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)}
is_cross = False
objects = []
empty_sources = [] # Passing the unresolved sources list causes errors
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index d752ac4..04255dc 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -791,6 +791,7 @@ class Backend:
for df in self.interpreter.get_build_def_files()]
if self.environment.is_cross_build():
deps.extend(self.environment.coredata.cross_files)
+ deps.extend(self.environment.coredata.config_files)
deps.append('meson-private/coredata.dat')
if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')):
deps.append(os.path.join(self.build_to_src, 'meson_options.txt'))
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 2560c82..bcf8243 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -309,9 +309,9 @@ class CCompiler(Compiler):
mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist))
mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
- extra_flags = []
source_name = os.path.join(work_dir, sname)
binname = sname.rsplit('.', 1)[0]
+ mode = 'link'
if self.is_cross:
binname += '_cross'
if self.exe_wrapper is None:
@@ -320,7 +320,9 @@ class CCompiler(Compiler):
# on OSX the compiler binary is the same but you need
# a ton of compiler flags to differentiate between
# arm and x86_64. So just compile.
- extra_flags += self.get_compile_only_args()
+ mode = 'compile'
+ extra_flags = self._get_basic_compiler_args(environment, mode)
+
# Is a valid executable output for all toolchains and platforms
binname += '.exe'
# Write binary check source
@@ -392,6 +394,29 @@ class CCompiler(Compiler):
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
+ def _get_basic_compiler_args(self, env, mode):
+ args = []
+ # Select a CRT if needed since we're linking
+ if mode == 'link':
+ args += self.get_linker_debug_crt_args()
+ if env.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ if mode in {'compile', 'preprocess'}:
+ # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
+ sys_args = env.coredata.get_external_args(for_machine, self.language)
+ # Apparently it is a thing to inject linker flags both
+ # via CFLAGS _and_ LDFLAGS, even though the former are
+ # also used during linking. These flags can break
+ # argument checks. Thanks, Autotools.
+ cleaned_sys_args = self.remove_linkerlike_args(sys_args)
+ args += cleaned_sys_args
+ elif mode == 'link':
+ # Add LDFLAGS from the env
+ args += env.coredata.get_external_link_args(for_machine, self.language)
+ return args
+
def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
if extra_args is None:
extra_args = []
@@ -415,25 +440,9 @@ class CCompiler(Compiler):
args += d.get_link_args()
if d.need_threads():
args += self.thread_link_flags(env)
- # Select a CRT if needed since we're linking
- if mode == 'link':
- args += self.get_linker_debug_crt_args()
- if env.is_cross_build() and not self.is_cross:
- for_machine = MachineChoice.BUILD
- else:
- for_machine = MachineChoice.HOST
- if mode in {'compile', 'preprocess'}:
- # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
- sys_args = env.coredata.get_external_args(for_machine, self.language)
- # Apparently it is a thing to inject linker flags both
- # via CFLAGS _and_ LDFLAGS, even though the former are
- # also used during linking. These flags can break
- # argument checks. Thanks, Autotools.
- cleaned_sys_args = self.remove_linkerlike_args(sys_args)
- args += cleaned_sys_args
- elif mode == 'link':
- # Add LDFLAGS from the env
- args += env.coredata.get_external_link_args(for_machine, self.language)
+
+ args += self._get_basic_compiler_args(env, mode)
+
args += self.get_compiler_check_args()
# extra_args must override all other arguments, so we add them last
args += extra_args
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index f1580b6..529919b 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -622,7 +622,15 @@ class DmdDCompiler(DCompiler):
return []
def get_std_shared_lib_link_args(self):
- return ['-shared', '-defaultlib=libphobos2.so']
+ libname = 'libphobos2.so'
+ if is_windows():
+ if self.arch == 'x86_64':
+ libname = 'phobos64.lib'
+ elif self.arch == 'x86_mscoff':
+ libname = 'phobos32mscoff.lib'
+ else:
+ libname = 'phobos.lib'
+ return ['-shared', '-defaultlib=' + libname]
def get_target_arch_args(self):
# DMD32 and DMD64 on 64-bit Windows defaults to 32-bit (OMF).
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index a16f2b5..e747a35 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -31,7 +31,9 @@ from .compilers import (
PGICompiler
)
-from mesonbuild.mesonlib import EnvironmentException, is_osx, LibType
+from mesonbuild.mesonlib import (
+ EnvironmentException, MachineChoice, is_osx, LibType
+)
class FortranCompiler(Compiler):
@@ -74,12 +76,27 @@ class FortranCompiler(Compiler):
def get_soname_args(self, *args):
return CCompiler.get_soname_args(self, *args)
- def sanity_check(self, work_dir, environment):
- source_name = os.path.join(work_dir, 'sanitycheckf.f90')
- binary_name = os.path.join(work_dir, 'sanitycheckf')
- with open(source_name, 'w') as ofile:
- ofile.write('print *, "Fortran compilation is working."; end')
- pc = subprocess.Popen(self.exelist + [source_name, '-o', binary_name])
+ def sanity_check(self, work_dir: Path, environment):
+ """
+ Check to be sure a minimal program can compile and execute
+ with this compiler & platform.
+ """
+ work_dir = Path(work_dir)
+ source_name = work_dir / 'sanitycheckf.f90'
+ binary_name = work_dir / 'sanitycheckf'
+ if binary_name.is_file():
+ binary_name.unlink()
+
+ source_name.write_text('print *, "Fortran compilation is working."; end')
+
+ if environment.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ extra_flags = environment.coredata.get_external_args(for_machine, self.language)
+ extra_flags += environment.coredata.get_external_link_args(for_machine, self.language)
+ # %% build the test executable
+ pc = subprocess.Popen(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)])
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
@@ -87,12 +104,16 @@ class FortranCompiler(Compiler):
if self.exe_wrapper is None:
# Can't check if the binaries run so we have to assume they do
return
- cmdlist = self.exe_wrapper + [binary_name]
+ cmdlist = self.exe_wrapper + [str(binary_name)]
else:
- cmdlist = [binary_name]
- pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- pe.wait()
- if pe.returncode != 0:
+ cmdlist = [str(binary_name)]
+ # %% Run the test executable
+ try:
+ pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pe.wait()
+ if pe.returncode != 0:
+ raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
+ except OSError:
raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
def get_std_warn_args(self, level):
@@ -223,6 +244,9 @@ class FortranCompiler(Compiler):
def gen_import_library_args(self, implibname):
return CCompiler.gen_import_library_args(self, implibname)
+ def _get_basic_compiler_args(self, env, mode):
+ return CCompiler._get_basic_compiler_args(self, env, mode)
+
def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
return CCompiler._get_compiler_check_args(self, env, extra_args, dependencies, mode='compile')
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index 8dfd0a2..c4a7019 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -14,7 +14,7 @@
import os.path, subprocess
-from ..mesonlib import EnvironmentException
+from ..mesonlib import EnvironmentException, MachineChoice
from .c import CCompiler
from .compilers import ClangCompiler, GnuCompiler
@@ -31,9 +31,15 @@ class ObjCCompiler(CCompiler):
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
binary_name = os.path.join(work_dir, 'sanitycheckobjc')
- extra_flags = []
+ if environment.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ extra_flags = environment.coredata.get_external_args(for_machine, self.language)
if self.is_cross:
extra_flags += self.get_compile_only_args()
+ else:
+ extra_flags += environment.coredata.get_external_link_args(for_machine, self.language)
with open(source_name, 'w') as ofile:
ofile.write('#import<stdio.h>\n'
'int main(int argc, char **argv) { return 0; }\n')
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index e66d730..4c23d0a 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -14,7 +14,7 @@
import os.path, subprocess
-from ..mesonlib import EnvironmentException
+from ..mesonlib import EnvironmentException, MachineChoice
from .cpp import CPPCompiler
from .compilers import ClangCompiler, GnuCompiler
@@ -31,11 +31,20 @@ class ObjCPPCompiler(CPPCompiler):
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
+ if environment.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ extra_flags = environment.coredata.get_external_args(for_machine, self.language)
+ if self.is_cross:
+ extra_flags += self.get_compile_only_args()
+ else:
+ extra_flags += environment.coredata.get_external_link_args(for_machine, self.language)
with open(source_name, 'w') as ofile:
ofile.write('#import<stdio.h>\n'
'class MyClass;'
'int main(int argc, char **argv) { return 0; }\n')
- pc = subprocess.Popen(self.exelist + [source_name, '-o', binary_name])
+ pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string())
diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py
index 94e6736..17705ac 100644
--- a/mesonbuild/compilers/swift.py
+++ b/mesonbuild/compilers/swift.py
@@ -14,7 +14,7 @@
import subprocess, os.path
-from ..mesonlib import EnvironmentException
+from ..mesonlib import EnvironmentException, MachineChoice
from .compilers import Compiler, swift_buildtype_args, clike_debug_args
@@ -102,13 +102,25 @@ class SwiftCompiler(Compiler):
src = 'swifttest.swift'
source_name = os.path.join(work_dir, src)
output_name = os.path.join(work_dir, 'swifttest')
+ if environment.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ extra_flags = environment.coredata.get_external_args(for_machine, self.language)
+ if self.is_cross:
+ extra_flags += self.get_compile_only_args()
+ else:
+ extra_flags += environment.coredata.get_external_link_args(for_machine, self.language)
with open(source_name, 'w') as ofile:
ofile.write('''print("Swift compilation is working.")
''')
- pc = subprocess.Popen(self.exelist + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
+ pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Swift compiler %s can not compile programs.' % self.name_string())
+ if self.is_cross:
+ # Can't check if the binaries run so we have to assume they do
+ return
if subprocess.call(output_name) != 0:
raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string())
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index b463f0d..98b8b42 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -15,7 +15,7 @@
import os.path
from .. import mlog
-from ..mesonlib import EnvironmentException, version_compare
+from ..mesonlib import EnvironmentException, MachineChoice, version_compare
from .compilers import Compiler
@@ -87,7 +87,16 @@ class ValaCompiler(Compiler):
def sanity_check(self, work_dir, environment):
code = 'class MesonSanityCheck : Object { }'
- with self.compile(code, [], 'compile') as p:
+ if environment.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ extra_flags = environment.coredata.get_external_args(for_machine, self.language)
+ if self.is_cross:
+ extra_flags += self.get_compile_only_args()
+ else:
+ extra_flags += environment.coredata.get_external_link_args(for_machine, self.language)
+ with self.compile(code, extra_flags, 'compile') as p:
if p.returncode != 0:
msg = 'Vala compiler {!r} can not compile programs' \
''.format(self.name_string())
@@ -105,8 +114,14 @@ class ValaCompiler(Compiler):
# no extra dirs are specified.
if not extra_dirs:
code = 'class MesonFindLibrary : Object { }'
+ if env.is_cross_build() and not self.is_cross:
+ for_machine = MachineChoice.BUILD
+ else:
+ for_machine = MachineChoice.HOST
+ args = env.coredata.get_external_args(for_machine, self.language)
vapi_args = ['--pkg', libname]
- with self.compile(code, vapi_args, 'compile') as p:
+ args += vapi_args
+ with self.compile(code, args, 'compile') as p:
if p.returncode == 0:
return vapi_args
# Not found? Try to find the vapi file itself.
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index b5f48bd..739f6e7 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -26,6 +26,7 @@ from .wrap import WrapMode
import ast
import argparse
import configparser
+from typing import Optional, Any, TypeVar, Generic, Type
version = '0.50.999'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode']
@@ -269,7 +270,6 @@ class CoreData:
self.cross_compilers = OrderedDict()
self.deps = OrderedDict()
# Only to print a warning if it changes between Meson invocations.
- self.pkgconf_envvar = os.environ.get('PKG_CONFIG_PATH', '')
self.config_files = self.__load_config_files(options.native_file)
self.libdir_cross_fixup()
@@ -335,11 +335,10 @@ class CoreData:
def init_builtins(self):
# Create builtin options with default values
self.builtins = {}
- prefix = get_builtin_option_default('prefix')
- for key in get_builtin_options():
- value = get_builtin_option_default(key, prefix)
- args = [key] + builtin_options[key][1:-1] + [value]
- self.builtins[key] = builtin_options[key][0](*args)
+ for key, opt in builtin_options.items():
+ self.builtins[key] = opt.init_option(key)
+ if opt.separate_cross:
+ self.builtins['cross_' + key] = opt.init_option(key)
def init_backend_options(self, backend_name):
if backend_name == 'ninja':
@@ -462,7 +461,7 @@ class CoreData:
self.builtins['prefix'].set_value(prefix)
for key in builtin_dir_noprefix_options:
if key not in options:
- self.builtins[key].set_value(get_builtin_option_default(key, prefix))
+ self.builtins[key].set_value(builtin_options[key].prefixed_default(key, prefix))
unknown_options = []
for k, v in options.items():
@@ -495,7 +494,7 @@ class CoreData:
from . import optinterpreter
for k, v in default_options.items():
if subproject:
- if optinterpreter.is_invalid_name(k):
+ if optinterpreter.is_invalid_name(k, log=False):
continue
k = subproject + ':' + k
env.cmd_line_options.setdefault(k, v)
@@ -506,14 +505,20 @@ class CoreData:
# languages and setting the backend (builtin options must be set first
# to know which backend we'll use).
options = {}
+
+ # Some options default to environment variables if they are
+ # unset, set those now. These will either be overwritten
+ # below, or they won't.
+ options['pkg_config_path'] = os.environ.get('PKG_CONFIG_PATH', '').split(':')
+
for k, v in env.cmd_line_options.items():
if subproject:
if not k.startswith(subproject + ':'):
continue
- elif k not in get_builtin_options():
+ elif k not in builtin_options:
if ':' in k:
continue
- if optinterpreter.is_invalid_name(k):
+ if optinterpreter.is_invalid_name(k, log=False):
continue
options[k] = v
@@ -531,7 +536,7 @@ class CoreData:
if cross_comp is not None:
new_options_for_host = cross_comp.get_and_default_options(env.properties.host)
else:
- new_options_for_host = comp.get_and_default_options(env.properties.host)
+ new_options_for_host = new_options_for_build
opts_machines_list = [
(new_options_for_build, MachineChoice.BUILD),
@@ -656,80 +661,10 @@ def save(obj, build_dir):
os.replace(tempfilename, filename)
return filename
-def get_builtin_options():
- return list(builtin_options.keys())
-
-def is_builtin_option(optname):
- return optname in get_builtin_options()
-
-def get_builtin_option_choices(optname):
- if is_builtin_option(optname):
- if builtin_options[optname][0] == UserComboOption:
- return builtin_options[optname][2]
- elif builtin_options[optname][0] == UserBooleanOption:
- return [True, False]
- elif builtin_options[optname][0] == UserFeatureOption:
- return UserFeatureOption.static_choices
- else:
- return None
- else:
- raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname)
-
-def get_builtin_option_description(optname):
- if is_builtin_option(optname):
- return builtin_options[optname][1]
- else:
- raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname)
-
-def get_builtin_option_action(optname):
- default = builtin_options[optname][2]
- if default is True:
- return 'store_false'
- elif default is False:
- return 'store_true'
- return None
-
-def get_builtin_option_default(optname, prefix=''):
- if is_builtin_option(optname):
- o = builtin_options[optname]
- if o[0] == UserComboOption:
- return o[3]
- if o[0] == UserIntegerOption:
- return o[4]
- try:
- return builtin_dir_noprefix_options[optname][prefix]
- except KeyError:
- pass
- return o[2]
- else:
- raise RuntimeError('Tried to get the default value for an unknown builtin option \'%s\'.' % optname)
-
-def get_builtin_option_cmdline_name(name):
- if name == 'warning_level':
- return '--warnlevel'
- else:
- return '--' + name.replace('_', '-')
-
-def add_builtin_argument(p, name):
- kwargs = {}
- c = get_builtin_option_choices(name)
- b = get_builtin_option_action(name)
- h = get_builtin_option_description(name)
- if not b:
- h = h.rstrip('.') + ' (default: %s).' % get_builtin_option_default(name)
- else:
- kwargs['action'] = b
- if c and not b:
- kwargs['choices'] = c
- kwargs['default'] = argparse.SUPPRESS
- kwargs['dest'] = name
-
- cmdline_name = get_builtin_option_cmdline_name(name)
- p.add_argument(cmdline_name, help=h, **kwargs)
def register_builtin_arguments(parser):
- for n in builtin_options:
- add_builtin_argument(parser, n)
+ for n, b in builtin_options.items():
+ b.add_to_argparse(n, parser)
parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
help='Set the value of an option, can be used several times to set multiple options.')
@@ -747,48 +682,129 @@ def parse_cmd_line_options(args):
args.cmd_line_options = create_options_dict(args.projectoptions)
# Merge builtin options set with --option into the dict.
- for name in builtin_options:
- value = getattr(args, name, None)
- if value is not None:
- if name in args.cmd_line_options:
- cmdline_name = get_builtin_option_cmdline_name(name)
- raise MesonException(
- 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name))
- args.cmd_line_options[name] = value
- delattr(args, name)
+ for name, builtin in builtin_options.items():
+ names = [name]
+ if builtin.separate_cross:
+ names.append('cross_' + name)
+ for name in names:
+ value = getattr(args, name, None)
+ if value is not None:
+ if name in args.cmd_line_options:
+ cmdline_name = BuiltinOption.argparse_name_to_arg(name)
+ raise MesonException(
+ 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name))
+ args.cmd_line_options[name] = value
+ delattr(args, name)
+
+
+_U = TypeVar('_U', bound=UserOption)
+
+class BuiltinOption(Generic[_U]):
+
+ """Class for a builtin option type.
+
+ Currently doesn't support UserIntegerOption, or a few other cases.
+ """
+
+ def __init__(self, opt_type: Type[_U], description: str, default: Any, yielding: Optional[bool] = None, *,
+ choices: Any = None, separate_cross: bool = False):
+ self.opt_type = opt_type
+ self.description = description
+ self.default = default
+ self.choices = choices
+ self.yielding = yielding
+ self.separate_cross = separate_cross
+
+ def init_option(self, name: str) -> _U:
+ """Create an instance of opt_type and return it."""
+ keywords = {'yielding': self.yielding, 'value': self.default}
+ if self.choices:
+ keywords['choices'] = self.choices
+ return self.opt_type(name, self.description, **keywords)
+
+ def _argparse_action(self) -> Optional[str]:
+ if self.default is True:
+ return 'store_false'
+ elif self.default is False:
+ return 'store_true'
+ return None
+
+ def _argparse_choices(self) -> Any:
+ if self.opt_type is UserBooleanOption:
+ return [True, False]
+ elif self.opt_type is UserFeatureOption:
+ return UserFeatureOption.static_choices
+ return self.choices
+
+ @staticmethod
+ def argparse_name_to_arg(name: str) -> str:
+ if name == 'warning_level':
+ return '--warnlevel'
+ else:
+ return '--' + name.replace('_', '-')
+
+ def prefixed_default(self, name: str, prefix: str = '') -> Any:
+ if self.opt_type in [UserComboOption, UserIntegerOption]:
+ return self.default
+ try:
+ return builtin_dir_noprefix_options[name][prefix]
+ except KeyError:
+ pass
+ return self.default
+
+ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser) -> None:
+ kwargs = {}
+
+ c = self._argparse_choices()
+ b = self._argparse_action()
+ h = self.description
+ if not b:
+ h = '{} (default: {}).'.format(h.rstrip('.'), self.prefixed_default(name))
+ else:
+ kwargs['action'] = b
+ if c and not b:
+ kwargs['choices'] = c
+ kwargs['default'] = argparse.SUPPRESS
+ kwargs['dest'] = name
+
+ cmdline_name = self.argparse_name_to_arg(name)
+ parser.add_argument(cmdline_name, help=h, **kwargs)
+ if self.separate_cross:
+ kwargs['dest'] = 'cross_' + name
+ parser.add_argument(self.argparse_name_to_arg('cross_' + name), help=h + ' (for host in cross compiles)', **kwargs)
+
builtin_options = {
- 'buildtype': [UserComboOption, 'Build type to use', ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'], 'debug'],
- 'strip': [UserBooleanOption, 'Strip targets on install', False],
- 'unity': [UserComboOption, 'Unity build', ['on', 'off', 'subprojects'], 'off'],
- 'prefix': [UserStringOption, 'Installation prefix', default_prefix()],
- 'libdir': [UserStringOption, 'Library directory', default_libdir()],
- 'libexecdir': [UserStringOption, 'Library executable directory', default_libexecdir()],
- 'bindir': [UserStringOption, 'Executable directory', 'bin'],
- 'sbindir': [UserStringOption, 'System executable directory', 'sbin'],
- 'includedir': [UserStringOption, 'Header file directory', 'include'],
- 'datadir': [UserStringOption, 'Data file directory', 'share'],
- 'mandir': [UserStringOption, 'Manual page directory', 'share/man'],
- 'infodir': [UserStringOption, 'Info page directory', 'share/info'],
- 'localedir': [UserStringOption, 'Locale data directory', 'share/locale'],
- 'sysconfdir': [UserStringOption, 'Sysconf data directory', 'etc'],
- 'localstatedir': [UserStringOption, 'Localstate data directory', 'var'],
- 'sharedstatedir': [UserStringOption, 'Architecture-independent data directory', 'com'],
- 'werror': [UserBooleanOption, 'Treat warnings as errors', False],
- 'warning_level': [UserComboOption, 'Compiler warning level to use', ['0', '1', '2', '3'], '1'],
- 'layout': [UserComboOption, 'Build directory layout', ['mirror', 'flat'], 'mirror'],
- 'default_library': [UserComboOption, 'Default library type', ['shared', 'static', 'both'], 'shared'],
- 'backend': [UserComboOption, 'Backend to use', backendlist, 'ninja'],
- 'stdsplit': [UserBooleanOption, 'Split stdout and stderr in test logs', True],
- 'errorlogs': [UserBooleanOption, "Whether to print the logs from failing tests", True],
- 'install_umask': [UserUmaskOption, 'Default umask to apply on permissions of installed files', '022'],
- 'auto_features': [UserFeatureOption, "Override value of all 'auto' features", 'auto'],
- 'optimization': [UserComboOption, 'Optimization level', ['0', 'g', '1', '2', '3', 's'], '0'],
- 'debug': [UserBooleanOption, 'Debug', True],
- 'wrap_mode': [UserComboOption, 'Wrap mode', ['default',
- 'nofallback',
- 'nodownload',
- 'forcefallback'], 'default'],
+ 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug',
+ choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom']),
+ 'strip': BuiltinOption(UserBooleanOption, 'Strip targets on install', False),
+ 'unity': BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects']),
+ 'prefix': BuiltinOption(UserStringOption, 'Installation prefix', default_prefix()),
+ 'libdir': BuiltinOption(UserStringOption, 'Library directory', default_libdir()),
+ 'libexecdir': BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir()),
+ 'bindir': BuiltinOption(UserStringOption, 'Executable directory', 'bin'),
+ 'sbindir': BuiltinOption(UserStringOption, 'System executable directory', 'sbin'),
+ 'includedir': BuiltinOption(UserStringOption, 'Header file directory', 'include'),
+ 'datadir': BuiltinOption(UserStringOption, 'Data file directory', 'share'),
+ 'mandir': BuiltinOption(UserStringOption, 'Manual page directory', 'share/man'),
+ 'infodir': BuiltinOption(UserStringOption, 'Info page directory', 'share/info'),
+ 'localedir': BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale'),
+ 'sysconfdir': BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc'),
+ 'localstatedir': BuiltinOption(UserStringOption, 'Localstate data directory', 'var'),
+ 'sharedstatedir': BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com'),
+ 'werror': BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False),
+ 'warning_level': BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3']),
+ 'layout': BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat']),
+ 'default_library': BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both']),
+ 'backend': BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist),
+ 'stdsplit': BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True),
+ 'errorlogs': BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True),
+ 'install_umask': BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022'),
+ 'auto_features': BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto'),
+ 'optimization': BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's']),
+ 'debug': BuiltinOption(UserBooleanOption, 'Debug', True),
+ 'wrap_mode': BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback']),
+ 'pkg_config_path': BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [], separate_cross=True),
}
# Special prefix-dependent defaults for installation directories that reside in
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py
index 53ff1c9..846f3de 100644
--- a/mesonbuild/dependencies/__init__.py
+++ b/mesonbuild/dependencies/__init__.py
@@ -18,7 +18,7 @@ from .base import ( # noqa: F401
ExternalDependency, NotFoundDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency,
PkgConfigDependency, CMakeDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language)
from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency
-from .misc import (CoarrayDependency, HDF5Dependency, MPIDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency)
+from .misc import (CoarrayDependency, HDF5Dependency, MPIDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency, GpgmeDependency, ShadercDependency)
from .platform import AppleFrameworks
from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency
@@ -43,6 +43,8 @@ packages.update({
'cups': CupsDependency,
'libwmf': LibWmfDependency,
'libgcrypt': LibGCryptDependency,
+ 'gpgme': GpgmeDependency,
+ 'shaderc': ShadercDependency,
# From platform:
'appleframeworks': AppleFrameworks,
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index af4b13f..f74eabb 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -419,6 +419,14 @@ class ConfigToolDependency(ExternalDependency):
best_match = (None, None)
for tool in tools:
+ if len(tool) == 1:
+ # In some situations the command can't be directly executed.
+ # For example Shell scripts need to be called through sh on
+ # Windows (see issue #1423).
+ potential_bin = ExternalProgram(tool[0], silent=True)
+ if not potential_bin.found():
+ continue
+ tool = potential_bin.get_command()
try:
p, out = Popen_safe(tool + ['--version'])[:2]
except (FileNotFoundError, PermissionError):
@@ -459,7 +467,7 @@ class ConfigToolDependency(ExternalDependency):
elif req_version:
found_msg.append('need {!r}'.format(req_version))
else:
- found_msg += [mlog.green('YES'), '({})'.format(shutil.which(self.config[0])), version]
+ found_msg += [mlog.green('YES'), '({})'.format(' '.join(self.config)), version]
mlog.log(*found_msg)
@@ -609,11 +617,19 @@ class PkgConfigDependency(ExternalDependency):
return rc, out
def _call_pkgbin(self, args, env=None):
+ # Always copy the environment since we're going to modify it
+ # with pkg-config variables
if env is None:
- fenv = env
- env = os.environ
+ env = os.environ.copy()
else:
- fenv = frozenset(env.items())
+ env = env.copy()
+
+ if self.want_cross:
+ extra_paths = self.env.coredata.get_builtin_option('cross_pkg_config_path')
+ else:
+ extra_paths = self.env.coredata.get_builtin_option('pkg_config_path')
+ env['PKG_CONFIG_PATH'] = ':'.join([p for p in extra_paths])
+ fenv = frozenset(env.items())
targs = tuple(args)
cache = PkgConfigDependency.pkgbin_cache
if (self.pkgbin, targs, fenv) not in cache:
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 52e8ee6..f4694ca 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -117,6 +117,7 @@ class HDF5Dependency(ExternalDependency):
except Exception:
pass
+
class NetCDFDependency(ExternalDependency):
def __init__(self, environment, kwargs):
@@ -211,6 +212,9 @@ class MPIDependency(ExternalDependency):
break
if not self.is_found and mesonlib.is_windows():
+ # only Intel Fortran compiler is compatible with Microsoft MPI at this time.
+ if language == 'fortran' and environment.detect_fortran_compiler(False).name_string() != 'intel':
+ return
result = self._try_msmpi()
if result is not None:
self.is_found = True
@@ -666,3 +670,77 @@ class LibGCryptDependency(ExternalDependency):
@staticmethod
def get_methods():
return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]
+
+
+class GpgmeDependency(ExternalDependency):
+ def __init__(self, environment, kwargs):
+ super().__init__('gpgme', environment, None, kwargs)
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ candidates = []
+
+ if DependencyMethods.CONFIG_TOOL in methods:
+ candidates.append(functools.partial(ConfigToolDependency.factory,
+ 'gpgme', environment, None, kwargs, ['gpgme-config'],
+ 'gpgme-config',
+ GpgmeDependency.tool_finish_init))
+
+ return candidates
+
+ @staticmethod
+ def tool_finish_init(ctdep):
+ ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
+ ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
+ ctdep.version = ctdep.get_config_value(['--version'], 'version')[0]
+
+ @staticmethod
+ def get_methods():
+ return [DependencyMethods.CONFIG_TOOL]
+
+
+class ShadercDependency(ExternalDependency):
+
+ def __init__(self, environment, kwargs):
+ super().__init__('shaderc', environment, None, kwargs)
+
+ static_lib = 'shaderc_combined'
+ shared_lib = 'shaderc_shared'
+
+ libs = [shared_lib, static_lib]
+ if self.static:
+ libs.reverse()
+
+ cc = self.get_compiler()
+
+ for lib in libs:
+ self.link_args = cc.find_library(lib, environment, [])
+ if self.link_args is not None:
+ self.is_found = True
+
+ if self.static and lib != static_lib:
+ mlog.warning('Static library {!r} not found for dependency {!r}, may '
+ 'not be statically linked'.format(static_lib, self.name))
+
+ break
+
+ def log_tried(self):
+ return 'system'
+
+ @classmethod
+ def _factory(cls, environment, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ candidates = []
+
+ if DependencyMethods.SYSTEM in methods:
+ candidates.append(functools.partial(ShadercDependency, environment, kwargs))
+
+ if DependencyMethods.PKGCONFIG in methods:
+ candidates.append(functools.partial(PkgConfigDependency, 'shaderc', environment, kwargs))
+
+ return candidates
+
+ @staticmethod
+ def get_methods():
+ return [DependencyMethods.SYSTEM, DependencyMethods.PKGCONFIG]
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index deb6b7d..2241089 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -215,6 +215,9 @@ def detect_cpu_family(compilers):
trial = 'x86'
elif trial == 'bepc':
trial = 'x86'
+ # OpenBSD's 64 bit arm architecute identifies as 'arm64'
+ elif trial == 'arm64':
+ trial = 'aarch64'
elif trial.startswith('arm'):
trial = 'arm'
elif trial.startswith('ppc64'):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 234b983..4b713ea 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1911,7 +1911,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
'add_languages': {'required'},
'add_project_link_arguments': {'language', 'native'},
'add_project_arguments': {'language', 'native'},
- 'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env'},
+ 'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env', 'is_default'},
'benchmark': {'args', 'env', 'should_fail', 'timeout', 'workdir', 'suite'},
'build_target': known_build_target_kwargs,
'configure_file': {'input',
@@ -2471,7 +2471,8 @@ external dependencies (including libraries) must go to "dependencies".''')
self.active_projectname = current_active
self.subprojects.update(subi.subprojects)
self.subprojects[dirname] = SubprojectHolder(subi, self.subproject_dir, dirname)
- self.build_def_files += subi.build_def_files
+ # Duplicates are possible when subproject uses files from project root
+ self.build_def_files = list(set(self.build_def_files + subi.build_def_files))
self.build.merge(subi.build)
self.build.subprojects[dirname] = subi.project_version
return self.subprojects[dirname]
diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py
index 34fe5a5..bd69244 100644
--- a/mesonbuild/modules/python.py
+++ b/mesonbuild/modules/python.py
@@ -131,7 +131,7 @@ class PythonDependency(ExternalDependency):
if self.is_found:
mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES ({})'.format(py_lookup_method)))
else:
- mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO'))
+ mlog.log('Dependency', mlog.bold(self.name), 'found:', [mlog.red('NO')])
def _find_libpy(self, python_holder, environment):
if python_holder.is_pypy:
@@ -498,9 +498,6 @@ class PythonModule(ExtensionModule):
def find_installation(self, interpreter, state, args, kwargs):
feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0')
disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check)
- if disabled:
- mlog.log('find_installation skipped: feature', mlog.bold(feature), 'disabled')
- return ExternalProgramHolder(NonExistingExternalProgram())
if len(args) > 1:
raise InvalidArguments('find_installation takes zero or one positional argument.')
@@ -511,9 +508,12 @@ class PythonModule(ExtensionModule):
if not isinstance(name_or_path, str):
raise InvalidArguments('find_installation argument must be a string.')
+ if disabled:
+ mlog.log('Program', name_or_path or 'python', 'found:', mlog.red('NO'), '(disabled by:', mlog.bold(feature), ')')
+ return ExternalProgramHolder(NonExistingExternalProgram())
+
if not name_or_path:
- mlog.log("Using meson's python {}".format(mesonlib.python_command))
- python = ExternalProgram('python3', mesonlib.python_command, silent=True)
+ python = ExternalProgram('python3', mesonlib.python_command)
else:
python = ExternalProgram.from_entry('python3', name_or_path)
@@ -521,14 +521,17 @@ class PythonModule(ExtensionModule):
pythonpath = self._get_win_pythonpath(name_or_path)
if pythonpath is not None:
name_or_path = pythonpath
- python = ExternalProgram(name_or_path, silent = True)
+ python = ExternalProgram(name_or_path, silent=True)
# Last ditch effort, python2 or python3 can be named python
# on various platforms, let's not give up just yet, if an executable
# named python is available and has a compatible version, let's use
# it
if not python.found() and name_or_path in ['python2', 'python3']:
- python = ExternalProgram('python', silent = True)
+ python = ExternalProgram('python', silent=True)
+
+ mlog.log('Program', python.name, 'found:',
+ *[mlog.green('YES'), '({})'.format(' '.join(python.command))] if python.found() else [mlog.red('NO')])
if not python.found():
if required:
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index 6e8ca83..ef0511d 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -149,13 +149,6 @@ class MesonApp:
sys.exit(1)
return src_dir, build_dir
- def check_pkgconfig_envvar(self, env):
- curvar = os.environ.get('PKG_CONFIG_PATH', '')
- if curvar != env.coredata.pkgconf_envvar:
- mlog.warning('PKG_CONFIG_PATH has changed between invocations from "%s" to "%s".' %
- (env.coredata.pkgconf_envvar, curvar))
- env.coredata.pkgconf_envvar = curvar
-
def generate(self):
env = environment.Environment(self.source_dir, self.build_dir, self.options)
mlog.initialize(env.get_log_dir(), self.options.fatal_warnings)
@@ -169,7 +162,6 @@ class MesonApp:
mlog.debug('Main binary:', sys.executable)
mlog.debug('Python system:', platform.system())
mlog.log(mlog.bold('The Meson build system'))
- self.check_pkgconfig_envvar(env)
mlog.log('Version:', coredata.version)
mlog.log('Source dir:', mlog.bold(self.source_dir))
mlog.log('Build dir:', mlog.bold(self.build_dir))
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index dc82084..0f15690 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -490,7 +490,9 @@ class SingleTestRunner:
stderr = None
if not self.options.verbose:
stdout = tempfile.TemporaryFile("wb+")
- stderr = tempfile.TemporaryFile("wb+") if self.options and self.options.split else stdout
+ stderr = tempfile.TemporaryFile("wb+") if self.options.split else stdout
+ if self.test.protocol == 'tap' and stderr is stdout:
+ stdout = tempfile.TemporaryFile("wb+")
# Let gdb handle ^C instead of us
if self.options.gdb:
@@ -570,17 +572,16 @@ class SingleTestRunner:
endtime = time.time()
duration = endtime - starttime
if additional_error is None:
- if stdout is None: # if stdout is None stderr should be as well
+ if stdout is None:
stdo = ''
- stde = ''
else:
stdout.seek(0)
stdo = decode(stdout.read())
- if stderr != stdout:
- stderr.seek(0)
- stde = decode(stderr.read())
- else:
- stde = ""
+ if stderr is None or stderr is stdout:
+ stde = ''
+ else:
+ stderr.seek(0)
+ stde = decode(stderr.read())
else:
stdo = ""
stde = additional_error
@@ -590,6 +591,8 @@ class SingleTestRunner:
if self.test.protocol == 'exitcode':
return TestRun.make_exitcode(self.test, p.returncode, duration, stdo, stde, cmd)
else:
+ if self.options.verbose:
+ print(stdo, end='')
return TestRun.make_tap(self.test, p.returncode, duration, stdo, stde, cmd)
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 85f6897..e64ed4e 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -20,19 +20,20 @@ from . import coredata
from . import mesonlib
from . import compilers
-forbidden_option_names = coredata.get_builtin_options()
+forbidden_option_names = set(coredata.builtin_options.keys())
forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_']
reserved_prefixes = ['cross_']
-def is_invalid_name(name):
+def is_invalid_name(name: str, *, log: bool = True) -> bool:
if name in forbidden_option_names:
return True
pref = name.split('_')[0] + '_'
if pref in forbidden_prefixes:
return True
if pref in reserved_prefixes:
- from . import mlog
- mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref)
+ if log:
+ from . import mlog
+ mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref)
return False
class OptionException(mesonlib.MesonException):
diff --git a/mesonbuild/scripts/symbolextractor.py b/mesonbuild/scripts/symbolextractor.py
index 976d2f0..95ea0ec 100644
--- a/mesonbuild/scripts/symbolextractor.py
+++ b/mesonbuild/scripts/symbolextractor.py
@@ -68,7 +68,14 @@ def linux_syms(libfilename, outfilename):
libfilename])[0:2]
if pnm.returncode != 0:
raise RuntimeError('nm does not work.')
- result += [' '.join(x.split()[0:2]) for x in output.split('\n') if len(x) > 0]
+ for line in output.split('\n'):
+ if len(line) == 0:
+ continue
+ line_split = line.split()
+ entry = line_split[0:2]
+ if len(line_split) >= 4:
+ entry += [line_split[3]]
+ result += [' '.join(entry)]
write_if_changed('\n'.join(result) + '\n', outfilename)
def osx_syms(libfilename, outfilename):
diff --git a/mesonbuild/scripts/vcstagger.py b/mesonbuild/scripts/vcstagger.py
index 62a45d9..16dd4d1 100644
--- a/mesonbuild/scripts/vcstagger.py
+++ b/mesonbuild/scripts/vcstagger.py
@@ -14,6 +14,7 @@
import sys, os, subprocess, re
+
def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, cmd):
try:
output = subprocess.check_output(cmd, cwd=source_dir)
@@ -21,17 +22,18 @@ def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_
except Exception:
new_string = fallback
- with open(infile) as f:
+ with open(infile, encoding='utf8') as f:
new_data = f.read().replace(replace_string, new_string)
if os.path.exists(outfile):
- with open(outfile) as f:
+ with open(outfile, encoding='utf8') as f:
needs_update = (f.read() != new_data)
else:
needs_update = True
if needs_update:
- with open(outfile, 'w') as f:
+ with open(outfile, 'w', encoding='utf8') as f:
f.write(new_data)
+
def run(args):
infile, outfile, fallback, source_dir, replace_string, regex_selector = args[0:6]
command = args[6:]
diff --git a/run_cross_test.py b/run_cross_test.py
index b2ef6be..8d18123 100755
--- a/run_cross_test.py
+++ b/run_cross_test.py
@@ -34,7 +34,7 @@ def runtests(cross_file, failfast):
commontests = [('common', gather_tests(Path('test cases', 'common')), False)]
try:
(passing_tests, failing_tests, skipped_tests) = \
- run_tests(commontests, 'meson-cross-test-run', failfast, ['--cross', cross_file])
+ run_tests(commontests, 'meson-cross-test-run', failfast, ['--cross-file', cross_file])
except StopException:
pass
print('\nTotal passed cross tests:', passing_tests)
diff --git a/run_project_tests.py b/run_project_tests.py
index 467d522..fdb5f48 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -460,6 +460,7 @@ def have_objc_compiler():
return False
if not objc_comp:
return False
+ env.coredata.process_new_compilers('objc', objc_comp, None, env)
try:
objc_comp.sanity_check(env.get_scratch_dir(), env)
except mesonlib.MesonException:
@@ -475,6 +476,7 @@ def have_objcpp_compiler():
return False
if not objcpp_comp:
return False
+ env.coredata.process_new_compilers('objcpp', objcpp_comp, None, env)
try:
objcpp_comp.sanity_check(env.get_scratch_dir(), env)
except mesonlib.MesonException:
@@ -561,7 +563,7 @@ def detect_tests_to_run():
('C#', 'csharp', skip_csharp(backend)),
('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')),
('rust', 'rust', backend is not Backend.ninja or not shutil.which('rustc')),
- ('d', 'd', backend is not Backend.ninja or not have_d_compiler() or mesonlib.is_windows()),
+ ('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objc_compiler()),
('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objcpp_compiler()),
('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')),
diff --git a/run_unittests.py b/run_unittests.py
index f381efc..19426b8 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3408,7 +3408,7 @@ recommended as it is not supported on some platforms''')
self.assertDictEqual(buildopts_to_find, {})
# Check buildsystem_files
- bs_files = ['meson.build', 'sharedlib/meson.build', 'staticlib/meson.build']
+ bs_files = ['meson.build', 'meson_options.txt', 'sharedlib/meson.build', 'staticlib/meson.build']
bs_files = [os.path.join(testdir, x) for x in bs_files]
self.assertPathListEqual(list(sorted(res['buildsystem_files'])), list(sorted(bs_files)))
@@ -3560,6 +3560,12 @@ recommended as it is not supported on some platforms''')
'conditional': False
},
{
+ 'name': 'bugDep1',
+ 'required': False,
+ 'has_fallback': False,
+ 'conditional': False
+ },
+ {
'name': 'somethingthatdoesnotexist',
'required': True,
'has_fallback': False,
@@ -4373,12 +4379,11 @@ class LinuxlikeTests(BasePlatformTests):
cmd_std = '-std=FAIL'
env_flags = p.upper() + 'FLAGS'
os.environ[env_flags] = cmd_std
- self.init(testdir)
- cmd = self.get_compdb()[0]['command']
- qcmd_std = " {} ".format(cmd_std)
- self.assertIn(qcmd_std, cmd)
- with self.assertRaises(subprocess.CalledProcessError,
- msg='{} should have failed'.format(qcmd_std)):
+ with self.assertRaises((subprocess.CalledProcessError, mesonbuild.mesonlib.EnvironmentException),
+ msg='C compiler should have failed with -std=FAIL'):
+ self.init(testdir)
+ # ICC won't fail in the above because additional flags are needed to
+ # make unknown -std=... options errors.
self.build()
def test_compiler_c_stds(self):
@@ -4832,9 +4837,9 @@ endian = 'little'
testdir = os.path.join(self.unit_test_dir, '58 pkgconfig relative paths')
pkg_dir = os.path.join(testdir, 'pkgconfig')
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc')))
- os.environ['PKG_CONFIG_PATH'] = pkg_dir
env = get_fake_env(testdir, self.builddir, self.prefix)
+ env.coredata.set_options({'pkg_config_path': pkg_dir}, '')
kwargs = {'required': True, 'silent': True}
relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs)
self.assertTrue(relative_path_dep.found())
@@ -4873,7 +4878,7 @@ endian = 'little'
myenv['PKG_CONFIG_PATH'] = self.privatedir
stdo = subprocess.check_output(['pkg-config', '--libs-only-l', 'libsomething'], env=myenv)
deps = [b'-lgobject-2.0', b'-lgio-2.0', b'-lglib-2.0', b'-lsomething']
- if is_windows() or is_cygwin() or is_osx():
+ if is_windows() or is_cygwin() or is_osx() or is_openbsd():
# On Windows, libintl is a separate library
deps.append(b'-lintl')
self.assertEqual(set(deps), set(stdo.split()))
@@ -5063,6 +5068,11 @@ endian = 'little'
# Assert that
self.assertEqual(len(line.split(lib)), 2, msg=(lib, line))
+ @skipIfNoPkgconfig
+ def test_pkg_config_option(self):
+ testdir = os.path.join(self.unit_test_dir, '55 pkg_config_path option')
+ self.init(testdir, extra_args=['-Dpkg_config_path=' + os.path.join(testdir, 'extra_path')])
+
def should_run_cross_arm_tests():
return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm')
@@ -5159,6 +5169,11 @@ class LinuxCrossMingwTests(BasePlatformTests):
# Must run in-process or we'll get a generic CalledProcessError
self.run_tests(inprocess=True)
+ @skipIfNoPkgconfig
+ def test_cross_pkg_config_option(self):
+ testdir = os.path.join(self.unit_test_dir, '55 pkg_config_path option')
+ self.init(testdir, extra_args=['-Dcross_pkg_config_path=' + os.path.join(testdir, 'extra_path')])
+
class PythonTests(BasePlatformTests):
'''
diff --git a/test cases/common/177 initial c_args/meson.build b/test cases/common/177 initial c_args/meson.build
index 169d2bd..638f8c2 100644
--- a/test cases/common/177 initial c_args/meson.build
+++ b/test cases/common/177 initial c_args/meson.build
@@ -3,5 +3,5 @@ project('options', 'c')
# Test passing c_args and c_link_args options from the command line.
assert(get_option('c_args') == ['-funroll-loops'],
'Incorrect value for c_args option.')
-assert(get_option('c_link_args') == ['-random_linker_option'],
+assert(get_option('c_link_args') == ['-Dtest_harmless_but_useless_link_arg'],
'Incorrect value for c_link_args option.')
diff --git a/test cases/common/177 initial c_args/test_args.txt b/test cases/common/177 initial c_args/test_args.txt
index 9a6da06..166e481 100644
--- a/test cases/common/177 initial c_args/test_args.txt
+++ b/test cases/common/177 initial c_args/test_args.txt
@@ -1,4 +1,4 @@
# This file is not read by meson itself, but by the test framework.
# It is not possible to pass arguments to meson from a file.
['-Dc_args=-march=native', '-Dc_args=-funroll-loops',
- '-Dc_link_args=-random_linker_option']
+ '-Dc_link_args=-Dtest_harmless_but_useless_link_arg']
diff --git a/test cases/failing/85 gtest dependency with version/meson.build b/test cases/failing/85 gtest dependency with version/meson.build
index 5115f27..3d90994 100644
--- a/test cases/failing/85 gtest dependency with version/meson.build
+++ b/test cases/failing/85 gtest dependency with version/meson.build
@@ -1,3 +1,3 @@
project('gtest dependency with version', ['c', 'cpp'])
# discovering gtest version is not yet implemented
-dep = dependency('gtest', version: '>0')
+dep = dependency('gtest', method: 'system', version: '>0')
diff --git a/test cases/frameworks/17 mpi/is_broken_ubuntu.py b/test cases/frameworks/17 mpi/is_broken_ubuntu.py
deleted file mode 100755
index 27651ba..0000000
--- a/test cases/frameworks/17 mpi/is_broken_ubuntu.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python3
-
-# Any exception causes return value to be not zero, which is sufficient.
-
-import sys
-
-fc = open('/etc/apt/sources.list').read()
-if 'artful' not in fc and 'bionic' not in fc and 'cosmic' not in fc:
- sys.exit(1)
diff --git a/test cases/frameworks/17 mpi/main.f90 b/test cases/frameworks/17 mpi/main.f90
index d379e96..b5666e8 100644
--- a/test cases/frameworks/17 mpi/main.f90
+++ b/test cases/frameworks/17 mpi/main.f90
@@ -1,21 +1,30 @@
-program mpitest
- implicit none
- include 'mpif.h'
- logical :: flag
- integer :: ier
- call MPI_Init(ier)
- if (ier /= 0) then
- print *, 'Unable to initialize MPI: ', ier
- stop 1
- endif
- call MPI_Initialized(flag, ier)
- if (ier /= 0) then
- print *, 'Unable to check MPI initialization state: ', ier
- stop 1
- endif
- call MPI_Finalize(ier)
- if (ier /= 0) then
- print *, 'Unable to finalize MPI: ', ier
- stop 1
- endif
-end program mpitest
+use, intrinsic :: iso_fortran_env, only: stderr=>error_unit
+use mpi
+
+implicit none
+
+logical :: flag
+integer :: ier
+
+call MPI_Init(ier)
+
+if (ier /= 0) then
+ write(stderr,*) 'Unable to initialize MPI', ier
+ stop 1
+endif
+
+call MPI_Initialized(flag, ier)
+if (ier /= 0) then
+ write(stderr,*) 'Unable to check MPI initialization state: ', ier
+ stop 1
+endif
+
+call MPI_Finalize(ier)
+if (ier /= 0) then
+ write(stderr,*) 'Unable to finalize MPI: ', ier
+ stop 1
+endif
+
+print *, "OK: Fortran MPI"
+
+end program
diff --git a/test cases/frameworks/17 mpi/meson.build b/test cases/frameworks/17 mpi/meson.build
index 2d0e4d3..8af9374 100644
--- a/test cases/frameworks/17 mpi/meson.build
+++ b/test cases/frameworks/17 mpi/meson.build
@@ -26,21 +26,15 @@ if build_machine.system() != 'windows'
test('MPI C++', execpp)
endif
-# OpenMPI is broken with Fortran on Ubuntu Artful.
-# Remove this once the following bug has been fixed:
-#
-# https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1727474
-
-ubudetector = find_program('is_broken_ubuntu.py')
-uburesult = run_command(ubudetector)
-
-if uburesult.returncode() != 0 and add_languages('fortran', required : false)
- mpifort = dependency('mpi', language : 'fortran')
- # Mixing compilers (msvc/clang with gfortran) does not seem to work on Windows.
- if build_machine.system() != 'windows' or cc.get_id() == 'gnu'
+# One of few feasible ways to use MPI for Fortran on Windows is via Intel compilers.
+if build_machine.system() != 'windows' or cc.get_id() == 'intel'
+ if add_languages('fortran', required : false)
+ mpifort = dependency('mpi', language : 'fortran')
+
exef = executable('exef',
- 'main.f90',
- dependencies : [mpifort])
+ 'main.f90',
+ dependencies : [mpifort])
+
test('MPI Fortran', exef)
endif
endif
diff --git a/test cases/frameworks/27 gpgme/gpgme_prog.c b/test cases/frameworks/27 gpgme/gpgme_prog.c
new file mode 100644
index 0000000..594f685
--- /dev/null
+++ b/test cases/frameworks/27 gpgme/gpgme_prog.c
@@ -0,0 +1,8 @@
+#include <gpgme.h>
+
+int
+main()
+{
+ printf("gpgme-v%s", gpgme_check_version(NULL));
+ return 0;
+}
diff --git a/test cases/frameworks/27 gpgme/meson.build b/test cases/frameworks/27 gpgme/meson.build
new file mode 100644
index 0000000..220a4c0
--- /dev/null
+++ b/test cases/frameworks/27 gpgme/meson.build
@@ -0,0 +1,21 @@
+project('gpgme test', 'c')
+
+wm = find_program('gpgme-config', required: false)
+if not wm.found()
+ error('MESON_SKIP_TEST: gpgme-config not installed')
+endif
+
+gpgme_dep = dependency('gpgme', version: '>= 1.0')
+gpgme_ver = gpgme_dep.version()
+assert(gpgme_ver.split('.').length() > 1, 'gpgme version is "@0@"'.format(gpgme_ver))
+message('gpgme version is "@0@"'.format(gpgme_ver))
+e = executable('gpgme_prog', 'gpgme_prog.c', dependencies: gpgme_dep)
+
+test('gpgmetest', e)
+
+# Test using the method keyword:
+
+dependency('gpgme', method: 'config-tool')
+
+# Check we can apply a version constraint
+dependency('gpgme', version: '>=@0@'.format(gpgme_dep.version()), method: 'config-tool')
diff --git a/test cases/python/1 basic/meson.build b/test cases/python/1 basic/meson.build
index f9a7433..9c3af10 100644
--- a/test cases/python/1 basic/meson.build
+++ b/test cases/python/1 basic/meson.build
@@ -1,7 +1,7 @@
project('python sample', 'c')
py_mod = import('python')
-py = py_mod.find_installation()
+py = py_mod.find_installation('python3')
py_version = py.language_version()
if py_version.version_compare('< 3.2')
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
index 98f6f22..588f71c 100644
--- a/test cases/unit/55 introspection/meson.build
+++ b/test cases/unit/55 introspection/meson.build
@@ -2,6 +2,12 @@ project('introspection', ['c', 'cpp'], version: '1.2.3', default_options: ['cpp_
dep1 = dependency('threads')
dep2 = dependency('zlib', required: false)
+dep3 = dependency('bugDep1', required: get_option('test_opt1'))
+
+b1 = get_option('test_opt1')
+b2 = get_option('test_opt2')
+test_bool = b1 or b2
+test_bool = b1 and b2
if false
dependency('somethingthatdoesnotexist', required: true)
@@ -11,7 +17,7 @@ endif
subdir('sharedlib')
subdir('staticlib')
-t1 = executable('test1', 't1.cpp', link_with: [sharedlib], install: true)
+t1 = executable('test1', 't1.cpp', link_with: [sharedlib], install: true, build_by_default: get_option('test_opt2'))
t2 = executable('test2', 't2.cpp', link_with: [staticlib])
t3 = executable('test3', 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1])
diff --git a/test cases/unit/55 introspection/meson_options.txt b/test cases/unit/55 introspection/meson_options.txt
new file mode 100644
index 0000000..fc5cb4d
--- /dev/null
+++ b/test cases/unit/55 introspection/meson_options.txt
@@ -0,0 +1,2 @@
+option('test_opt1', type: 'boolean', value: false, description: 'simple boolean flag')
+option('test_opt2', type: 'boolean', value: true, description: 'simple boolean flag')
diff --git a/test cases/unit/55 pkg_config_path option/extra_path/totally_made_up_dep.pc b/test cases/unit/55 pkg_config_path option/extra_path/totally_made_up_dep.pc
new file mode 100644
index 0000000..6d08687
--- /dev/null
+++ b/test cases/unit/55 pkg_config_path option/extra_path/totally_made_up_dep.pc
@@ -0,0 +1,7 @@
+prefix=/
+libdir=${prefix}/lib
+includedir=${prefix}/include
+
+Name: totally_made_up_dep
+Description: completely and totally made up for a test case
+Version: 1.2.3 \ No newline at end of file
diff --git a/test cases/unit/55 pkg_config_path option/meson.build b/test cases/unit/55 pkg_config_path option/meson.build
new file mode 100644
index 0000000..623c3a2
--- /dev/null
+++ b/test cases/unit/55 pkg_config_path option/meson.build
@@ -0,0 +1,3 @@
+project('pkg_config_path option')
+
+dependency('totally_made_up_dep', method : 'pkg-config')