|
|
|
@ -1221,7 +1221,7 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
os.environ.update(self.orig_env) |
|
|
|
|
super().tearDown() |
|
|
|
|
|
|
|
|
|
def _run(self, command, workdir=None): |
|
|
|
|
def _run(self, command, *, workdir=None, override_envvars=None): |
|
|
|
|
''' |
|
|
|
|
Run a command while printing the stdout and stderr to stdout, |
|
|
|
|
and also return a copy of it |
|
|
|
@ -1229,8 +1229,14 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
# If this call hangs CI will just abort. It is very hard to distinguish |
|
|
|
|
# between CI issue and test bug in that case. Set timeout and fail loud |
|
|
|
|
# instead. |
|
|
|
|
if override_envvars is None: |
|
|
|
|
env = None |
|
|
|
|
else: |
|
|
|
|
env = os.environ.copy() |
|
|
|
|
env.update(override_envvars) |
|
|
|
|
|
|
|
|
|
p = subprocess.run(command, stdout=subprocess.PIPE, |
|
|
|
|
stderr=subprocess.STDOUT, env=os.environ.copy(), |
|
|
|
|
stderr=subprocess.STDOUT, env=env, |
|
|
|
|
universal_newlines=True, cwd=workdir, timeout=60 * 5) |
|
|
|
|
print(p.stdout) |
|
|
|
|
if p.returncode != 0: |
|
|
|
@ -1239,7 +1245,11 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) |
|
|
|
|
return p.stdout |
|
|
|
|
|
|
|
|
|
def init(self, srcdir, extra_args=None, default_args=True, inprocess=False): |
|
|
|
|
def init(self, srcdir, *, |
|
|
|
|
extra_args=None, |
|
|
|
|
default_args=True, |
|
|
|
|
inprocess=False, |
|
|
|
|
override_envvars=None): |
|
|
|
|
self.assertPathExists(srcdir) |
|
|
|
|
if extra_args is None: |
|
|
|
|
extra_args = [] |
|
|
|
@ -1254,7 +1264,13 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
self.privatedir = os.path.join(self.builddir, 'meson-private') |
|
|
|
|
if inprocess: |
|
|
|
|
try: |
|
|
|
|
if override_envvars is not None: |
|
|
|
|
old_envvars = os.environ.copy() |
|
|
|
|
os.environ.update(override_envvars) |
|
|
|
|
(returncode, out, err) = run_configure_inprocess(self.meson_args + args + extra_args) |
|
|
|
|
if override_envvars is not None: |
|
|
|
|
os.environ.clear() |
|
|
|
|
os.environ.update(old_envvars) |
|
|
|
|
if 'MESON_SKIP_TEST' in out: |
|
|
|
|
raise unittest.SkipTest('Project requested skipping.') |
|
|
|
|
if returncode != 0: |
|
|
|
@ -1274,7 +1290,7 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
mesonbuild.mlog.log_file = None |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
out = self._run(self.setup_command + args + extra_args) |
|
|
|
|
out = self._run(self.setup_command + args + extra_args, override_envvars=override_envvars) |
|
|
|
|
except unittest.SkipTest: |
|
|
|
|
raise unittest.SkipTest('Project requested skipping: ' + srcdir) |
|
|
|
|
except Exception: |
|
|
|
@ -1282,40 +1298,52 @@ class BasePlatformTests(unittest.TestCase): |
|
|
|
|
raise |
|
|
|
|
return out |
|
|
|
|
|
|
|
|
|
def build(self, target=None, extra_args=None): |
|
|
|
|
def build(self, target=None, *, extra_args=None, override_envvars=None): |
|
|
|
|
if extra_args is None: |
|
|
|
|
extra_args = [] |
|
|
|
|
# Add arguments for building the target (if specified), |
|
|
|
|
# and using the build dir (if required, with VS) |
|
|
|
|
args = get_builddir_target_args(self.backend, self.builddir, target) |
|
|
|
|
return self._run(self.build_command + args + extra_args, workdir=self.builddir) |
|
|
|
|
return self._run(self.build_command + args + extra_args, workdir=self.builddir, override_envvars=override_envvars) |
|
|
|
|
|
|
|
|
|
def clean(self): |
|
|
|
|
def clean(self, *, override_envvars=None): |
|
|
|
|
dir_args = get_builddir_target_args(self.backend, self.builddir, None) |
|
|
|
|
self._run(self.clean_command + dir_args, workdir=self.builddir) |
|
|
|
|
self._run(self.clean_command + dir_args, workdir=self.builddir, override_envvars=override_envvars) |
|
|
|
|
|
|
|
|
|
def run_tests(self, inprocess=False): |
|
|
|
|
def run_tests(self, *, inprocess=False, override_envvars=None): |
|
|
|
|
if not inprocess: |
|
|
|
|
self._run(self.test_command, workdir=self.builddir) |
|
|
|
|
self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) |
|
|
|
|
else: |
|
|
|
|
if override_envvars is not None: |
|
|
|
|
old_envvars = os.environ.copy() |
|
|
|
|
os.environ.update(override_envvars) |
|
|
|
|
try: |
|
|
|
|
run_mtest_inprocess(['-C', self.builddir]) |
|
|
|
|
finally: |
|
|
|
|
if override_envvars is not None: |
|
|
|
|
os.environ.clear() |
|
|
|
|
os.environ.update(old_envvars) |
|
|
|
|
|
|
|
|
|
def install(self, *, use_destdir=True): |
|
|
|
|
def install(self, *, use_destdir=True, override_envvars=None): |
|
|
|
|
if self.backend is not Backend.ninja: |
|
|
|
|
raise unittest.SkipTest('{!r} backend can\'t install files'.format(self.backend.name)) |
|
|
|
|
if use_destdir: |
|
|
|
|
os.environ['DESTDIR'] = self.installdir |
|
|
|
|
self._run(self.install_command, workdir=self.builddir) |
|
|
|
|
destdir = {'DESTDIR': self.installdir} |
|
|
|
|
if override_envvars is None: |
|
|
|
|
override_envvars = destdir |
|
|
|
|
else: |
|
|
|
|
override_envvars.update(destdir) |
|
|
|
|
self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars) |
|
|
|
|
|
|
|
|
|
def uninstall(self): |
|
|
|
|
self._run(self.uninstall_command, workdir=self.builddir) |
|
|
|
|
def uninstall(self, *, override_envvars=None): |
|
|
|
|
self._run(self.uninstall_command, workdir=self.builddir, override_envvars=override_envvars) |
|
|
|
|
|
|
|
|
|
def run_target(self, target): |
|
|
|
|
def run_target(self, target, *, override_envvars=None): |
|
|
|
|
''' |
|
|
|
|
Run a Ninja target while printing the stdout and stderr to stdout, |
|
|
|
|
and also return a copy of it |
|
|
|
|
''' |
|
|
|
|
return self.build(target=target) |
|
|
|
|
return self.build(target=target, override_envvars=override_envvars) |
|
|
|
|
|
|
|
|
|
def setconf(self, arg, will_build=True): |
|
|
|
|
if not isinstance(arg, list): |
|
|
|
@ -1498,7 +1526,7 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
# This can just be a relative path, but we want to test |
|
|
|
|
# that passing this as an absolute path also works |
|
|
|
|
'--libdir=' + prefix + '/' + libdir] |
|
|
|
|
self.init(testdir, extra_args, default_args=False) |
|
|
|
|
self.init(testdir, extra_args=extra_args, default_args=False) |
|
|
|
|
opts = self.introspect('--buildoptions') |
|
|
|
|
for opt in opts: |
|
|
|
|
if opt['name'] == 'prefix': |
|
|
|
@ -1514,11 +1542,11 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '1 trivial') |
|
|
|
|
# libdir being inside prefix is ok |
|
|
|
|
args = ['--prefix', '/opt', '--libdir', '/opt/lib32'] |
|
|
|
|
self.init(testdir, args) |
|
|
|
|
self.init(testdir, extra_args=args) |
|
|
|
|
self.wipe() |
|
|
|
|
# libdir not being inside prefix is not ok |
|
|
|
|
args = ['--prefix', '/usr', '--libdir', '/opt/lib32'] |
|
|
|
|
self.assertRaises(subprocess.CalledProcessError, self.init, testdir, args) |
|
|
|
|
self.assertRaises(subprocess.CalledProcessError, self.init, testdir, extra_args=args) |
|
|
|
|
self.wipe() |
|
|
|
|
# libdir must be inside prefix even when set via mesonconf |
|
|
|
|
self.init(testdir) |
|
|
|
@ -1558,7 +1586,7 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
} |
|
|
|
|
for prefix in expected: |
|
|
|
|
args = ['--prefix', prefix] |
|
|
|
|
self.init(testdir, args, default_args=False) |
|
|
|
|
self.init(testdir, extra_args=args, default_args=False) |
|
|
|
|
opts = self.introspect('--buildoptions') |
|
|
|
|
for opt in opts: |
|
|
|
|
name = opt['name'] |
|
|
|
@ -1597,7 +1625,7 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
'sharedstatedir': '/var/state'}, |
|
|
|
|
} |
|
|
|
|
for args in expected: |
|
|
|
|
self.init(testdir, args.split(), default_args=False) |
|
|
|
|
self.init(testdir, extra_args=args.split(), default_args=False) |
|
|
|
|
opts = self.introspect('--buildoptions') |
|
|
|
|
for opt in opts: |
|
|
|
|
name = opt['name'] |
|
|
|
@ -1755,7 +1783,7 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
|
|
|
|
|
def test_forcefallback(self): |
|
|
|
|
testdir = os.path.join(self.unit_test_dir, '31 forcefallback') |
|
|
|
|
self.init(testdir, ['--wrap-mode=forcefallback']) |
|
|
|
|
self.init(testdir, extra_args=['--wrap-mode=forcefallback']) |
|
|
|
|
self.build() |
|
|
|
|
self.run_tests() |
|
|
|
|
|
|
|
|
@ -2187,9 +2215,10 @@ class AllPlatformTests(BasePlatformTests): |
|
|
|
|
# !, ^, *, and < confuse lcc preprocessor |
|
|
|
|
value = 'spaces and fun@$&()-=_+{}[]:;>?,./~`' |
|
|
|
|
for env_var in ['CPPFLAGS', 'CFLAGS']: |
|
|
|
|
os.environ[env_var] = '-D{}="{}"'.format(define, value) |
|
|
|
|
os.environ['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read'.format(define) |
|
|
|
|
self.init(testdir, ['-D{}={}'.format(define, value)]) |
|
|
|
|
env = {} |
|
|
|
|
env[env_var] = '-D{}="{}"'.format(define, value) |
|
|
|
|
env['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read'.format(define) |
|
|
|
|
self.init(testdir, extra_args=['-D{}={}'.format(define, value)], override_envvars=env) |
|
|
|
|
|
|
|
|
|
def test_custom_target_exe_data_deterministic(self): |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '114 custom target capture') |
|
|
|
@ -2542,9 +2571,8 @@ int main(int argc, char **argv) { |
|
|
|
|
self.build_static_lib(cc, stlinker, source, objectfile, stlibfile, extra_args=['-DFOO_STATIC']) |
|
|
|
|
self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) |
|
|
|
|
# Run test |
|
|
|
|
os.environ['PKG_CONFIG_LIBDIR'] = self.builddir |
|
|
|
|
try: |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': self.builddir}) |
|
|
|
|
self.build() |
|
|
|
|
self.run_tests() |
|
|
|
|
finally: |
|
|
|
@ -2783,12 +2811,12 @@ int main(int argc, char **argv) { |
|
|
|
|
name = os.path.basename(f.name) |
|
|
|
|
|
|
|
|
|
with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}): |
|
|
|
|
self.init(testdir, ['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
|
with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}): |
|
|
|
|
os.environ.pop('XDG_DATA_HOME', None) |
|
|
|
|
self.init(testdir, ['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
|
with tempfile.TemporaryDirectory() as d: |
|
|
|
@ -2804,7 +2832,7 @@ int main(int argc, char **argv) { |
|
|
|
|
with mock.patch.dict(os.environ): |
|
|
|
|
os.environ.pop('XDG_DATA_HOME', None) |
|
|
|
|
with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)): |
|
|
|
|
self.init(testdir, ['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
|
def test_compiler_run_command(self): |
|
|
|
@ -2899,9 +2927,8 @@ recommended as it is not supported on some platforms''') |
|
|
|
|
# build user of library |
|
|
|
|
self.new_builddir() |
|
|
|
|
# replace is needed because meson mangles platform pathes passed via LDFLAGS |
|
|
|
|
os.environ["LDFLAGS"] = '-L{}'.format(libdir.replace('\\', '/')) |
|
|
|
|
self.init(os.path.join(testdirbase, 'exe')) |
|
|
|
|
del os.environ["LDFLAGS"] |
|
|
|
|
self.init(os.path.join(testdirbase, 'exe'), |
|
|
|
|
override_envvars={"LDFLAGS": '-L{}'.format(libdir.replace('\\', '/'))}) |
|
|
|
|
self.build() |
|
|
|
|
self.assertBuildIsNoop() |
|
|
|
|
|
|
|
|
@ -3230,11 +3257,11 @@ recommended as it is not supported on some platforms''') |
|
|
|
|
crossfile.flush() |
|
|
|
|
self.meson_cross_file = crossfile.name |
|
|
|
|
|
|
|
|
|
os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(testdir, |
|
|
|
|
'native_pkgconfig') |
|
|
|
|
self.init(testdir, extra_args=['-Dstart_native=false']) |
|
|
|
|
env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, |
|
|
|
|
'native_pkgconfig')} |
|
|
|
|
self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) |
|
|
|
|
self.wipe() |
|
|
|
|
self.init(testdir, extra_args=['-Dstart_native=true']) |
|
|
|
|
self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) |
|
|
|
|
|
|
|
|
|
def __reconfigure(self, change_minor=False): |
|
|
|
|
# Set an older version to force a reconfigure from scratch |
|
|
|
@ -3741,7 +3768,12 @@ class FailureTests(BasePlatformTests): |
|
|
|
|
super().tearDown() |
|
|
|
|
windows_proof_rmtree(self.srcdir) |
|
|
|
|
|
|
|
|
|
def assertMesonRaises(self, contents, match, extra_args=None, langs=None, meson_version=None, options=None): |
|
|
|
|
def assertMesonRaises(self, contents, match, *, |
|
|
|
|
extra_args=None, |
|
|
|
|
langs=None, |
|
|
|
|
meson_version=None, |
|
|
|
|
options=None, |
|
|
|
|
override_envvars=None): |
|
|
|
|
''' |
|
|
|
|
Assert that running meson configure on the specified @contents raises |
|
|
|
|
a error message matching regex @match. |
|
|
|
@ -3759,11 +3791,17 @@ class FailureTests(BasePlatformTests): |
|
|
|
|
if options is not None: |
|
|
|
|
with open(self.moptions, 'w') as f: |
|
|
|
|
f.write(options) |
|
|
|
|
o = {'MESON_FORCE_BACKTRACE': '1'} |
|
|
|
|
if override_envvars is None: |
|
|
|
|
override_envvars = o |
|
|
|
|
else: |
|
|
|
|
override_envvars.update(o) |
|
|
|
|
# Force tracebacks so we can detect them properly |
|
|
|
|
os.environ['MESON_FORCE_BACKTRACE'] = '1' |
|
|
|
|
with self.assertRaisesRegex(MesonException, match, msg=contents): |
|
|
|
|
# Must run in-process or we'll get a generic CalledProcessError |
|
|
|
|
self.init(self.srcdir, extra_args=extra_args, inprocess=True) |
|
|
|
|
self.init(self.srcdir, extra_args=extra_args, |
|
|
|
|
inprocess=True, |
|
|
|
|
override_envvars = override_envvars) |
|
|
|
|
|
|
|
|
|
def obtainMesonOutput(self, contents, match, extra_args, langs, meson_version=None): |
|
|
|
|
if langs is None: |
|
|
|
@ -3873,9 +3911,9 @@ class FailureTests(BasePlatformTests): |
|
|
|
|
|
|
|
|
|
def test_boost_BOOST_ROOT_dependency(self): |
|
|
|
|
# Test BOOST_ROOT; can be run even if Boost is found or not |
|
|
|
|
os.environ['BOOST_ROOT'] = 'relative/path' |
|
|
|
|
self.assertMesonRaises("dependency('boost')", |
|
|
|
|
"(BOOST_ROOT.*absolute|{})".format(self.dnf)) |
|
|
|
|
"(BOOST_ROOT.*absolute|{})".format(self.dnf), |
|
|
|
|
override_envvars = {'BOOST_ROOT': 'relative/path'}) |
|
|
|
|
|
|
|
|
|
def test_dependency_invalid_method(self): |
|
|
|
|
code = '''zlib_dep = dependency('zlib', required : false) |
|
|
|
@ -3934,9 +3972,8 @@ class FailureTests(BasePlatformTests): |
|
|
|
|
Test exit status on python exception |
|
|
|
|
''' |
|
|
|
|
tdir = os.path.join(self.unit_test_dir, '21 exit status') |
|
|
|
|
os.environ['MESON_UNIT_TEST'] = '1' |
|
|
|
|
with self.assertRaises(subprocess.CalledProcessError) as cm: |
|
|
|
|
self.init(tdir, inprocess=False) |
|
|
|
|
self.init(tdir, inprocess=False, override_envvars = {'MESON_UNIT_TEST': '1'}) |
|
|
|
|
self.assertEqual(cm.exception.returncode, 2) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
@ -4207,11 +4244,10 @@ class DarwinTests(BasePlatformTests): |
|
|
|
|
# to ascertain that Meson does not call install_name_tool |
|
|
|
|
# with duplicate -delete_rpath arguments, which would |
|
|
|
|
# lead to erroring out on installation |
|
|
|
|
os.environ["LDFLAGS"] = "-Wl,-rpath,/foo/bar" |
|
|
|
|
self.init(testdir) |
|
|
|
|
env = {"LDFLAGS": "-Wl,-rpath,/foo/bar"} |
|
|
|
|
self.init(testdir, override_envvars=env) |
|
|
|
|
self.build() |
|
|
|
|
self.install() |
|
|
|
|
del os.environ["LDFLAGS"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(not is_windows(), "requires something Unix-like") |
|
|
|
@ -4294,13 +4330,13 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
privatedir1 = self.privatedir |
|
|
|
|
|
|
|
|
|
self.new_builddir() |
|
|
|
|
os.environ['PKG_CONFIG_LIBDIR'] = privatedir1 |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '48 pkgconfig-gen', 'dependencies') |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': privatedir1}) |
|
|
|
|
privatedir2 = self.privatedir |
|
|
|
|
|
|
|
|
|
os.environ['PKG_CONFIG_LIBDIR'] = os.pathsep.join([privatedir1, privatedir2]) |
|
|
|
|
self._run(['pkg-config', 'dependency-test', '--validate']) |
|
|
|
|
os.environ |
|
|
|
|
env = {'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2])} |
|
|
|
|
self._run(['pkg-config', 'dependency-test', '--validate'], override_envvars=env) |
|
|
|
|
|
|
|
|
|
# pkg-config strips some duplicated flags so we have to parse the |
|
|
|
|
# generated file ourself. |
|
|
|
@ -4326,14 +4362,14 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
self.assertEqual(len(expected), matched_lines) |
|
|
|
|
|
|
|
|
|
cmd = ['pkg-config', 'requires-test'] |
|
|
|
|
out = self._run(cmd + ['--print-requires']).strip().split('\n') |
|
|
|
|
out = self._run(cmd + ['--print-requires'], override_envvars=env).strip().split('\n') |
|
|
|
|
if not is_openbsd(): |
|
|
|
|
self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) |
|
|
|
|
else: |
|
|
|
|
self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) |
|
|
|
|
|
|
|
|
|
cmd = ['pkg-config', 'requires-private-test'] |
|
|
|
|
out = self._run(cmd + ['--print-requires-private']).strip().split('\n') |
|
|
|
|
out = self._run(cmd + ['--print-requires-private'], override_envvars=env).strip().split('\n') |
|
|
|
|
if not is_openbsd(): |
|
|
|
|
self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) |
|
|
|
|
else: |
|
|
|
@ -4392,7 +4428,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
qt4 = subprocess.call(['pkg-config', '--exists', 'QtCore']) |
|
|
|
|
qt5 = subprocess.call(['pkg-config', '--exists', 'Qt5Core']) |
|
|
|
|
testdir = os.path.join(self.framework_test_dir, '4 qt') |
|
|
|
|
self.init(testdir, ['-Dmethod=pkg-config']) |
|
|
|
|
self.init(testdir, extra_args=['-Dmethod=pkg-config']) |
|
|
|
|
# Confirm that the dependency was found with pkg-config |
|
|
|
|
mesonlog = self.get_meson_log() |
|
|
|
|
if qt4 == 0: |
|
|
|
@ -4410,7 +4446,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
raise unittest.SkipTest('-fsanitize=address is not supported on OpenBSD') |
|
|
|
|
|
|
|
|
|
testdir = os.path.join(self.framework_test_dir, '7 gnome') |
|
|
|
|
self.init(testdir, ['-Db_sanitize=address', '-Db_lundef=false']) |
|
|
|
|
self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) |
|
|
|
|
self.build() |
|
|
|
|
|
|
|
|
|
def test_qt5dependency_qmake_detection(self): |
|
|
|
@ -4427,7 +4463,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
raise unittest.SkipTest('Qmake found, but it is not for Qt 5.') |
|
|
|
|
# Disable pkg-config codepath and force searching with qmake/qmake-qt5 |
|
|
|
|
testdir = os.path.join(self.framework_test_dir, '4 qt') |
|
|
|
|
self.init(testdir, ['-Dmethod=qmake']) |
|
|
|
|
self.init(testdir, extra_args=['-Dmethod=qmake']) |
|
|
|
|
# Confirm that the dependency was found with qmake |
|
|
|
|
mesonlog = self.get_meson_log() |
|
|
|
|
self.assertRegex('\n'.join(mesonlog), |
|
|
|
@ -4492,9 +4528,10 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
an ordinary test case because it needs the environment to be set. |
|
|
|
|
''' |
|
|
|
|
Oflag = '-O3' |
|
|
|
|
os.environ['CFLAGS'] = os.environ['CXXFLAGS'] = Oflag |
|
|
|
|
env = {'CFLAGS': Oflag, |
|
|
|
|
'CXXFLAGS': Oflag} |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '40 has function') |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars=env) |
|
|
|
|
cmds = self.get_meson_log_compiler_checks() |
|
|
|
|
for cmd in cmds: |
|
|
|
|
if cmd[0] == 'ccache': |
|
|
|
@ -4522,7 +4559,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
if (compiler.get_id() == 'gcc' and '2a' in v and version_compare(compiler.version, '<8.0.0')): |
|
|
|
|
continue |
|
|
|
|
std_opt = '{}={}'.format(lang_std, v) |
|
|
|
|
self.init(testdir, ['-D' + std_opt]) |
|
|
|
|
self.init(testdir, extra_args=['-D' + std_opt]) |
|
|
|
|
cmd = self.get_compdb()[0]['command'] |
|
|
|
|
# c++03 and gnu++03 are not understood by ICC, don't try to look for them |
|
|
|
|
skiplist = frozenset([ |
|
|
|
@ -4540,11 +4577,17 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
# 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 |
|
|
|
|
if p == 'c': |
|
|
|
|
env_flag_name = 'CFLAGS' |
|
|
|
|
elif p == 'cpp': |
|
|
|
|
env_flag_name = 'CXXFLAGS' |
|
|
|
|
else: |
|
|
|
|
raise NotImplementedError('Language {} not defined.'.format(p)) |
|
|
|
|
env = {} |
|
|
|
|
env[env_flag_name] = cmd_std |
|
|
|
|
with self.assertRaises((subprocess.CalledProcessError, mesonbuild.mesonlib.EnvironmentException), |
|
|
|
|
msg='C compiler should have failed with -std=FAIL'): |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars = env) |
|
|
|
|
# ICC won't fail in the above because additional flags are needed to |
|
|
|
|
# make unknown -std=... options errors. |
|
|
|
|
self.build() |
|
|
|
@ -4793,8 +4836,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
@skipIfNoPkgconfig |
|
|
|
|
def test_order_of_l_arguments(self): |
|
|
|
|
testdir = os.path.join(self.unit_test_dir, '8 -L -l order') |
|
|
|
|
os.environ['PKG_CONFIG_PATH'] = testdir |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) |
|
|
|
|
# NOTE: .pc file has -Lfoo -lfoo -Lbar -lbar but pkg-config reorders |
|
|
|
|
# the flags before returning them to -Lfoo -Lbar -lfoo -lbar |
|
|
|
|
# but pkgconf seems to not do that. Sigh. Support both. |
|
|
|
@ -4875,7 +4917,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
raise unittest.SkipTest('-fsanitize=address is not supported on OpenBSD') |
|
|
|
|
|
|
|
|
|
testdir = os.path.join(self.common_test_dir, '13 pch') |
|
|
|
|
self.init(testdir, ['-Db_sanitize=address']) |
|
|
|
|
self.init(testdir, extra_args=['-Db_sanitize=address']) |
|
|
|
|
self.build() |
|
|
|
|
compdb = self.get_compdb() |
|
|
|
|
for i in compdb: |
|
|
|
@ -4891,7 +4933,7 @@ class LinuxlikeTests(BasePlatformTests): |
|
|
|
|
# We need to use llvm-cov instead of gcovr with clang |
|
|
|
|
raise unittest.SkipTest('Coverage does not work with clang right now, help wanted!') |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '1 trivial') |
|
|
|
|
self.init(testdir, ['-Db_coverage=true']) |
|
|
|
|
self.init(testdir, extra_args=['-Db_coverage=true']) |
|
|
|
|
self.build() |
|
|
|
|
self.run_tests() |
|
|
|
|
self.run_target('coverage-html') |
|
|
|
@ -4921,7 +4963,7 @@ endian = 'little' |
|
|
|
|
|
|
|
|
|
def test_reconfigure(self): |
|
|
|
|
testdir = os.path.join(self.unit_test_dir, '13 reconfigure') |
|
|
|
|
self.init(testdir, ['-Db_coverage=true'], default_args=False) |
|
|
|
|
self.init(testdir, extra_args=['-Db_coverage=true'], default_args=False) |
|
|
|
|
self.build('reconfigure') |
|
|
|
|
|
|
|
|
|
def test_vala_generated_source_buildir_inside_source_tree(self): |
|
|
|
@ -4952,10 +4994,14 @@ endian = 'little' |
|
|
|
|
also tested. |
|
|
|
|
''' |
|
|
|
|
testdir = os.path.join(self.framework_test_dir, '7 gnome') |
|
|
|
|
os.environ['MESON_UNIT_TEST_PRETEND_GLIB_OLD'] = "1" |
|
|
|
|
mesonbuild.modules.gnome.native_glib_version = '2.20' |
|
|
|
|
self.init(testdir, inprocess=True) |
|
|
|
|
self.build() |
|
|
|
|
env = {'MESON_UNIT_TEST_PRETEND_GLIB_OLD': "1"} |
|
|
|
|
try: |
|
|
|
|
self.init(testdir, |
|
|
|
|
inprocess=True, |
|
|
|
|
override_envvars=env) |
|
|
|
|
self.build(override_envvars=env) |
|
|
|
|
finally: |
|
|
|
|
mesonbuild.modules.gnome.native_glib_version = None |
|
|
|
|
|
|
|
|
|
@skipIfNoPkgconfig |
|
|
|
@ -4967,23 +5013,24 @@ endian = 'little' |
|
|
|
|
stderr=subprocess.DEVNULL) != 0: |
|
|
|
|
raise unittest.SkipTest('Glib 2.0 dependency not available.') |
|
|
|
|
with tempfile.TemporaryDirectory() as tempdirname: |
|
|
|
|
self.init(testdir1, ['--prefix=' + tempdirname, '--libdir=lib'], default_args=False) |
|
|
|
|
self.init(testdir1, extra_args=['--prefix=' + tempdirname, '--libdir=lib'], default_args=False) |
|
|
|
|
self.install(use_destdir=False) |
|
|
|
|
shutil.rmtree(self.builddir) |
|
|
|
|
os.mkdir(self.builddir) |
|
|
|
|
pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') |
|
|
|
|
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'libpkgdep.pc'))) |
|
|
|
|
lib_dir = os.path.join(tempdirname, 'lib') |
|
|
|
|
os.environ['PKG_CONFIG_PATH'] = pkg_dir |
|
|
|
|
myenv = os.environ.copy() |
|
|
|
|
myenv['PKG_CONFIG_PATH'] = pkg_dir |
|
|
|
|
# Private internal libraries must not leak out. |
|
|
|
|
pkg_out = subprocess.check_output(['pkg-config', '--static', '--libs', 'libpkgdep']) |
|
|
|
|
pkg_out = subprocess.check_output(['pkg-config', '--static', '--libs', 'libpkgdep'], env=myenv) |
|
|
|
|
self.assertFalse(b'libpkgdep-int' in pkg_out, 'Internal library leaked out.') |
|
|
|
|
# Dependencies must not leak to cflags when building only a shared library. |
|
|
|
|
pkg_out = subprocess.check_output(['pkg-config', '--cflags', 'libpkgdep']) |
|
|
|
|
pkg_out = subprocess.check_output(['pkg-config', '--cflags', 'libpkgdep'], env=myenv) |
|
|
|
|
self.assertFalse(b'glib' in pkg_out, 'Internal dependency leaked to headers.') |
|
|
|
|
# Test that the result is usable. |
|
|
|
|
self.init(testdir2) |
|
|
|
|
self.build() |
|
|
|
|
self.init(testdir2, override_envvars=myenv) |
|
|
|
|
self.build(override_envvars=myenv) |
|
|
|
|
myenv = os.environ.copy() |
|
|
|
|
myenv['LD_LIBRARY_PATH'] = ':'.join([lib_dir, myenv.get('LD_LIBRARY_PATH', '')]) |
|
|
|
|
if is_cygwin(): |
|
|
|
@ -5027,9 +5074,9 @@ endian = 'little' |
|
|
|
|
|
|
|
|
|
# build user of library |
|
|
|
|
pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') |
|
|
|
|
os.environ['PKG_CONFIG_PATH'] = pkg_dir |
|
|
|
|
self.new_builddir() |
|
|
|
|
self.init(os.path.join(testdirbase, 'app')) |
|
|
|
|
self.init(os.path.join(testdirbase, 'app'), |
|
|
|
|
override_envvars={'PKG_CONFIG_PATH': pkg_dir}) |
|
|
|
|
self.build() |
|
|
|
|
|
|
|
|
|
@skipIfNoPkgconfig |
|
|
|
@ -5134,16 +5181,16 @@ endian = 'little' |
|
|
|
|
self.install(use_destdir=False) |
|
|
|
|
## New builddir for the consumer |
|
|
|
|
self.new_builddir() |
|
|
|
|
os.environ['LIBRARY_PATH'] = os.path.join(installdir, self.libdir) |
|
|
|
|
os.environ['PKG_CONFIG_PATH'] = os.path.join(installdir, self.libdir, 'pkgconfig') |
|
|
|
|
env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), |
|
|
|
|
'PKG_CONFIG_PATH': os.path.join(installdir, self.libdir, 'pkgconfig')} |
|
|
|
|
testdir = os.path.join(self.unit_test_dir, '40 external, internal library rpath', 'built library') |
|
|
|
|
# install into installdir without using DESTDIR |
|
|
|
|
self.prefix = self.installdir |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars=env) |
|
|
|
|
self.prefix = oldprefix |
|
|
|
|
self.build() |
|
|
|
|
self.build(override_envvars=env) |
|
|
|
|
# test uninstalled |
|
|
|
|
self.run_tests() |
|
|
|
|
self.run_tests(override_envvars=env) |
|
|
|
|
if not is_osx(): |
|
|
|
|
# Rest of the workflow only works on macOS |
|
|
|
|
return |
|
|
|
@ -5156,10 +5203,10 @@ endian = 'little' |
|
|
|
|
## New builddir for testing that DESTDIR is not added to install_name |
|
|
|
|
self.new_builddir() |
|
|
|
|
# install into installdir with DESTDIR |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.build() |
|
|
|
|
self.init(testdir, override_envvars=env) |
|
|
|
|
self.build(override_envvars=env) |
|
|
|
|
# test running after installation |
|
|
|
|
self.install() |
|
|
|
|
self.install(override_envvars=env) |
|
|
|
|
prog = self.installdir + os.path.join(self.prefix, 'bin', 'prog') |
|
|
|
|
lib = self.installdir + os.path.join(self.prefix, 'lib', 'libbar_built.dylib') |
|
|
|
|
for f in prog, lib: |
|
|
|
@ -5249,14 +5296,14 @@ endian = 'little' |
|
|
|
|
def test_identity_cross(self): |
|
|
|
|
testdir = os.path.join(self.unit_test_dir, '58 identity cross') |
|
|
|
|
crossfile = tempfile.NamedTemporaryFile(mode='w') |
|
|
|
|
os.environ['CC'] = '"' + os.path.join(testdir, 'build_wrapper.py') + '"' |
|
|
|
|
env = {'CC': '"' + os.path.join(testdir, 'build_wrapper.py') + '"'} |
|
|
|
|
crossfile.write('''[binaries] |
|
|
|
|
c = ['{0}'] |
|
|
|
|
'''.format(os.path.join(testdir, 'host_wrapper.py'))) |
|
|
|
|
crossfile.flush() |
|
|
|
|
self.meson_cross_file = crossfile.name |
|
|
|
|
# TODO should someday be explicit about build platform only here |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars=env) |
|
|
|
|
|
|
|
|
|
def should_run_cross_arm_tests(): |
|
|
|
|
return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm') |
|
|
|
@ -5278,8 +5325,7 @@ class LinuxCrossArmTests(BasePlatformTests): |
|
|
|
|
inspect the compiler database. |
|
|
|
|
''' |
|
|
|
|
testdir = os.path.join(self.common_test_dir, '3 static') |
|
|
|
|
os.environ['CFLAGS'] = '-DBUILD_ENVIRONMENT_ONLY' |
|
|
|
|
self.init(testdir) |
|
|
|
|
self.init(testdir, override_envvars={'CFLAGS': '-DBUILD_ENVIRONMENT_ONLY'}) |
|
|
|
|
compdb = self.get_compdb() |
|
|
|
|
self.assertNotIn('-DBUILD_ENVIRONMENT_ONLY', compdb[0]['command']) |
|
|
|
|
|
|
|
|
@ -5348,18 +5394,23 @@ class LinuxCrossMingwTests(BasePlatformTests): |
|
|
|
|
# Change cross file to use a non-existing exe_wrapper and it should fail |
|
|
|
|
self.meson_cross_file = os.path.join(testdir, 'broken-cross.txt') |
|
|
|
|
# Force tracebacks so we can detect them properly |
|
|
|
|
os.environ['MESON_FORCE_BACKTRACE'] = '1' |
|
|
|
|
env = {'MESON_FORCE_BACKTRACE': '1'} |
|
|
|
|
with self.assertRaisesRegex(MesonException, 'exe_wrapper.*target.*use-exe-wrapper'): |
|
|
|
|
# Must run in-process or we'll get a generic CalledProcessError |
|
|
|
|
self.init(testdir, extra_args='-Drun-target=false', inprocess=True) |
|
|
|
|
self.init(testdir, extra_args='-Drun-target=false', |
|
|
|
|
inprocess=True, |
|
|
|
|
override_envvars=env) |
|
|
|
|
with self.assertRaisesRegex(MesonException, 'exe_wrapper.*run target.*run-prog'): |
|
|
|
|
# Must run in-process or we'll get a generic CalledProcessError |
|
|
|
|
self.init(testdir, extra_args='-Dcustom-target=false', inprocess=True) |
|
|
|
|
self.init(testdir, extra_args=['-Dcustom-target=false', '-Drun-target=false']) |
|
|
|
|
self.init(testdir, extra_args='-Dcustom-target=false', |
|
|
|
|
inprocess=True, |
|
|
|
|
override_envvars=env) |
|
|
|
|
self.init(testdir, extra_args=['-Dcustom-target=false', '-Drun-target=false'], |
|
|
|
|
override_envvars=env) |
|
|
|
|
self.build() |
|
|
|
|
with self.assertRaisesRegex(MesonException, 'exe_wrapper.*PATH'): |
|
|
|
|
# Must run in-process or we'll get a generic CalledProcessError |
|
|
|
|
self.run_tests(inprocess=True) |
|
|
|
|
self.run_tests(inprocess=True, override_envvars=env) |
|
|
|
|
|
|
|
|
|
@skipIfNoPkgconfig |
|
|
|
|
def test_cross_pkg_config_option(self): |
|
|
|
@ -5390,7 +5441,7 @@ class PythonTests(BasePlatformTests): |
|
|
|
|
# will also try 'python' as a fallback and use it if the major |
|
|
|
|
# version matches |
|
|
|
|
try: |
|
|
|
|
self.init(testdir, ['-Dpython=python2']) |
|
|
|
|
self.init(testdir, extra_args=['-Dpython=python2']) |
|
|
|
|
self.build() |
|
|
|
|
self.run_tests() |
|
|
|
|
except unittest.SkipTest: |
|
|
|
@ -5406,7 +5457,7 @@ class PythonTests(BasePlatformTests): |
|
|
|
|
|
|
|
|
|
for py in ('pypy', 'pypy3'): |
|
|
|
|
try: |
|
|
|
|
self.init(testdir, ['-Dpython=%s' % py]) |
|
|
|
|
self.init(testdir, extra_args=['-Dpython=%s' % py]) |
|
|
|
|
except unittest.SkipTest: |
|
|
|
|
# Same as above, pypy2 and pypy3 are not expected to be present |
|
|
|
|
# on the test system, the test project only raises in these cases |
|
|
|
@ -5420,13 +5471,13 @@ class PythonTests(BasePlatformTests): |
|
|
|
|
# The test is configured to error out with MESON_SKIP_TEST |
|
|
|
|
# in case it could not find python |
|
|
|
|
with self.assertRaises(unittest.SkipTest): |
|
|
|
|
self.init(testdir, ['-Dpython=not-python']) |
|
|
|
|
self.init(testdir, extra_args=['-Dpython=not-python']) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
|
# While dir is an external command on both Windows and Linux, |
|
|
|
|
# it certainly isn't python |
|
|
|
|
with self.assertRaises(unittest.SkipTest): |
|
|
|
|
self.init(testdir, ['-Dpython=dir']) |
|
|
|
|
self.init(testdir, extra_args=['-Dpython=dir']) |
|
|
|
|
self.wipe() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|