aboutsummaryrefslogtreecommitdiff
path: root/unittests/allplatformstests.py
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/allplatformstests.py')
-rw-r--r--unittests/allplatformstests.py295
1 files changed, 188 insertions, 107 deletions
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 2fee06c..8f56611 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -29,7 +29,7 @@ import mesonbuild.coredata
import mesonbuild.machinefile
import mesonbuild.modules.gnome
from mesonbuild.mesonlib import (
- BuildDirLock, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd,
+ DirectoryLock, DirectoryLockAction, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd,
is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg,
relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix,
MesonException, EnvironmentException,
@@ -222,6 +222,47 @@ class AllPlatformTests(BasePlatformTests):
confdata.values = {'VAR': (['value'], 'description')}
self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'meson')
+ def test_cmake_configuration(self):
+ if self.backend is not Backend.ninja:
+ raise SkipTest('ninja backend needed to configure with cmake')
+
+ cmake = ExternalProgram('cmake')
+ if not cmake.found():
+ raise SkipTest('cmake not available')
+
+ cmake_version = cmake.get_version()
+ if not version_compare(cmake_version, '>=3.13.5'):
+ raise SkipTest('cmake is too old')
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ srcdir = os.path.join(tmpdir, 'src')
+
+ shutil.copytree(os.path.join(self.src_root, 'test cases', 'common', '14 configure file'), srcdir)
+ self.init(srcdir)
+
+ cmake_builddir = os.path.join(srcdir, "cmake_builddir")
+ self.assertNotEqual(self.builddir, cmake_builddir)
+ self._run([cmake.path, '-G', 'Ninja', '-S', srcdir, '-B', cmake_builddir])
+
+ header_list = [
+ 'config7.h',
+ 'config10.h',
+ ]
+
+ for header in header_list:
+ meson_header = ""
+ cmake_header = ""
+
+ with open(os.path.join(self.builddir, header), encoding='utf-8') as f:
+ meson_header = f.read()
+
+ cmake_header_path = os.path.join(cmake_builddir, header)
+ with open(os.path.join(cmake_builddir, header), encoding='utf-8') as f:
+ cmake_header = f.read()
+
+ self.assertTrue(cmake_header, f'cmake generated header {header} is empty')
+ self.assertEqual(cmake_header, meson_header)
+
def test_absolute_prefix_libdir(self):
'''
Tests that setting absolute paths for --prefix and --libdir work. Can't
@@ -529,7 +570,8 @@ class AllPlatformTests(BasePlatformTests):
if self.backend is not Backend.ninja:
raise SkipTest(f'{self.backend.name!r} backend can\'t install files')
testdir = os.path.join(self.common_test_dir, '8 install')
- self.init(testdir)
+ # sneak in a test that covers backend options...
+ self.init(testdir, extra_args=['-Dbackend_max_links=4'])
intro = self.introspect('--targets')
if intro[0]['type'] == 'executable':
intro = intro[::-1]
@@ -1098,110 +1140,144 @@ class AllPlatformTests(BasePlatformTests):
for lang, evar in langs:
# Detect with evar and do sanity checks on that
if evar in os.environ:
- ecc = compiler_from_language(env, lang, MachineChoice.HOST)
- self.assertTrue(ecc.version)
- elinker = detect_static_linker(env, ecc)
- # Pop it so we don't use it for the next detection
- evalue = os.environ.pop(evar)
- # Very rough/strict heuristics. Would never work for actual
- # compiler detection, but should be ok for the tests.
- ebase = os.path.basename(evalue)
- if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')):
- self.assertIsInstance(ecc, gnu)
- self.assertIsInstance(elinker, ar)
- elif 'clang-cl' in ebase:
- self.assertIsInstance(ecc, clangcl)
- self.assertIsInstance(elinker, lib)
- elif 'clang' in ebase:
- self.assertIsInstance(ecc, clang)
- self.assertIsInstance(elinker, ar)
- elif ebase.startswith('ic'):
- self.assertIsInstance(ecc, intel)
- self.assertIsInstance(elinker, ar)
- elif ebase.startswith('cl'):
- self.assertIsInstance(ecc, msvc)
- self.assertIsInstance(elinker, lib)
- else:
- raise AssertionError(f'Unknown compiler {evalue!r}')
- # Check that we actually used the evalue correctly as the compiler
- self.assertEqual(ecc.get_exelist(), split_args(evalue))
+ with self.subTest(lang=lang, evar=evar):
+ try:
+ ecc = compiler_from_language(env, lang, MachineChoice.HOST)
+ except EnvironmentException:
+ # always raise in ci, we expect to have a valid ObjC and ObjC++ compiler of some kind
+ if is_ci():
+ self.fail(f'Could not find a compiler for {lang}')
+ if sys.version_info < (3, 11):
+ continue
+ self.skipTest(f'No valid compiler for {lang}.')
+ finally:
+ # Pop it so we don't use it for the next detection
+ evalue = os.environ.pop(evar)
+ assert ecc is not None, "Something went really wrong"
+ self.assertTrue(ecc.version)
+ elinker = detect_static_linker(env, ecc)
+ # Very rough/strict heuristics. Would never work for actual
+ # compiler detection, but should be ok for the tests.
+ ebase = os.path.basename(evalue)
+ if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')):
+ self.assertIsInstance(ecc, gnu)
+ self.assertIsInstance(elinker, ar)
+ elif 'clang-cl' in ebase:
+ self.assertIsInstance(ecc, clangcl)
+ self.assertIsInstance(elinker, lib)
+ elif 'clang' in ebase:
+ self.assertIsInstance(ecc, clang)
+ self.assertIsInstance(elinker, ar)
+ elif ebase.startswith('ic'):
+ self.assertIsInstance(ecc, intel)
+ self.assertIsInstance(elinker, ar)
+ elif ebase.startswith('cl'):
+ self.assertIsInstance(ecc, msvc)
+ self.assertIsInstance(elinker, lib)
+ else:
+ self.fail(f'Unknown compiler {evalue!r}')
+ # Check that we actually used the evalue correctly as the compiler
+ self.assertEqual(ecc.get_exelist(), split_args(evalue))
+
# Do auto-detection of compiler based on platform, PATH, etc.
- cc = compiler_from_language(env, lang, MachineChoice.HOST)
- self.assertTrue(cc.version)
- linker = detect_static_linker(env, cc)
- # Check compiler type
- if isinstance(cc, gnu):
- self.assertIsInstance(linker, ar)
- if is_osx():
- self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
- elif is_sunos():
- self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
- else:
- self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin)
- if isinstance(cc, clangcl):
- self.assertIsInstance(linker, lib)
- self.assertIsInstance(cc.linker, linkers.ClangClDynamicLinker)
- if isinstance(cc, clang):
- self.assertIsInstance(linker, ar)
- if is_osx():
- self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
- elif is_windows():
- # This is clang, not clang-cl. This can be either an
- # ld-like linker of link.exe-like linker (usually the
- # former for msys2, the latter otherwise)
- self.assertIsInstance(cc.linker, (linkers.MSVCDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
- elif is_sunos():
- self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
- else:
- self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin)
- if isinstance(cc, intel):
- self.assertIsInstance(linker, ar)
- if is_osx():
- self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
- elif is_windows():
- self.assertIsInstance(cc.linker, linkers.XilinkDynamicLinker)
- else:
- self.assertIsInstance(cc.linker, linkers.GnuDynamicLinker)
- if isinstance(cc, msvc):
- self.assertTrue(is_windows())
- self.assertIsInstance(linker, lib)
- self.assertEqual(cc.id, 'msvc')
- self.assertTrue(hasattr(cc, 'is_64'))
- self.assertIsInstance(cc.linker, linkers.MSVCDynamicLinker)
- # If we're on Windows CI, we know what the compiler will be
- if 'arch' in os.environ:
- if os.environ['arch'] == 'x64':
- self.assertTrue(cc.is_64)
+ with self.subTest(lang=lang):
+ try:
+ cc = compiler_from_language(env, lang, MachineChoice.HOST)
+ except EnvironmentException:
+ # always raise in ci, we expect to have a valid ObjC and ObjC++ compiler of some kind
+ if is_ci():
+ self.fail(f'Could not find a compiler for {lang}')
+ if sys.version_info < (3, 11):
+ continue
+ self.skipTest(f'No valid compiler for {lang}.')
+ assert cc is not None, "Something went really wrong"
+ self.assertTrue(cc.version)
+ linker = detect_static_linker(env, cc)
+ # Check compiler type
+ if isinstance(cc, gnu):
+ self.assertIsInstance(linker, ar)
+ if is_osx():
+ self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
+ elif is_sunos():
+ self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
else:
- self.assertFalse(cc.is_64)
+ self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin)
+ if isinstance(cc, clangcl):
+ self.assertIsInstance(linker, lib)
+ self.assertIsInstance(cc.linker, linkers.ClangClDynamicLinker)
+ if isinstance(cc, clang):
+ self.assertIsInstance(linker, ar)
+ if is_osx():
+ self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
+ elif is_windows():
+ # This is clang, not clang-cl. This can be either an
+ # ld-like linker of link.exe-like linker (usually the
+ # former for msys2, the latter otherwise)
+ self.assertIsInstance(cc.linker, (linkers.MSVCDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
+ elif is_sunos():
+ self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin))
+ else:
+ self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin)
+ if isinstance(cc, intel):
+ self.assertIsInstance(linker, ar)
+ if is_osx():
+ self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker)
+ elif is_windows():
+ self.assertIsInstance(cc.linker, linkers.XilinkDynamicLinker)
+ else:
+ self.assertIsInstance(cc.linker, linkers.GnuDynamicLinker)
+ if isinstance(cc, msvc):
+ self.assertTrue(is_windows())
+ self.assertIsInstance(linker, lib)
+ self.assertEqual(cc.id, 'msvc')
+ self.assertTrue(hasattr(cc, 'is_64'))
+ self.assertIsInstance(cc.linker, linkers.MSVCDynamicLinker)
+ # If we're on Windows CI, we know what the compiler will be
+ if 'arch' in os.environ:
+ if os.environ['arch'] == 'x64':
+ self.assertTrue(cc.is_64)
+ else:
+ self.assertFalse(cc.is_64)
+
# Set evar ourselves to a wrapper script that just calls the same
# exelist + some argument. This is meant to test that setting
# something like `ccache gcc -pipe` or `distcc ccache gcc` works.
- wrapper = os.path.join(testdir, 'compiler wrapper.py')
- wrappercc = python_command + [wrapper] + cc.get_exelist() + ['-DSOME_ARG']
- os.environ[evar] = ' '.join(quote_arg(w) for w in wrappercc)
-
- # Check static linker too
- wrapperlinker = python_command + [wrapper] + linker.get_exelist() + linker.get_always_args()
- os.environ['AR'] = ' '.join(quote_arg(w) for w in wrapperlinker)
-
- # Need a new env to re-run environment loading
- env = get_fake_env(testdir, self.builddir, self.prefix)
-
- wcc = compiler_from_language(env, lang, MachineChoice.HOST)
- wlinker = detect_static_linker(env, wcc)
- # Pop it so we don't use it for the next detection
- os.environ.pop('AR')
- # Must be the same type since it's a wrapper around the same exelist
- self.assertIs(type(cc), type(wcc))
- self.assertIs(type(linker), type(wlinker))
- # Ensure that the exelist is correct
- self.assertEqual(wcc.get_exelist(), wrappercc)
- self.assertEqual(wlinker.get_exelist(), wrapperlinker)
- # Ensure that the version detection worked correctly
- self.assertEqual(cc.version, wcc.version)
- if hasattr(cc, 'is_64'):
- self.assertEqual(cc.is_64, wcc.is_64)
+ with self.subTest('wrapper script', lang=lang):
+ wrapper = os.path.join(testdir, 'compiler wrapper.py')
+ wrappercc = python_command + [wrapper] + cc.get_exelist() + ['-DSOME_ARG']
+ os.environ[evar] = ' '.join(quote_arg(w) for w in wrappercc)
+
+ # Check static linker too
+ wrapperlinker = python_command + [wrapper] + linker.get_exelist() + linker.get_always_args()
+ os.environ['AR'] = ' '.join(quote_arg(w) for w in wrapperlinker)
+
+ # Need a new env to re-run environment loading
+ env = get_fake_env(testdir, self.builddir, self.prefix)
+
+ try:
+ wcc = compiler_from_language(env, lang, MachineChoice.HOST)
+ except EnvironmentException:
+ # always raise in ci, we expect to have a valid ObjC and ObjC++ compiler of some kind
+ if is_ci():
+ self.fail(f'Could not find a compiler for {lang}')
+ if sys.version_info < (3, 11):
+ continue
+ self.skipTest(f'No valid compiler for {lang}.')
+ wlinker = detect_static_linker(env, wcc)
+ del os.environ['AR']
+
+ # Must be the same type since it's a wrapper around the same exelist
+ self.assertIs(type(cc), type(wcc))
+ self.assertIs(type(linker), type(wlinker))
+
+ # Ensure that the exelist is correct
+ self.assertEqual(wcc.get_exelist(), wrappercc)
+ self.assertEqual(wlinker.get_exelist(), wrapperlinker)
+
+ # Ensure that the version detection worked correctly
+ self.assertEqual(cc.version, wcc.version)
+ if hasattr(cc, 'is_64'):
+ self.assertEqual(cc.is_64, wcc.is_64)
def test_always_prefer_c_compiler_for_asm(self):
testdir = os.path.join(self.common_test_dir, '133 c cpp and asm')
@@ -2498,10 +2574,9 @@ class AllPlatformTests(BasePlatformTests):
def test_flock(self):
exception_raised = False
with tempfile.TemporaryDirectory() as tdir:
- os.mkdir(os.path.join(tdir, 'meson-private'))
- with BuildDirLock(tdir):
+ with DirectoryLock(tdir, 'lock', DirectoryLockAction.FAIL, 'failed to lock directory'):
try:
- with BuildDirLock(tdir):
+ with DirectoryLock(tdir, 'lock', DirectoryLockAction.FAIL, 'expected failure'):
pass
except MesonException:
exception_raised = True
@@ -3611,6 +3686,8 @@ class AllPlatformTests(BasePlatformTests):
# Account for differences in output
res_wb = [i for i in res_wb if i['type'] != 'custom']
for i in res_wb:
+ if i['id'] == 'test1@exe':
+ i['build_by_default'] = 'unknown'
i['filename'] = [os.path.relpath(x, self.builddir) for x in i['filename']]
for k in ('install_filename', 'dependencies', 'win_subsystem'):
if k in i:
@@ -3729,7 +3806,7 @@ class AllPlatformTests(BasePlatformTests):
},
{
'name': 'bugDep1',
- 'required': True,
+ 'required': 'unknown',
'version': [],
'has_fallback': False,
'conditional': False
@@ -4452,6 +4529,10 @@ class AllPlatformTests(BasePlatformTests):
self.assertIn(f'TEST_C="{expected}"', o)
self.assertIn('export TEST_C', o)
+ cmd = self.meson_command + ['devenv', '-C', self.builddir] + python_command + ['-c', 'import sys; sys.exit(42)']
+ result = subprocess.run(cmd, encoding='utf-8')
+ self.assertEqual(result.returncode, 42)
+
def test_clang_format_check(self):
if self.backend is not Backend.ninja:
raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend')
@@ -5196,7 +5277,7 @@ class AllPlatformTests(BasePlatformTests):
'10/10': [10],
}.items():
output = self._run(self.mtest_command + ['--slice=' + arg])
- tests = sorted([ int(x[5:]) for x in re.findall(r'test-[0-9]*', output) ])
+ tests = sorted([ int(x) for x in re.findall(r'\n[ 0-9]+/[0-9]+ test-([0-9]*)', output) ])
self.assertEqual(tests, expectation)
for arg, expectation in {'': 'error: argument --slice: value does not conform to format \'SLICE/NUM_SLICES\'',
@@ -5216,7 +5297,7 @@ class AllPlatformTests(BasePlatformTests):
env = get_fake_env()
cc = detect_c_compiler(env, MachineChoice.HOST)
has_rsp = cc.linker.id in {
- 'ld.bfd', 'ld.gold', 'ld.lld', 'ld.mold', 'ld.qcld', 'ld.wasm',
+ 'ld.bfd', 'ld.eld', 'ld.gold', 'ld.lld', 'ld.mold', 'ld.qcld', 'ld.wasm',
'link', 'lld-link', 'mwldarm', 'mwldeppc', 'optlink', 'xilink',
}
self.assertEqual(cc.linker.get_accepts_rsp(), has_rsp)