aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authors.txt1
-rw-r--r--mesonbuild/backend/backends.py11
-rw-r--r--mesonbuild/backend/ninjabackend.py6
-rw-r--r--mesonbuild/build.py8
-rw-r--r--mesonbuild/compilers.py212
-rw-r--r--mesonbuild/environment.py8
-rw-r--r--mesonbuild/interpreter.py141
-rw-r--r--mesonbuild/modules/i18n.py3
-rw-r--r--mesonbuild/optinterpreter.py7
-rw-r--r--mesonbuild/scripts/depfixer.py2
-rwxr-xr-xmesontest.py288
-rwxr-xr-xrun_project_tests.py12
-rwxr-xr-xrun_unittests.py124
-rw-r--r--test cases/common/1 trivial/meson.build5
-rw-r--r--test cases/common/132 dependency file generation/main .c3
-rw-r--r--test cases/common/132 dependency file generation/meson.build12
-rw-r--r--test cases/common/2 cpp/meson.build6
-rw-r--r--test cases/common/25 object extraction/meson.build4
-rw-r--r--test cases/common/94 default options/meson.build8
-rw-r--r--test cases/d/3 shared library/meson.build15
-rw-r--r--test cases/d/3 shared library/no-installed-files0
-rw-r--r--test cases/d/4 library versions/meson.build33
-rw-r--r--test cases/d/4 library versions/no-installed-files0
-rw-r--r--test cases/failing build/1 vala c werror/unused-var.c2
-rw-r--r--test cases/fortran/1 basic/meson.build2
-rw-r--r--test cases/fortran/1 basic/simple.f90 (renamed from test cases/fortran/1 basic/simple.f95)0
-rw-r--r--test cases/fortran/2 modules/meson.build2
-rw-r--r--test cases/fortran/2 modules/prog.f90 (renamed from test cases/fortran/2 modules/prog.f95)0
-rw-r--r--test cases/fortran/2 modules/stuff.f90 (renamed from test cases/fortran/2 modules/stuff.f95)0
-rw-r--r--test cases/fortran/5 static/main.f90 (renamed from test cases/fortran/5 static/main.f95)0
-rw-r--r--test cases/fortran/5 static/meson.build4
-rw-r--r--test cases/fortran/5 static/static_hello.f90 (renamed from test cases/fortran/5 static/static_hello.f95)0
-rw-r--r--test cases/fortran/6 dynamic/dynamic.f90 (renamed from test cases/fortran/6 dynamic/dynamic.f95)0
-rw-r--r--test cases/fortran/6 dynamic/main.f90 (renamed from test cases/fortran/6 dynamic/main.f95)0
-rw-r--r--test cases/fortran/6 dynamic/meson.build4
-rw-r--r--test cases/frameworks/11 gir subproject/gir/meson.build8
-rw-r--r--test cases/frameworks/7 gnome/gir/meson.build7
-rw-r--r--test cases/frameworks/7 gnome/meson.build10
-rw-r--r--test cases/unit/2 testsetups/buggy.c14
-rw-r--r--test cases/unit/2 testsetups/impl.c5
-rw-r--r--test cases/unit/2 testsetups/impl.h3
-rw-r--r--test cases/unit/2 testsetups/meson.build16
-rw-r--r--test cases/unit/3 subproject defaults/meson.build11
-rw-r--r--test cases/unit/3 subproject defaults/meson_options.txt3
-rw-r--r--test cases/unit/3 subproject defaults/subprojects/foob/meson.build12
-rw-r--r--test cases/unit/3 subproject defaults/subprojects/foob/meson_options.txt5
-rw-r--r--test cases/windows/7 mingw dll versioning/meson.build20
-rw-r--r--test cases/windows/7 mingw dll versioning/no-installed-files0
-rw-r--r--test cases/windows/8 msvc dll versioning/meson.build20
-rw-r--r--test cases/windows/8 msvc dll versioning/no-installed-files0
50 files changed, 788 insertions, 269 deletions
diff --git a/authors.txt b/authors.txt
index 2c2a4df..18863eb 100644
--- a/authors.txt
+++ b/authors.txt
@@ -60,3 +60,4 @@ Daniel Stone
Marc-Antoine Perennou
Matthieu Gautier
Kseniia Vasilchuk
+Philipp Geier
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index ac184f0..7e3f936 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -197,15 +197,20 @@ class Backend():
def serialise_executable(self, exe, cmd_args, workdir, env={},
capture=None):
- import uuid
+ import hashlib
# Can't just use exe.name here; it will likely be run more than once
if isinstance(exe, (dependencies.ExternalProgram,
build.BuildTarget, build.CustomTarget)):
basename = exe.name
else:
basename = os.path.basename(exe)
- scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename,
- str(uuid.uuid4())[:8])
+ # Take a digest of the cmd args, env, workdir, and capture. This avoids
+ # collisions and also makes the name deterministic over regenerations
+ # which avoids a rebuild by Ninja because the cmdline stays the same.
+ data = bytes(str(sorted(env.items())) + str(cmd_args) + str(workdir) + str(capture),
+ encoding='utf-8')
+ digest = hashlib.sha1(data).hexdigest()
+ scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest)
exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file)
with open(exe_data, 'wb') as f:
if isinstance(exe, dependencies.ExternalProgram):
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 77d8b1c..429bb64 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1837,6 +1837,8 @@ rule FORTRAN_DEP_HACK
pchlist = []
if len(pchlist) == 0:
pch_dep = []
+ elif compiler.id == 'intel':
+ pch_dep = []
else:
arr = []
i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0]))
@@ -1956,6 +1958,9 @@ rule FORTRAN_DEP_HACK
src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1])
(commands, dep, dst, objs) = self.generate_msvc_pch_command(target, compiler, pch)
extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0])
+ elif compiler.id == 'intel':
+ # Intel generates on target generation
+ continue
else:
src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0])
(commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0])
@@ -2104,7 +2109,6 @@ rule FORTRAN_DEP_HACK
e = NinjaBuildElement(self.all_outputs, 'clean-ctlist', 'CUSTOM_COMMAND', 'PHONY')
d = CleanTrees(self.environment.get_build_dir(), trees)
d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat')
- script_root = self.environment.get_script_dir()
e.add_item('COMMAND', [sys.executable,
self.environment.get_build_command(),
'--internal', 'cleantrees', d_file])
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 449afe7..f895531 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -98,6 +98,7 @@ class Build:
self.dep_manifest_name = None
self.dep_manifest = {}
self.cross_stdlibs = {}
+ self.test_setups = {}
def add_compiler(self, compiler):
if self.static_linker is None and compiler.needs_static_linker():
@@ -1507,3 +1508,10 @@ class RunScript(dict):
assert(isinstance(args, list))
self['exe'] = script
self['args'] = args
+
+class TestSetup:
+ def __init__(self, *, exe_wrapper=None, gdb=None, timeout_multiplier=None, env=None):
+ self.exe_wrapper = exe_wrapper
+ self.gdb = gdb
+ self.timeout_multiplier = timeout_multiplier
+ self.env = env
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 06f76e4..bd8d0a1 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -33,7 +33,9 @@ lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so')
lang_suffixes = {
'c': ('c',),
'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
- 'fortran': ('f', 'f90', 'f95'),
+ # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
+ # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
+ 'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
'd': ('d', 'di'),
'objc': ('m',),
'objcpp': ('mm',),
@@ -1683,9 +1685,10 @@ class GnuDCompiler(DCompiler):
def __init__(self, exelist, version, is_cross):
DCompiler.__init__(self, exelist, version, is_cross)
self.id = 'gcc'
- self.warn_args = {'1': ['-Wall', '-Wdeprecated'],
- '2': ['-Wall', '-Wextra', '-Wdeprecated'],
- '3': ['-Wall', '-Wextra', '-Wdeprecated', '-Wpedantic']}
+ default_warn_args = ['-Wall', '-Wdeprecated']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic']
def get_colorout_args(self, colortype):
@@ -2064,6 +2067,10 @@ CLANG_OSX = 1
CLANG_WIN = 2
# Possibly clang-cl?
+ICC_STANDARD = 0
+ICC_OSX = 1
+ICC_WIN = 2
+
def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module):
if soversion is None:
sostr = ''
@@ -2072,7 +2079,6 @@ def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, i
if gcc_type == GCC_STANDARD or gcc_type == GCC_MINGW:
# Might not be correct for mingw but seems to work.
return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)]
- return ['-Wl,-soname,%s%s' % (shlib_name, sostr)]
elif gcc_type == GCC_OSX:
if is_shared_module:
return []
@@ -2149,9 +2155,10 @@ class GnuCCompiler(GnuCompiler, CCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
GnuCompiler.__init__(self, gcc_type, defines)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']}
+ default_warn_args = ['-Wall', '-Winvalid-pch']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
opts = {'c_std': coredata.UserComboOption('c_std', 'C language standard to use',
@@ -2185,9 +2192,10 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines):
CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
GnuCompiler.__init__(self, gcc_type, defines)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
+ default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
@@ -2224,6 +2232,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
# too strict without this and always fails.
return self.get_no_optimization_args() + ['-fpermissive']
+
class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, defines=None):
@@ -2231,9 +2240,10 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
# Not really correct, but GNU objc is only used on non-OSX non-win. File a bug
# if this breaks your use case.
GnuCompiler.__init__(self, GCC_STANDARD, defines)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']}
+ default_warn_args = ['-Wall', '-Winvalid-pch']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
@@ -2242,9 +2252,10 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
# Not really correct, but GNU objc is only used on non-OSX non-win. File a bug
# if this breaks your use case.
GnuCompiler.__init__(self, GCC_STANDARD, defines)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
+ default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_compiler_check_args(self):
# -fpermissive allows non-conforming code to compile which is necessary
@@ -2284,7 +2295,7 @@ class ClangCompiler():
# Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
# This flag is internal to Clang (or at least not documented on the man page)
# so it might change semantics at any time.
- return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))]
+ return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
if self.clang_type == CLANG_STANDARD:
@@ -2322,9 +2333,10 @@ class ClangCCompiler(ClangCompiler, CCompiler):
def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
ClangCompiler.__init__(self, clang_type)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']}
+ default_warn_args = ['-Wall', '-Winvalid-pch']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
return {'c_std': coredata.UserComboOption('c_std', 'C language standard to use',
@@ -2347,14 +2359,15 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
ClangCompiler.__init__(self, cltype)
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
+ default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
return {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++03', 'c++11', 'c++14', 'c++1z',
- 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++1z'],
+ 'gnu++11', 'gnu++14', 'gnu++1z'],
'none')}
def get_option_compile_args(self, options):
@@ -2379,6 +2392,140 @@ class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler):
ClangCompiler.__init__(self, cltype)
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
+
+# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
+class IntelCompiler:
+ def __init__(self, icc_type):
+ self.id = 'intel'
+ self.icc_type = icc_type
+ self.lang_header = 'none'
+ self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
+ 'b_colorout', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']
+ # Assembly
+ self.can_compile_suffixes.add('s')
+
+ def get_pic_args(self):
+ return ['-fPIC']
+
+ def get_buildtype_args(self, buildtype):
+ return gnulike_buildtype_args[buildtype]
+
+ def get_buildtype_linker_args(self, buildtype):
+ return gnulike_buildtype_linker_args[buildtype]
+
+ def get_pch_suffix(self):
+ return 'pchi'
+
+ def get_pch_use_args(self, pch_dir, header):
+ return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x',
+ self.lang_header, '-include', header, '-x', 'none']
+
+ def get_pch_name(self, header_name):
+ return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
+
+ def split_shlib_to_parts(self, fname):
+ return (os.path.split(fname)[0], fname)
+
+ def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
+ if self.icc_type == ICC_STANDARD:
+ gcc_type = GCC_STANDARD
+ elif self.icc_type == ICC_OSX:
+ gcc_type = GCC_OSX
+ elif self.icc_type == ICC_WIN:
+ gcc_type = GCC_MINGW
+ else:
+ raise MesonException('Unreachable code when converting icc type to gcc type.')
+ return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
+
+ def get_std_shared_lib_link_args(self):
+ # FIXME: Don't know how icc works on OSX
+ # if self.icc_type == ICC_OSX:
+ # return ['-bundle']
+ return ['-shared']
+
+
+class IntelCCompiler(IntelCompiler, CCompiler):
+ def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None):
+ CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ IntelCompiler.__init__(self, icc_type)
+ self.lang_header = 'c-header'
+ default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+ def get_options(self):
+ c_stds = ['c89', 'c99']
+ g_stds = ['gnu89', 'gnu99']
+ if mesonlib.version_compare(self.version, '>=16.0.0'):
+ c_stds += ['c11']
+ opts = {'c_std': coredata.UserComboOption('c_std', 'C language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none')}
+ return opts
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['c_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
+ def get_std_shared_lib_link_args(self):
+ return ['-shared']
+
+ def has_multi_arguments(self, args, env):
+ return super(IntelCCompiler, self).has_multi_arguments(args + ['-diag-error', '10006'], env)
+
+
+class IntelCPPCompiler(IntelCompiler, CPPCompiler):
+ def __init__(self, exelist, version, icc_type, is_cross, exe_wrap):
+ CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
+ IntelCompiler.__init__(self, icc_type)
+ self.lang_header = 'c++-header'
+ default_warn_args = ['-Wall', '-w3', '-diag-disable:remark',
+ '-Wpch-messages', '-Wnon-virtual-dtor']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+ def get_options(self):
+ c_stds = []
+ g_stds = ['gnu++98']
+ if mesonlib.version_compare(self.version, '>=15.0.0'):
+ c_stds += ['c++11', 'c++14']
+ g_stds += ['gnu++11']
+ if mesonlib.version_compare(self.version, '>=16.0.0'):
+ c_stds += ['c++17']
+ if mesonlib.version_compare(self.version, '>=17.0.0'):
+ g_stds += ['gnu++14']
+ opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none'),
+ 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
+ 'STL debug mode',
+ False)}
+ return opts
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['cpp_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ if options['cpp_debugstl'].value:
+ args.append('-D_GLIBCXX_DEBUG=1')
+ return args
+
+ def get_option_link_args(self, options):
+ return []
+
+ def get_compiler_check_args(self):
+ return self.get_no_optimization_args()
+
+ def has_multi_arguments(self, args, env):
+ return super(IntelCPPCompiler, self).has_multi_arguments(args + ['-diag-error', '10006'], env)
+
+
class FortranCompiler(Compiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
self.language = 'fortran'
@@ -2553,18 +2700,21 @@ class SunFortranCompiler(FortranCompiler):
def get_always_args(self):
return []
- def get_warn_args(self):
+ def get_warn_args(self, level):
return []
def get_module_outdir_args(self, path):
return ['-moddir=' + path]
-class IntelFortranCompiler(FortranCompiler):
+class IntelFortranCompiler(IntelCompiler, FortranCompiler):
std_warn_args = ['-warn', 'all']
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- self.file_suffixes = ('f', 'f90')
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
+ self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp')
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
+ # FIXME: Add support for OS X and Windows in detect_fortran_compiler so
+ # we are sent the type of compiler
+ IntelCompiler.__init__(self, ICC_STANDARD)
self.id = 'intel'
def get_module_outdir_args(self, path):
@@ -2626,15 +2776,13 @@ class NAGFortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-mdir', path]
- def get_always_args(self):
- return []
-
def get_warn_args(self, level):
return NAGFortranCompiler.std_warn_args
class VisualStudioLinker():
always_args = ['/NOLOGO']
+
def __init__(self, exelist):
self.exelist = exelist
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 2e5387d..48f5865 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -396,6 +396,10 @@ class Environment():
# everything else to stdout. Why? Lord only knows.
version = search_version(err)
return VisualStudioCCompiler([compiler], version, is_cross, exe_wrap)
+ if '(ICC)' in out:
+ # TODO: add microsoft add check OSX
+ inteltype = ICC_STANDARD
+ return IntelCCompiler(ccache + [compiler], version, inteltype, is_cross, exe_wrap)
errmsg = 'Unknown compiler(s): "' + ', '.join(compilers) + '"'
if popen_exceptions:
errmsg += '\nThe follow exceptions were encountered:'
@@ -525,6 +529,10 @@ class Environment():
if 'Microsoft' in out or 'Microsoft' in err:
version = search_version(err)
return VisualStudioCPPCompiler([compiler], version, is_cross, exe_wrap)
+ if '(ICC)' in out:
+ # TODO: add microsoft add check OSX
+ inteltype = ICC_STANDARD
+ return IntelCPPCompiler(ccache + [compiler], version, inteltype, is_cross, exe_wrap)
errmsg = 'Unknown compiler(s): "' + ', '.join(compilers) + '"'
if popen_exceptions:
errmsg += '\nThe follow exceptions were encountered:'
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index ac15401..ec82ec9 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -30,6 +30,7 @@ from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
from .interpreterbase import InterpreterObject, MutableInterpreterObject
import os, sys, shutil, uuid
+import re
import importlib
@@ -1139,7 +1140,8 @@ class MesonMain(InterpreterObject):
class Interpreter(InterpreterBase):
- def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects'):
+ def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects',
+ default_project_options=[]):
super().__init__(build.environment.get_source_dir(), subdir)
self.build = build
self.environment = build.environment
@@ -1147,12 +1149,7 @@ class Interpreter(InterpreterBase):
self.backend = backend
self.subproject = subproject
self.subproject_dir = subproject_dir
- option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
- if os.path.exists(option_file):
- oi = optinterpreter.OptionInterpreter(self.subproject, \
- self.build.environment.cmd_line_options.projectoptions)
- oi.process(option_file)
- self.build.environment.merge_options(oi.options)
+ self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
self.load_root_meson_file()
self.sanity_check_ast()
self.builtin.update({'meson': MesonMain(build, self)})
@@ -1161,6 +1158,7 @@ class Interpreter(InterpreterBase):
self.args_frozen = False
self.subprojects = {}
self.subproject_stack = []
+ self.default_project_options = default_project_options[:] # Passed from the outside, only used in subprojects.
self.build_func_dict()
self.parse_project()
self.builtin['build_machine'] = BuildMachine(self.coredata.compilers)
@@ -1207,6 +1205,7 @@ class Interpreter(InterpreterBase):
'add_project_arguments': self.func_add_project_arguments,
'add_global_link_arguments': self.func_add_global_link_arguments,
'add_project_link_arguments': self.func_add_project_link_arguments,
+ 'add_test_setup': self.func_add_test_setup,
'add_languages': self.func_add_languages,
'find_program': self.func_find_program,
'find_library': self.func_find_library,
@@ -1418,7 +1417,8 @@ class Interpreter(InterpreterBase):
os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
self.args_frozen = True
mlog.log('\nExecuting subproject ', mlog.bold(dirname), '.\n', sep='')
- subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir)
+ subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir,
+ mesonlib.stringlistify(kwargs.get('default_options', [])))
subi.subprojects = self.subprojects
subi.subproject_stack = self.subproject_stack + [dirname]
@@ -1488,19 +1488,53 @@ class Interpreter(InterpreterBase):
raise InterpreterException('All default options must be of type key=value.')
key, value = option.split('=', 1)
if coredata.is_builtin_option(key):
+ if self.subproject != '':
+ continue # Only the master project is allowed to set global options.
if not self.environment.had_argument_for(key):
self.coredata.set_builtin_option(key, value)
# If this was set on the command line, do not override.
else:
+ # Option values set with subproject() default_options override those
+ # set in project() default_options.
+ pref = key + '='
+ for i in self.default_project_options:
+ if i.startswith(pref):
+ option = i
+ break
+ # If we are in a subproject, add the subproject prefix to option
+ # name.
+ if self.subproject != '':
+ option = self.subproject + ':' + option
newoptions = [option] + self.environment.cmd_line_options.projectoptions
self.environment.cmd_line_options.projectoptions = newoptions
+ # Add options that are only in default_options.
+ for defopt in self.default_project_options:
+ key, value = defopt.split('=')
+ pref = key + '='
+ was_found = False
+ for i in default_options:
+ if i.startswith(pref):
+ was_found = True
+ break
+ if was_found:
+ break
+ defopt = self.subproject + ':' + defopt
+ newoptions = [defopt] + self.environment.cmd_line_options.projectoptions
+ self.environment.cmd_line_options.projectoptions = newoptions
@stringArgs
def func_project(self, node, args, kwargs):
+ if self.environment.first_invocation and ('default_options' in kwargs or \
+ len(self.default_project_options) > 0):
+ self.parse_default_options(kwargs['default_options'])
if not self.is_subproject():
self.build.project_name = args[0]
- if self.environment.first_invocation and 'default_options' in kwargs:
- self.parse_default_options(kwargs['default_options'])
+ if os.path.exists(self.option_file):
+ oi = optinterpreter.OptionInterpreter(self.subproject, \
+ self.build.environment.cmd_line_options.projectoptions,
+ )
+ oi.process(self.option_file)
+ self.build.environment.merge_options(oi.options)
if len(args) < 2:
raise InvalidArguments('Not enough arguments to project(). Needs at least the project name and one language')
self.active_projectname = args[0]
@@ -1766,7 +1800,12 @@ requirements use the version keyword argument instead.''')
dirname, varname = self.get_subproject_infos(kwargs)
# Try to execute the subproject
try:
- self.do_subproject(dirname, {})
+ sp_kwargs = {}
+ try:
+ sp_kwargs['default_options'] = kwargs['default_options']
+ except KeyError:
+ pass
+ self.do_subproject(dirname, sp_kwargs)
# Invalid code is always an error
except InvalidCode:
raise
@@ -1785,7 +1824,6 @@ requirements use the version keyword argument instead.''')
if not isinstance(dep, DependencyHolder):
raise InvalidCode('Fallback variable {!r} in the subproject {!r} is '
'not a dependency object.'.format(varname, dirname))
- return None
# Check if the version of the declared dependency matches what we want
if 'version' in kwargs:
wanted = kwargs['version']
@@ -1942,22 +1980,7 @@ requirements use the version keyword argument instead.''')
def func_test(self, node, args, kwargs):
self.add_test(node, args, kwargs, True)
- def add_test(self, node, args, kwargs, is_base_test):
- if len(args) != 2:
- raise InterpreterException('Incorrect number of arguments')
- if not isinstance(args[0], str):
- raise InterpreterException('First argument of test must be a string.')
- if not isinstance(args[1], (ExecutableHolder, JarHolder, ExternalProgramHolder)):
- raise InterpreterException('Second argument must be executable.')
- par = kwargs.get('is_parallel', True)
- if not isinstance(par, bool):
- raise InterpreterException('Keyword argument is_parallel must be a boolean.')
- cmd_args = kwargs.get('args', [])
- if not isinstance(cmd_args, list):
- cmd_args = [cmd_args]
- for i in cmd_args:
- if not isinstance(i, (str, mesonlib.File)):
- raise InterpreterException('Command line arguments must be strings')
+ def unpack_env_kwarg(self, kwargs):
envlist = kwargs.get('env', [])
if isinstance(envlist, EnvironmentVariablesHolder):
env = envlist.held_object
@@ -1974,8 +1997,25 @@ requirements use the version keyword argument instead.''')
if ' ' in k:
raise InterpreterException('Env var key must not have spaces in it.')
env[k] = val
- if not isinstance(envlist, list):
- envlist = [envlist]
+ return env
+
+ def add_test(self, node, args, kwargs, is_base_test):
+ if len(args) != 2:
+ raise InterpreterException('Incorrect number of arguments')
+ if not isinstance(args[0], str):
+ raise InterpreterException('First argument of test must be a string.')
+ if not isinstance(args[1], (ExecutableHolder, JarHolder, ExternalProgramHolder)):
+ raise InterpreterException('Second argument must be executable.')
+ par = kwargs.get('is_parallel', True)
+ if not isinstance(par, bool):
+ raise InterpreterException('Keyword argument is_parallel must be a boolean.')
+ cmd_args = kwargs.get('args', [])
+ if not isinstance(cmd_args, list):
+ cmd_args = [cmd_args]
+ for i in cmd_args:
+ if not isinstance(i, (str, mesonlib.File)):
+ raise InterpreterException('Command line arguments must be strings')
+ env = self.unpack_env_kwarg(kwargs)
should_fail = kwargs.get('should_fail', False)
if not isinstance(should_fail, bool):
raise InterpreterException('Keyword argument should_fail must be a boolean.')
@@ -2139,6 +2179,47 @@ requirements use the version keyword argument instead.''')
return i
@stringArgs
+ def func_add_test_setup(self, node, args, kwargs):
+ if len(args) != 1:
+ raise InterpreterException('Add_test_setup needs one argument for the setup name.')
+ setup_name = args[0]
+ if re.fullmatch('[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None:
+ raise InterpreterException('Setup name may only contain alphanumeric characters.')
+ try:
+ inp = kwargs.get('exe_wrapper', [])
+ if not isinstance(inp, list):
+ inp = [inp]
+ exe_wrapper = []
+ for i in inp:
+ if hasattr(i, 'held_object'):
+ i = i.held_object
+ if isinstance(i, str):
+ exe_wrapper.append(i)
+ elif isinstance(i, dependencies.ExternalProgram):
+ if not i.found():
+ raise InterpreterException('Tried to use non-found external executable.')
+ exe_wrapper += i.get_command()
+ else:
+ raise InterpreterException('Exe wrapper can only contain strings or external binaries.')
+ except KeyError:
+ exe_wrapper = None
+ gdb = kwargs.get('gdb', False)
+ if not isinstance(gdb, bool):
+ raise InterpreterException('Gdb option must be a boolean')
+ timeout_multiplier = kwargs.get('timeout_multiplier', 1)
+ if not isinstance(timeout_multiplier, int):
+ raise InterpreterException('Timeout multiplier must be a number.')
+ env = self.unpack_env_kwarg(kwargs)
+ setupobj = build.TestSetup(exe_wrapper=exe_wrapper,
+ gdb=gdb,
+ timeout_multiplier=timeout_multiplier,
+ env=env)
+ if self.subproject == '':
+ # Dunno what we should do with subprojects really. Let's start simple
+ # and just use the master project ones.
+ self.build.test_setups[setup_name] = setupobj
+
+ @stringArgs
def func_add_global_arguments(self, node, args, kwargs):
if self.subproject != '':
msg = 'Global arguments can not be set in subprojects because ' \
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
index 5ff14ff..4b4ae3d 100644
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -16,6 +16,7 @@ from os import path
from .. import coredata, mesonlib, build
from ..mesonlib import MesonException
import sys
+import shutil
PRESET_ARGS = {
'glib': [
@@ -63,6 +64,8 @@ class I18nModule:
def gettext(self, state, args, kwargs):
if len(args) != 1:
raise coredata.MesonException('Gettext requires one positional argument (package name).')
+ if not shutil.which('xgettext'):
+ raise coredata.MesonException('Can not do gettext because xgettext is not installed.')
packagename = args[0]
languages = mesonlib.stringlistify(kwargs.get('languages', []))
datadirs = mesonlib.stringlistify(kwargs.get('data_dirs', []))
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index ac23fe8..089eb2c 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -71,8 +71,15 @@ class OptionInterpreter:
def __init__(self, subproject, command_line_options):
self.options = {}
self.subproject = subproject
+ self.sbprefix = subproject + ':'
self.cmd_line_options = {}
for o in command_line_options:
+ if self.subproject != '': # Strip the beginning.
+ if not o.startswith(self.sbprefix):
+ continue
+ else:
+ if ':' in o:
+ continue
try:
(key, value) = o.split('=', 1)
except ValueError:
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index c9ee36c..193d5b6 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -220,7 +220,7 @@ class Elf(DataSizes):
soname = i
if i.d_tag == DT_STRTAB:
strtab = i
- else:
+ if soname is None or strtab is None:
print("This file does not have a soname")
return
self.bf.seek(strtab.val + soname.val)
diff --git a/mesontest.py b/mesontest.py
index ecf1b41..af4ae2a 100755
--- a/mesontest.py
+++ b/mesontest.py
@@ -69,7 +69,7 @@ parser.add_argument('--suite', default=None, dest='suite',
parser.add_argument('--no-stdsplit', default=True, dest='split', action='store_false',
help='Do not split stderr and stdout in test logs.')
parser.add_argument('--print-errorlogs', default=False, action='store_true',
- help="Whether to print faling tests' logs.")
+ help="Whether to print failing tests' logs.")
parser.add_argument('--benchmark', default=False, action='store_true',
help="Run benchmarks instead of tests.")
parser.add_argument('--logbase', default='testlog',
@@ -82,6 +82,8 @@ parser.add_argument('-t', '--timeout-multiplier', type=float, default=1.0,
help='Define a multiplier for test timeout, for example '
' when running tests in particular conditions they might take'
' more time to execute.')
+parser.add_argument('--setup', default=None, dest='setup',
+ help='Which test setup to use.')
parser.add_argument('args', nargs='*')
class TestRun():
@@ -101,9 +103,7 @@ class TestRun():
if self.cmd is None:
res += 'NONE\n'
else:
- res += "\n%s %s\n" % (' '.join(
- ["%s='%s'" % (k, v) for k, v in self.env.items()]),
- ' ' .join(self.cmd))
+ res += "%s%s\n" % (''.join(["%s='%s' " % (k, v) for k, v in self.env.items()]), ' ' .join(self.cmd))
if self.stdo:
res += '--- stdout ---\n'
res += self.stdo
@@ -149,8 +149,10 @@ class TestHarness:
def __init__(self, options):
self.options = options
self.collected_logs = []
- self.failed_tests = []
- self.error_count = 0
+ self.fail_count = 0
+ self.success_count = 0
+ self.skip_count = 0
+ self.timeout_count = 0
self.is_run = False
self.cant_rebuild = False
if self.options.benchmark:
@@ -180,7 +182,6 @@ class TestHarness:
return True
def run_single_test(self, wrap, test):
- failling = False
if test.fname[0].endswith('.jar'):
cmd = ['java', '-jar'] + test.fname
elif not test.is_cross and run_with_mono(test.fname[0]):
@@ -206,6 +207,7 @@ class TestHarness:
cmd = wrap + cmd + test.cmd_args
starttime = time.time()
child_env = os.environ.copy()
+ child_env.update(self.options.global_env.get_env(child_env))
if isinstance(test.env, build.EnvironmentVariables):
test.env = test.env.get_env(child_env)
@@ -255,21 +257,19 @@ class TestHarness:
stde = decode(stde)
if timed_out:
res = 'TIMEOUT'
- failling = True
+ self.timeout_count += 1
if p.returncode == GNU_SKIP_RETURNCODE:
res = 'SKIP'
- elif (not test.should_fail and p.returncode == 0) or \
- (test.should_fail and p.returncode != 0):
+ self.skip_count += 1
+ elif test.should_fail == bool(p.returncode):
res = 'OK'
+ self.success_count += 1
else:
res = 'FAIL'
- failling = True
+ self.fail_count += 1
returncode = p.returncode
result = TestRun(res, returncode, test.should_fail, duration, stdo, stde, cmd, test.env)
- if failling:
- self.failed_tests.append(result)
-
return result
def print_stats(self, numlen, tests, name, result, i, logfile, jsonlogfile):
@@ -283,20 +283,21 @@ class TestHarness:
result_str += "\n\n" + result.get_log()
if (result.returncode != GNU_SKIP_RETURNCODE) and \
(result.returncode != 0) != result.should_fail:
- self.error_count += 1
if self.options.print_errorlogs:
self.collected_logs.append(result_str)
- logfile.write(result_str)
- write_json_log(jsonlogfile, name, result)
-
- def doit(self):
- if self.is_run:
- raise RuntimeError('Test harness object can only be used once.')
- if not os.path.isfile(self.datafile):
- print('Test data file. Probably this means that you did not run this in the build directory.')
- return 1
- self.is_run = True
- logfilename = self.run_tests(self.options.logbase)
+ if logfile:
+ logfile.write(result_str)
+ if jsonlogfile:
+ write_json_log(jsonlogfile, name, result)
+
+ def print_summary(self, logfile, jsonlogfile):
+ msg = 'Test summary: %d OK, %d FAIL, %d SKIP, %d TIMEOUT' \
+ % (self.success_count, self.fail_count, self.skip_count, self.timeout_count)
+ print(msg)
+ if logfile:
+ logfile.write(msg)
+
+ def print_collected_logs(self):
if len(self.collected_logs) > 0:
if len(self.collected_logs) > 10:
print('\nThe output from 10 first failed tests:\n')
@@ -304,54 +305,100 @@ class TestHarness:
print('\nThe output from the failed tests:\n')
for log in self.collected_logs[:10]:
lines = log.splitlines()
- if len(lines) > 100:
- print(lines[0])
+ if len(lines) > 104:
+ print('\n'.join(lines[0:4]))
print('--- Listing only the last 100 lines from a long log. ---')
- lines = lines[-99:]
+ lines = lines[-100:]
for line in lines:
print(line)
- print('Full log written to %s.' % logfilename)
- return self.error_count
+
+ def doit(self):
+ if self.is_run:
+ raise RuntimeError('Test harness object can only be used once.')
+ if not os.path.isfile(self.datafile):
+ print('Test data file. Probably this means that you did not run this in the build directory.')
+ return 1
+ self.is_run = True
+ tests = self.get_tests()
+ if not tests:
+ return 0
+ self.run_tests(tests)
+ return self.fail_count
def get_tests(self):
with open(self.datafile, 'rb') as f:
tests = pickle.load(f)
+
+ if not tests:
+ print('No tests defined.')
+ return []
+
+ if self.options.suite:
+ tests = [t for t in tests if self.options.suite in t.suite]
+
+ if self.options.args:
+ tests = [t for t in tests if t.name in self.options.args]
+
+ if not tests:
+ print('No suitable tests defined.')
+ return []
+
for test in tests:
test.rebuilt = False
return tests
- def run_tests(self, log_base):
- logfile_base = os.path.join(self.options.wd, 'meson-logs', log_base)
+ def open_log_files(self):
+ if not self.options.logbase or self.options.verbose:
+ return (None, None, None, None)
+
+ logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase)
+
if self.options.wrapper is None:
- wrap = []
logfilename = logfile_base + '.txt'
jsonlogfilename = logfile_base + '.json'
else:
- wrap = self.options.wrapper.split()
- namebase = wrap[0]
+ namebase = os.path.split(self.get_wrapper()[0])[1]
logfilename = logfile_base + '-' + namebase.replace(' ', '_') + '.txt'
jsonlogfilename = logfile_base + '-' + namebase.replace(' ', '_') + '.json'
- tests = self.get_tests()
- if len(tests) == 0:
- print('No tests defined.')
- return
- numlen = len('%d' % len(tests))
- executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes)
- futures = []
- filtered_tests = filter_tests(self.options.suite, tests)
-
- jsonlogfile = None
- logfile = None
+
+ jsonlogfile = open(jsonlogfilename, 'w')
+ logfile = open(logfilename, 'w')
+
+ logfile.write('Log of Meson test suite run on %s.\n\n'
+ % datetime.datetime.now().isoformat())
+
+ return (logfile, logfilename, jsonlogfile, jsonlogfilename)
+
+ def get_wrapper(self):
+ wrap = []
+ if self.options.gdb:
+ wrap = ['gdb', '--quiet', '--nh']
+ if self.options.repeat > 1:
+ wrap += ['-ex', 'run', '-ex', 'quit']
+ elif self.options.wrapper:
+ if isinstance(self.options.wrapper, str):
+ wrap = self.options.wrapper.split()
+ else:
+ wrap = self.options.wrapper
+ assert(isinstance(wrap, list))
+ return wrap
+
+ def get_suites(self, tests):
+ return set([test.suite[0] for test in tests])
+
+ def run_tests(self, tests):
try:
- if not self.options.verbose:
- jsonlogfile = open(jsonlogfilename, 'w')
- logfile = open(logfilename, 'w')
- logfile.write('Log of Meson test suite run on %s.\n\n' %
- datetime.datetime.now().isoformat())
+ executor = None
+ logfile = None
+ jsonlogfile = None
+ futures = []
+ numlen = len('%d' % len(tests))
+ (logfile, logfilename, jsonlogfile, jsonlogfilename) = self.open_log_files()
+ wrap = self.get_wrapper()
for i in range(self.options.repeat):
- for i, test in enumerate(filtered_tests):
+ for i, test in enumerate(tests):
if test.suite[0] == '':
visible_name = test.name
else:
@@ -360,112 +407,113 @@ class TestHarness:
else:
visible_name = test.suite[0] + ' / ' + test.name
- if not test.is_parallel:
- self.drain_futures(futures)
+ if self.options.gdb:
+ test.timeout = None
+ if len(test.cmd_args):
+ wrap.append('--args')
+
+ if not test.is_parallel or self.options.gdb:
+ self.drain_futures(futures, logfile, jsonlogfile)
futures = []
res = self.run_single_test(wrap, test)
- if not self.options.verbose:
- self.print_stats(numlen, filtered_tests, visible_name, res, i,
- logfile, jsonlogfile)
+ self.print_stats(numlen, tests, visible_name, res, i, logfile, jsonlogfile)
else:
+ if not executor:
+ executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes)
f = executor.submit(self.run_single_test, wrap, test)
- if not self.options.verbose:
- futures.append((f, numlen, filtered_tests, visible_name, i,
- logfile, jsonlogfile))
+ futures.append((f, numlen, tests, visible_name, i, logfile, jsonlogfile))
+ if self.options.repeat > 1 and self.fail_count:
+ break
+ if self.options.repeat > 1 and self.fail_count:
+ break
+
self.drain_futures(futures, logfile, jsonlogfile)
+ self.print_summary(logfile, jsonlogfile)
+ self.print_collected_logs()
+
+ if logfilename:
+ print('Full log written to %s.' % logfilename)
finally:
if jsonlogfile:
jsonlogfile.close()
if logfile:
logfile.close()
- return logfilename
-
-
def drain_futures(self, futures, logfile, jsonlogfile):
for i in futures:
(result, numlen, tests, name, i, logfile, jsonlogfile) = i
- if self.options.repeat > 1 and self.failed_tests:
+ if self.options.repeat > 1 and self.fail_count:
result.cancel()
- elif not self.options.verbose:
- self.print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile)
- else:
+ if self.options.verbose:
result.result()
-
- if self.options.repeat > 1 and self.failed_tests:
- if not self.options.verbose:
- for res in self.failed_tests:
- print('Test failed:\n\n-- stdout --\n')
- print(res.stdo)
- print('\n-- stderr --\n')
- print(res.stde)
- return 1
-
- return
+ self.print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile)
def run_special(self):
'Tests run by the user, usually something like "under gdb 1000 times".'
if self.is_run:
raise RuntimeError('Can not use run_special after a full run.')
- if self.options.wrapper is not None:
- wrap = self.options.wrapper.split(' ')
- else:
- wrap = []
- if self.options.gdb and len(wrap) > 0:
- print('Can not specify both a wrapper and gdb.')
- return 1
if os.path.isfile('build.ninja'):
subprocess.check_call([environment.detect_ninja(), 'all'])
tests = self.get_tests()
- if self.options.list:
- for i in tests:
- print(i.name)
- return 0
- for t in tests:
- if t.name in self.options.args:
- for i in range(self.options.repeat):
- print('Running: %s %d/%d' % (t.name, i + 1, self.options.repeat))
- if self.options.gdb:
- wrap = ['gdb', '--quiet']
- if len(t.cmd_args) > 0:
- wrap.append('--args')
- if self.options.repeat > 1:
- # The user wants to debug interactively, so no timeout.
- t.timeout = None
- wrap += ['-ex', 'run', '-ex', 'quit']
-
- res = self.run_single_test(wrap, t)
- else:
- res = self.run_single_test(wrap, t)
- if (res.returncode == 0 and res.should_fail) or \
- (res.returncode != 0 and not res.should_fail):
- if not self.options.verbose:
- print('Test failed:\n\n-- stdout --\n')
- print(res.stdo)
- print('\n-- stderr --\n')
- print(res.stde)
- return 1
- return 0
+ self.run_tests(tests)
+ return self.fail_count
-def filter_tests(suite, tests):
- if suite is None:
- return tests
- return [x for x in tests if suite in x.suite]
+def list_tests(th):
+ tests = th.get_tests()
+ print_suites = True if len(th.get_suites(tests)) != 1 else False
+ for i in tests:
+ if print_suites:
+ print("%s / %s" % (i.suite[0], i.name))
+ else:
+ print("%s" % i.name)
+
+
+def merge_suite_options(options):
+ buildfile = os.path.join(options.wd, 'meson-private/build.dat')
+ with open(buildfile, 'rb') as f:
+ build = pickle.load(f)
+ setups = build.test_setups
+ if options.setup not in setups:
+ sys.exit('Unknown test setup: %s' % options.setup)
+ current = setups[options.setup]
+ if not options.gdb:
+ options.gdb = current.gdb
+ if options.timeout_multiplier is None:
+ options.timeout_multiplier = current.timeout_multiplier
+# if options.env is None:
+# options.env = current.env # FIXME, should probably merge options here.
+ if options.wrapper is not None and current.exe_wrapper is not None:
+ sys.exit('Conflict: both test setup and command line specify an exe wrapper.')
+ if options.wrapper is None:
+ options.wrapper = current.exe_wrapper
+ return current.env
def run(args):
options = parser.parse_args(args)
+
if options.benchmark:
options.num_processes = 1
+ if options.setup is not None:
+ global_env = merge_suite_options(options)
+ else:
+ global_env = build.EnvironmentVariables()
+
+ setattr(options, 'global_env', global_env)
+
if options.gdb:
options.verbose = True
+ if options.wrapper:
+ print('Must not specify both a wrapper and gdb at the same time.')
+ return 1
options.wd = os.path.abspath(options.wd)
th = TestHarness(options)
if options.list:
- return th.run_special()
+ list_tests(th)
+ return 0
if not options.no_rebuild:
if not th.rebuild_all():
sys.exit(-1)
diff --git a/run_project_tests.py b/run_project_tests.py
index 07e7ddb..18988fb 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -58,9 +58,15 @@ class AutoDeletedDir():
try:
shutil.rmtree(self.dir)
return
- except OSError:
+ # Sometimes we get: ValueError: I/O operation on closed file.
+ except ValueError:
+ return
+ # Deleting can raise OSError or PermissionError on Windows
+ # (most likely because of anti-virus locking the file)
+ except (OSError, PermissionError):
if i == retries - 1:
- raise
+ mlog.warning('Could not delete temporary directory.')
+ return
time.sleep(0.1 * (2**i))
failing_logs = []
@@ -554,7 +560,7 @@ if __name__ == '__main__':
print('\nTotal passed tests:', passing_tests)
print('Total failed tests:', failing_tests)
print('Total skipped tests:', skipped_tests)
- if failing_tests > 0 and ('TRAVIS' in os.environ or 'APPVEYOR' in os.environ):
+ if failing_tests > 0:
print('\nMesonlogs of failing tests\n')
for l in failing_logs:
print(l, '\n')
diff --git a/run_unittests.py b/run_unittests.py
index 8f1f155..d1c192f 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -19,7 +19,7 @@ import re, json
import tempfile
from glob import glob
import mesonbuild.environment
-from mesonbuild.environment import detect_ninja
+from mesonbuild.environment import detect_ninja, Environment
from mesonbuild.dependencies import PkgConfigDependency
def get_soname(fname):
@@ -33,6 +33,12 @@ def get_soname(fname):
return m.group(1)
raise RuntimeError('Could not determine soname:\n\n' + raw_out)
+def get_fake_options():
+ import argparse
+ opts = argparse.Namespace()
+ opts.cross_file = None
+ return opts
+
class FakeEnvironment(object):
def __init__(self):
self.cross_info = None
@@ -57,12 +63,14 @@ class LinuxlikeTests(unittest.TestCase):
src_root = os.path.dirname(__file__)
src_root = os.path.join(os.getcwd(), src_root)
self.builddir = tempfile.mkdtemp()
+ self.logdir = os.path.join(self.builddir, 'meson-logs')
self.prefix = '/usr'
self.libdir = os.path.join(self.prefix, 'lib')
self.installdir = os.path.join(self.builddir, 'install')
self.meson_command = [sys.executable, os.path.join(src_root, 'meson.py')]
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]
self.ninja_command = [detect_ninja(), '-C', self.builddir]
self.common_test_dir = os.path.join(src_root, 'test cases/common')
self.vala_test_dir = os.path.join(src_root, 'test cases/vala')
@@ -79,15 +87,21 @@ class LinuxlikeTests(unittest.TestCase):
def _run(self, command):
self.output += subprocess.check_output(command, env=os.environ.copy())
- def init(self, srcdir):
+ def init(self, srcdir, extra_args=None):
+ if extra_args is None:
+ extra_args = []
args = [srcdir, self.builddir,
'--prefix', self.prefix,
'--libdir', self.libdir]
- self._run(self.meson_command + args)
+ self._run(self.meson_command + args + extra_args)
+ self.privatedir = os.path.join(self.builddir, 'meson-private')
def build(self):
self._run(self.ninja_command)
+ def run_tests(self):
+ self._run(self.ninja_command + ['test'])
+
def install(self):
os.environ['DESTDIR'] = self.installdir
self._run(self.ninja_command + ['install'])
@@ -101,6 +115,9 @@ class LinuxlikeTests(unittest.TestCase):
def setconf(self, arg):
self._run(self.mconf_command + [arg, self.builddir])
+ def wipe(self):
+ shutil.rmtree(self.builddir)
+
def get_compdb(self):
with open(os.path.join(self.builddir, 'compile_commands.json')) as ifile:
return json.load(ifile)
@@ -161,7 +178,7 @@ class LinuxlikeTests(unittest.TestCase):
testdir = os.path.join(self.common_test_dir, '3 static')
self.init(testdir)
compdb = self.get_compdb()
- self.assertTrue('-fPIC' in compdb[0]['command'])
+ self.assertIn('-fPIC', compdb[0]['command'])
# This is needed to increase the difference between build.ninja's
# timestamp and coredata.dat's timestamp due to a Ninja bug.
# https://github.com/ninja-build/ninja/issues/371
@@ -170,7 +187,7 @@ class LinuxlikeTests(unittest.TestCase):
# Regenerate build
self.build()
compdb = self.get_compdb()
- self.assertTrue('-fPIC' not in compdb[0]['command'])
+ self.assertNotIn('-fPIC', compdb[0]['command'])
def test_pkgconfig_gen(self):
'''
@@ -183,11 +200,11 @@ class LinuxlikeTests(unittest.TestCase):
self.init(testdir)
env = FakeEnvironment()
kwargs = {'required': True, 'silent': True}
- os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(self.builddir, 'meson-private')
+ os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
simple_dep = PkgConfigDependency('libfoo', env, kwargs)
self.assertTrue(simple_dep.found())
self.assertEqual(simple_dep.get_version(), '1.0')
- self.assertTrue('-lfoo' in simple_dep.get_link_args())
+ self.assertIn('-lfoo', simple_dep.get_link_args())
def test_vala_c_warnings(self):
'''
@@ -212,15 +229,15 @@ class LinuxlikeTests(unittest.TestCase):
self.assertIsNotNone(vala_command)
self.assertIsNotNone(c_command)
# -w suppresses all warnings, should be there in Vala but not in C
- self.assertTrue('-w' in vala_command)
- self.assertFalse('-w' in c_command)
+ self.assertIn("'-w'", vala_command)
+ self.assertNotIn("'-w'", c_command)
# -Wall enables all warnings, should be there in C but not in Vala
- self.assertFalse('-Wall' in vala_command)
- self.assertTrue('-Wall' in c_command)
+ self.assertNotIn("'-Wall'", vala_command)
+ self.assertIn("'-Wall'", c_command)
# -Werror converts warnings to errors, should always be there since it's
# injected by an unrelated piece of code and the project has werror=true
- self.assertTrue('-Werror' in vala_command)
- self.assertTrue('-Werror' in c_command)
+ self.assertIn("'-Werror'", vala_command)
+ self.assertIn("'-Werror'", c_command)
def test_static_compile_order(self):
'''
@@ -374,6 +391,86 @@ class LinuxlikeTests(unittest.TestCase):
self.uninstall()
self.assertFalse(os.path.exists(exename))
+ def test_custom_target_exe_data_deterministic(self):
+ testdir = os.path.join(self.common_test_dir, '117 custom target capture')
+ self.init(testdir)
+ meson_exe_dat1 = glob(os.path.join(self.privatedir, 'meson_exe*.dat'))
+ self.wipe()
+ self.init(testdir)
+ meson_exe_dat2 = glob(os.path.join(self.privatedir, 'meson_exe*.dat'))
+ self.assertListEqual(meson_exe_dat1, meson_exe_dat2)
+
+ def test_testsetups(self):
+ if not shutil.which('valgrind'):
+ raise unittest.SkipTest('Valgrind not installed.')
+ testdir = os.path.join(self.unit_test_dir, '2 testsetups')
+ self.init(testdir)
+ self.build()
+ self.run_tests()
+ with open(os.path.join(self.logdir, 'testlog.txt')) as f:
+ basic_log = f.read()
+ self.assertRaises(subprocess.CalledProcessError,
+ self._run, self.mtest_command + ['--setup=valgrind'])
+ with open(os.path.join(self.logdir, 'testlog-valgrind.txt')) as f:
+ vg_log = f.read()
+ self.assertFalse('TEST_ENV is set' in basic_log)
+ self.assertFalse('Memcheck' in basic_log)
+ self.assertTrue('TEST_ENV is set' in vg_log)
+ self.assertTrue('Memcheck' in vg_log)
+
+ def _test_stds_impl(self, testdir, compiler, p):
+ lang_std = p + '_std'
+ # Check that all the listed -std=xxx options for this compiler work
+ # just fine when used
+ for v in compiler.get_options()[lang_std].choices:
+ std_opt = '{}={}'.format(lang_std, v)
+ self.init(testdir, ['-D' + std_opt])
+ cmd = self.get_compdb()[0]['command']
+ if v != 'none':
+ cmd_std = "'-std={}'".format(v)
+ self.assertIn(cmd_std, cmd)
+ try:
+ self.build()
+ except:
+ print('{} was {!r}'.format(lang_std, v))
+ raise
+ self.wipe()
+ # Check that an invalid std option in CFLAGS/CPPFLAGS fails
+ # Needed because by default ICC ignores invalid options
+ 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)):
+ self.build()
+
+ def test_compiler_c_stds(self):
+ '''
+ Test that C stds specified for this compiler can all be used. Can't be
+ an ordinary test because it requires passing options to meson.
+ '''
+ testdir = os.path.join(self.common_test_dir, '1 trivial')
+ env = Environment(testdir, self.builddir, self.meson_command,
+ get_fake_options(), [])
+ cc = env.detect_c_compiler(False)
+ self._test_stds_impl(testdir, cc, 'c')
+
+ def test_compiler_cpp_stds(self):
+ '''
+ Test that C++ stds specified for this compiler can all be used. Can't
+ be an ordinary test because it requires passing options to meson.
+ '''
+ testdir = os.path.join(self.common_test_dir, '2 cpp')
+ env = Environment(testdir, self.builddir, self.meson_command,
+ get_fake_options(), [])
+ cpp = env.detect_cpp_compiler(False)
+ self._test_stds_impl(testdir, cpp, 'cpp')
+
+
class RewriterTests(unittest.TestCase):
def setUp(self):
@@ -432,5 +529,6 @@ class RewriterTests(unittest.TestCase):
self.assertEqual(top, self.read_contents('meson.build'))
self.assertEqual(s2, self.read_contents('sub2/meson.build'))
+
if __name__ == '__main__':
unittest.main()
diff --git a/test cases/common/1 trivial/meson.build b/test cases/common/1 trivial/meson.build
index 1f7b375..a93de75 100644
--- a/test cases/common/1 trivial/meson.build
+++ b/test cases/common/1 trivial/meson.build
@@ -6,6 +6,11 @@ project('trivial test',
#this is a comment
sources = 'trivial.c'
+if meson.get_compiler('c').get_id() == 'intel'
+ # Error out if the -std=xxx option is incorrect
+ add_project_arguments('-diag-error', '10159', language : 'c')
+endif
+
exe = executable('trivialprog', sources : sources)
test('runtest', exe) # This is a comment
diff --git a/test cases/common/132 dependency file generation/main .c b/test cases/common/132 dependency file generation/main .c
new file mode 100644
index 0000000..0fb4389
--- /dev/null
+++ b/test cases/common/132 dependency file generation/main .c
@@ -0,0 +1,3 @@
+int main(int argc, char *argv[]) {
+ return 0;
+}
diff --git a/test cases/common/132 dependency file generation/meson.build b/test cases/common/132 dependency file generation/meson.build
new file mode 100644
index 0000000..dcfdcd9
--- /dev/null
+++ b/test cases/common/132 dependency file generation/meson.build
@@ -0,0 +1,12 @@
+project('dep file gen', 'c')
+
+cc_id = meson.get_compiler('c').get_id()
+if cc_id == 'intel'
+ # ICC does not escape spaces in paths in the dependency file, so Ninja
+ # (correctly) thinks that the rule has multiple outputs and errors out:
+ # 'depfile has multiple output paths'
+ error('MESON_SKIP_TEST: Skipping test with Intel compiler because it generates broken dependency files')
+endif
+
+e = executable('main file', 'main .c')
+test('test it', e)
diff --git a/test cases/common/2 cpp/meson.build b/test cases/common/2 cpp/meson.build
index 9c6f71a..6398382 100644
--- a/test cases/common/2 cpp/meson.build
+++ b/test cases/common/2 cpp/meson.build
@@ -1,3 +1,9 @@
project('c++ test', 'cpp')
+
+if meson.get_compiler('cpp').get_id() == 'intel'
+ # Error out if the -std=xxx option is incorrect
+ add_project_arguments('-diag-error', '10159', language : 'cpp')
+endif
+
exe = executable('trivialprog', 'trivial.cc', extra_files : 'something.txt')
test('runtest', exe)
diff --git a/test cases/common/25 object extraction/meson.build b/test cases/common/25 object extraction/meson.build
index c76b0db..d99ec84 100644
--- a/test cases/common/25 object extraction/meson.build
+++ b/test cases/common/25 object extraction/meson.build
@@ -9,8 +9,8 @@ else
obj1 = lib1.extract_objects('src/lib.c')
obj2 = lib2.extract_objects(['lib.c'])
- e1 = executable('main 1', 'main.c', objects : obj1)
- e2 = executable('main 2', 'main.c', objects : obj2)
+ e1 = executable('main1', 'main.c', objects : obj1)
+ e2 = executable('main2', 'main.c', objects : obj2)
test('extraction test 1', e1)
test('extraction test 2', e2)
diff --git a/test cases/common/94 default options/meson.build b/test cases/common/94 default options/meson.build
index a718bcc..a9176e0 100644
--- a/test cases/common/94 default options/meson.build
+++ b/test cases/common/94 default options/meson.build
@@ -1,20 +1,20 @@
project('default options', 'cpp', 'c', default_options : [
'buildtype=debugoptimized',
- 'cpp_std=c++03',
+ 'cpp_std=c++11',
'cpp_eh=none',
'warning_level=3',
])
-cpp = meson.get_compiler('cpp')
+cpp_id = meson.get_compiler('cpp').get_id()
assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.')
-if cpp.get_id() == 'msvc'
+if cpp_id == 'msvc'
cpp_eh = get_option('cpp_eh')
assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"')
else
cpp_std = get_option('cpp_std')
- assert(cpp_std == 'c++03', 'C++ std value is "' + cpp_std + '" instead of c++03.')
+ assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.')
endif
w_level = get_option('warning_level')
diff --git a/test cases/d/3 shared library/meson.build b/test cases/d/3 shared library/meson.build
index 5dae66b..1f45109 100644
--- a/test cases/d/3 shared library/meson.build
+++ b/test cases/d/3 shared library/meson.build
@@ -1,12 +1,9 @@
project('D Shared Library', 'd')
-if meson.get_compiler('d').get_id() != 'gcc'
-
- ldyn = shared_library('stuff', 'libstuff.d', install : true)
- ed = executable('app_d', 'app.d', link_with : ldyn, install : true)
- test('linktest_dyn', ed)
-
-else
- message('GDC can not build shared libraries. Test skipped.')
- install_data('no-installed-files', install_dir : '')
+if meson.get_compiler('d').get_id() == 'gcc'
+ error('MESON_SKIP_TEST: GDC can not build shared libraries')
endif
+
+ldyn = shared_library('stuff', 'libstuff.d', install : true)
+ed = executable('app_d', 'app.d', link_with : ldyn, install : true)
+test('linktest_dyn', ed)
diff --git a/test cases/d/3 shared library/no-installed-files b/test cases/d/3 shared library/no-installed-files
deleted file mode 100644
index e69de29..0000000
--- a/test cases/d/3 shared library/no-installed-files
+++ /dev/null
diff --git a/test cases/d/4 library versions/meson.build b/test cases/d/4 library versions/meson.build
index 26cc38a..f680651 100644
--- a/test cases/d/4 library versions/meson.build
+++ b/test cases/d/4 library versions/meson.build
@@ -1,25 +1,22 @@
project('D library versions', 'd')
if meson.get_compiler('d').get_id() == 'gcc'
- message('GDC can not build shared libraries. Test skipped.')
- install_data('no-installed-files', install_dir : '')
-else
-
- shared_library('some', 'lib.d',
- version : '1.2.3',
- soversion : '0',
- install : true)
+ error('MESON_SKIP_TEST: GDC can not build shared libraries')
+endif
- shared_library('noversion', 'lib.d',
- install : true)
+shared_library('some', 'lib.d',
+ version : '1.2.3',
+ soversion : '0',
+ install : true)
- shared_library('onlyversion', 'lib.d',
- version : '1.4.5',
- install : true)
+shared_library('noversion', 'lib.d',
+ install : true)
- shared_library('onlysoversion', 'lib.d',
- # Also test that int soversion is acceptable
- soversion : 5,
- install : true)
+shared_library('onlyversion', 'lib.d',
+ version : '1.4.5',
+ install : true)
-endif
+shared_library('onlysoversion', 'lib.d',
+ # Also test that int soversion is acceptable
+ soversion : 5,
+ install : true)
diff --git a/test cases/d/4 library versions/no-installed-files b/test cases/d/4 library versions/no-installed-files
deleted file mode 100644
index e69de29..0000000
--- a/test cases/d/4 library versions/no-installed-files
+++ /dev/null
diff --git a/test cases/failing build/1 vala c werror/unused-var.c b/test cases/failing build/1 vala c werror/unused-var.c
index e11d64c..6b85078 100644
--- a/test cases/failing build/1 vala c werror/unused-var.c
+++ b/test cases/failing build/1 vala c werror/unused-var.c
@@ -1,3 +1,5 @@
+#warning "something"
+
int
somelib(void)
{
diff --git a/test cases/fortran/1 basic/meson.build b/test cases/fortran/1 basic/meson.build
index 9c40951..833a177 100644
--- a/test cases/fortran/1 basic/meson.build
+++ b/test cases/fortran/1 basic/meson.build
@@ -2,6 +2,6 @@ project('simple fortran', 'fortran')
add_global_arguments('-fbounds-check', language : 'fortran')
-e = executable('simple', 'simple.f95',
+e = executable('simple', 'simple.f90',
fortran_args : '-ffree-form')
test('Simple Fortran', e)
diff --git a/test cases/fortran/1 basic/simple.f95 b/test cases/fortran/1 basic/simple.f90
index e0fb1d8..e0fb1d8 100644
--- a/test cases/fortran/1 basic/simple.f95
+++ b/test cases/fortran/1 basic/simple.f90
diff --git a/test cases/fortran/2 modules/meson.build b/test cases/fortran/2 modules/meson.build
index 0087c26..030f255 100644
--- a/test cases/fortran/2 modules/meson.build
+++ b/test cases/fortran/2 modules/meson.build
@@ -1,4 +1,4 @@
project('modules', 'fortran')
-e = executable('modprog', 'stuff.f95', 'prog.f95')
+e = executable('modprog', 'stuff.f90', 'prog.f90')
test('moduletest', e)
diff --git a/test cases/fortran/2 modules/prog.f95 b/test cases/fortran/2 modules/prog.f90
index c3998cc..c3998cc 100644
--- a/test cases/fortran/2 modules/prog.f95
+++ b/test cases/fortran/2 modules/prog.f90
diff --git a/test cases/fortran/2 modules/stuff.f95 b/test cases/fortran/2 modules/stuff.f90
index 4a6399b..4a6399b 100644
--- a/test cases/fortran/2 modules/stuff.f95
+++ b/test cases/fortran/2 modules/stuff.f90
diff --git a/test cases/fortran/5 static/main.f95 b/test cases/fortran/5 static/main.f90
index dc6454c..dc6454c 100644
--- a/test cases/fortran/5 static/main.f95
+++ b/test cases/fortran/5 static/main.f90
diff --git a/test cases/fortran/5 static/meson.build b/test cases/fortran/5 static/meson.build
index d6f922b..bd74a29 100644
--- a/test cases/fortran/5 static/meson.build
+++ b/test cases/fortran/5 static/meson.build
@@ -1,5 +1,5 @@
project('try-static-library', 'fortran')
-static_hello = static_library('static_hello', 'static_hello.f95')
+static_hello = static_library('static_hello', 'static_hello.f90')
-executable('test_exe', 'main.f95', link_with : static_hello)
+executable('test_exe', 'main.f90', link_with : static_hello)
diff --git a/test cases/fortran/5 static/static_hello.f95 b/test cases/fortran/5 static/static_hello.f90
index 63415b0..63415b0 100644
--- a/test cases/fortran/5 static/static_hello.f95
+++ b/test cases/fortran/5 static/static_hello.f90
diff --git a/test cases/fortran/6 dynamic/dynamic.f95 b/test cases/fortran/6 dynamic/dynamic.f90
index e78a406..e78a406 100644
--- a/test cases/fortran/6 dynamic/dynamic.f95
+++ b/test cases/fortran/6 dynamic/dynamic.f90
diff --git a/test cases/fortran/6 dynamic/main.f95 b/test cases/fortran/6 dynamic/main.f90
index cb3a53f..cb3a53f 100644
--- a/test cases/fortran/6 dynamic/main.f95
+++ b/test cases/fortran/6 dynamic/main.f90
diff --git a/test cases/fortran/6 dynamic/meson.build b/test cases/fortran/6 dynamic/meson.build
index 53edaf6..c791dac 100644
--- a/test cases/fortran/6 dynamic/meson.build
+++ b/test cases/fortran/6 dynamic/meson.build
@@ -1,4 +1,4 @@
project('dynamic_fortran', 'fortran')
-dynamic = shared_library('dynamic', 'dynamic.f95')
-executable('test_exe', 'main.f95', link_with : dynamic)
+dynamic = shared_library('dynamic', 'dynamic.f90')
+executable('test_exe', 'main.f90', link_with : dynamic)
diff --git a/test cases/frameworks/11 gir subproject/gir/meson.build b/test cases/frameworks/11 gir subproject/gir/meson.build
index e92c641..48e0a47 100644
--- a/test cases/frameworks/11 gir subproject/gir/meson.build
+++ b/test cases/frameworks/11 gir subproject/gir/meson.build
@@ -28,8 +28,10 @@ gnome.generate_gir(
message('TEST: ' + girsubproject.outdir())
+envdata = environment()
+envdata.append('GI_TYPELIB_PATH', girsubproject.outdir(), 'subprojects/mesongir', separator : ':')
+envdata.append('LD_LIBRARY_PATH', girsubproject.outdir(), 'subprojects/mesongir')
+
test('gobject introspection/subproject/c', girexe)
test('gobject introspection/subproject/py', find_program('prog.py'),
- env : ['GI_TYPELIB_PATH=' + girsubproject.outdir() + ':subprojects/mesongir',
- 'LD_LIBRARY_PATH=' + girsubproject.outdir() + ':subprojects/mesongir',
- ])
+ env : envdata)
diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build
index beddc81..f3a4534 100644
--- a/test cases/frameworks/7 gnome/gir/meson.build
+++ b/test cases/frameworks/7 gnome/gir/meson.build
@@ -33,7 +33,8 @@ gnome.generate_gir(
test('gobject introspection/c', girexe)
gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir()])
+envdata = environment()
+envdata.append('GI_TYPELIB_PATH', gir_paths, separator : ':')
+envdata.append('LD_LIBRARY_PATH', gir_paths)
test('gobject introspection/py', find_program('prog.py'),
- env : ['GI_TYPELIB_PATH=' + gir_paths,
- 'LD_LIBRARY_PATH=' + gir_paths,
- ])
+ env : envdata)
diff --git a/test cases/frameworks/7 gnome/meson.build b/test cases/frameworks/7 gnome/meson.build
index a771e71..c75c049 100644
--- a/test cases/frameworks/7 gnome/meson.build
+++ b/test cases/frameworks/7 gnome/meson.build
@@ -1,5 +1,14 @@
project('gobject-introspection', 'c')
+cc = meson.get_compiler('c')
+
+add_global_arguments('-DMESON_TEST', language : 'c')
+if cc.get_id() == 'intel'
+ # Ignore invalid GCC pragma warnings from glib
+ # https://bugzilla.gnome.org/show_bug.cgi?id=776562
+ add_global_arguments('-wd2282', language : 'c')
+endif
+
gnome = import('gnome')
gio = dependency('gio-2.0')
giounix = dependency('gio-unix-2.0')
@@ -7,7 +16,6 @@ glib = dependency('glib-2.0')
gobj = dependency('gobject-2.0')
gir = dependency('gobject-introspection-1.0')
gmod = dependency('gmodule-2.0')
-add_global_arguments('-DMESON_TEST', language : 'c')
subdir('resources-data')
subdir('resources')
diff --git a/test cases/unit/2 testsetups/buggy.c b/test cases/unit/2 testsetups/buggy.c
new file mode 100644
index 0000000..5d20a24
--- /dev/null
+++ b/test cases/unit/2 testsetups/buggy.c
@@ -0,0 +1,14 @@
+#include<stdio.h>
+#include<stdlib.h>
+
+#include<impl.h>
+
+int main(int argc, char **argv) {
+ char *ten = malloc(10);
+ do_nasty(ten);
+ free(ten);
+ if(getenv("TEST_ENV")) {
+ printf("TEST_ENV is set.\n");
+ }
+ return 0;
+}
diff --git a/test cases/unit/2 testsetups/impl.c b/test cases/unit/2 testsetups/impl.c
new file mode 100644
index 0000000..d87f3de
--- /dev/null
+++ b/test cases/unit/2 testsetups/impl.c
@@ -0,0 +1,5 @@
+/* Write past the end. */
+
+void do_nasty(char *ptr) {
+ ptr[10] = 'n';
+}
diff --git a/test cases/unit/2 testsetups/impl.h b/test cases/unit/2 testsetups/impl.h
new file mode 100644
index 0000000..7a08cb3
--- /dev/null
+++ b/test cases/unit/2 testsetups/impl.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void do_nasty(char *ptr);
diff --git a/test cases/unit/2 testsetups/meson.build b/test cases/unit/2 testsetups/meson.build
new file mode 100644
index 0000000..a65548e
--- /dev/null
+++ b/test cases/unit/2 testsetups/meson.build
@@ -0,0 +1,16 @@
+project('testsetups', 'c')
+
+vg = find_program('valgrind')
+
+# This is only set when running under Valgrind test setup.
+env = environment()
+env.set('TEST_ENV', '1')
+
+add_test_setup('valgrind',
+ exe_wrapper : [vg, '--error-exitcode=1', '--leak-check=full'],
+ timeout_multiplier : 100,
+ env : env)
+
+buggy = executable('buggy', 'buggy.c', 'impl.c')
+test('Test buggy', buggy)
+
diff --git a/test cases/unit/3 subproject defaults/meson.build b/test cases/unit/3 subproject defaults/meson.build
new file mode 100644
index 0000000..3bf05d0
--- /dev/null
+++ b/test cases/unit/3 subproject defaults/meson.build
@@ -0,0 +1,11 @@
+project('subproject defaults', 'c',
+ default_options : ['defopoverride=defopt', # This should be overridden.
+ 'fromcmdline=defopt'] # This should get the value set in command line.
+ )
+
+subproject('foob', default_options : ['fromspfunc=spfunc', 'fromspfunconly=spfunc'])
+
+assert(get_option('fromcmdline') == 'cmdline', 'Default option defined in cmd line is incorrect: ' + get_option('fromcmdline'))
+assert(get_option('defopoverride') == 'defopt', 'Default option without cmd line override is incorrect: ' + get_option('defopoverride'))
+assert(get_option('fromoptfile') == 'optfile', 'Default value from option file is incorrect: ' + get_option('fromoptfile'))
+
diff --git a/test cases/unit/3 subproject defaults/meson_options.txt b/test cases/unit/3 subproject defaults/meson_options.txt
new file mode 100644
index 0000000..b63f512
--- /dev/null
+++ b/test cases/unit/3 subproject defaults/meson_options.txt
@@ -0,0 +1,3 @@
+option('defopoverride', type : 'string', value : 'optfile', description : 'A value for overriding.')
+option('fromcmdline', type : 'string', value : 'optfile', description : 'A value for overriding.')
+option('fromoptfile', type : 'string', value : 'optfile', description : 'A value for not overriding.')
diff --git a/test cases/unit/3 subproject defaults/subprojects/foob/meson.build b/test cases/unit/3 subproject defaults/subprojects/foob/meson.build
new file mode 100644
index 0000000..69f01d1
--- /dev/null
+++ b/test cases/unit/3 subproject defaults/subprojects/foob/meson.build
@@ -0,0 +1,12 @@
+project('foob', 'c',
+ default_options : ['defopoverride=s_defopt', # This should be overridden.
+ 'fromspfunc=s_defopt', # This is specified with a default_options kwarg to subproject()
+ 'fromcmdline=s_defopt'] # This should get the value set in command line.
+ )
+
+assert(get_option('fromcmdline') == 's_cmdline', 'Default option defined in cmd line is incorrect: ' + get_option('fromcmdline'))
+assert(get_option('fromspfunc') == 'spfunc', 'Default option set with subproject() incorrect: ' + get_option('fromspfunc'))
+assert(get_option('fromspfunconly') == 'spfunc', 'Default option set with subproject() incorrect: ' + get_option('fromspfunc'))
+assert(get_option('defopoverride') == 's_defopt', 'Default option without cmd line override is incorrect: ' + get_option('defopoverride'))
+assert(get_option('fromoptfile') == 's_optfile', 'Default value from option file is incorrect: ' + get_option('fromoptfile'))
+
diff --git a/test cases/unit/3 subproject defaults/subprojects/foob/meson_options.txt b/test cases/unit/3 subproject defaults/subprojects/foob/meson_options.txt
new file mode 100644
index 0000000..a9a615e
--- /dev/null
+++ b/test cases/unit/3 subproject defaults/subprojects/foob/meson_options.txt
@@ -0,0 +1,5 @@
+option('defopoverride', type : 'string', value : 's_optfile', description : 'A value for overriding.')
+option('fromcmdline', type : 'string', value : 's_optfile', description : 'A value for overriding.')
+option('fromspfunc', type : 'string', value : 's_optfile', description : 'A value for overriding.')
+option('fromspfunconly', type : 'string', value : 's_optfile', description : 'A value for overriding.')
+option('fromoptfile', type : 'string', value : 's_optfile', description : 'A value for not overriding.')
diff --git a/test cases/windows/7 mingw dll versioning/meson.build b/test cases/windows/7 mingw dll versioning/meson.build
index 23a3343..2f6035e 100644
--- a/test cases/windows/7 mingw dll versioning/meson.build
+++ b/test cases/windows/7 mingw dll versioning/meson.build
@@ -2,16 +2,16 @@ project('mingw dll versioning', 'c')
cc = meson.get_compiler('c')
+if cc.get_id() == 'msvc'
+ error('MESON_SKIP_TEST: test is only for MinGW')
+endif
+
# Test that MinGW/GCC creates correctly-named dll files and dll.a files,
# and also installs them in the right place
-if cc.get_id() != 'msvc'
- shared_library('some', 'lib.c',
- version : '1.2.3',
- soversion : '0',
- install : true)
+shared_library('some', 'lib.c',
+ version : '1.2.3',
+ soversion : '0',
+ install : true)
- shared_library('noversion', 'lib.c',
- install : true)
-else
- install_data('no-installed-files', install_dir : '')
-endif
+shared_library('noversion', 'lib.c',
+ install : true)
diff --git a/test cases/windows/7 mingw dll versioning/no-installed-files b/test cases/windows/7 mingw dll versioning/no-installed-files
deleted file mode 100644
index e69de29..0000000
--- a/test cases/windows/7 mingw dll versioning/no-installed-files
+++ /dev/null
diff --git a/test cases/windows/8 msvc dll versioning/meson.build b/test cases/windows/8 msvc dll versioning/meson.build
index 0c36173..d6aecb6 100644
--- a/test cases/windows/8 msvc dll versioning/meson.build
+++ b/test cases/windows/8 msvc dll versioning/meson.build
@@ -2,15 +2,15 @@ project('msvc dll versioning', 'c')
cc = meson.get_compiler('c')
+if cc.get_id() != 'msvc'
+ error('MESON_SKIP_TEST: test is only for msvc')
+endif
+
# Test that MSVC creates foo-0.dll and bar.dll
-if cc.get_id() == 'msvc'
- shared_library('some', 'lib.c',
- version : '1.2.3',
- soversion : '0',
- install : true)
+shared_library('some', 'lib.c',
+ version : '1.2.3',
+ soversion : '0',
+ install : true)
- shared_library('noversion', 'lib.c',
- install : true)
-else
- install_data('no-installed-files', install_dir : '')
-endif
+shared_library('noversion', 'lib.c',
+ install : true)
diff --git a/test cases/windows/8 msvc dll versioning/no-installed-files b/test cases/windows/8 msvc dll versioning/no-installed-files
deleted file mode 100644
index e69de29..0000000
--- a/test cases/windows/8 msvc dll versioning/no-installed-files
+++ /dev/null