diff --git a/.travis.yml b/.travis.yml index 2acb908d0..b3346a163 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,5 +40,5 @@ script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:yakkety > Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX ./run_tests.py -- $MESON_ARGS"; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py -- $MESON_ARGS"; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) OBJC=$CC OBJCXX=$CXX ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi diff --git a/authors.txt b/authors.txt index c75f84bb3..85d58c368 100644 --- a/authors.txt +++ b/authors.txt @@ -65,3 +65,4 @@ Mike Sinkovsky Dima Krasner Fabio Porcedda Rodrigo Lourenço +Sebastian Stang diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 30f260836..8c2bb9272 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -2404,11 +2404,9 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): class GnuObjCCompiler(GnuCompiler, ObjCCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, defines=None): + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) - # 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) + GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], @@ -2416,11 +2414,9 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler): class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, defines=None): + def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) - # 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) + GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], @@ -2549,13 +2545,13 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler): class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): - GnuObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + GnuObjCCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper) ClangCompiler.__init__(self, cltype) self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): - GnuObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + GnuObjCPPCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper) ClangCompiler.__init__(self, cltype) self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index cbfa3ec47..88dc4cf70 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -367,10 +367,13 @@ class Environment: # We ignore Cygwin for now, and treat it as a standard GCC return GCC_STANDARD - def detect_c_compiler(self, want_cross): - evar = 'CC' + def _get_compilers(self, lang, evar, want_cross): + ''' + The list of compilers is detected in the exact same way for + C, C++, ObjC, ObjC++, Fortran so consolidate it here. + ''' if self.is_cross_build() and want_cross: - compilers = mesonlib.stringintlistify(self.cross_info.config['binaries']['c']) + compilers = [mesonlib.stringlistify(self.cross_info.config['binaries'][lang])] ccache = [] is_cross = True if self.cross_info.need_exe_wrapper(): @@ -378,22 +381,33 @@ class Environment: else: exe_wrap = [] elif evar in os.environ: - compilers = shlex.split(os.environ[evar]) + compilers = [shlex.split(os.environ[evar])] ccache = [] is_cross = False exe_wrap = None else: - compilers = self.default_c + compilers = getattr(self, 'default_' + lang) ccache = self.detect_ccache() is_cross = False exe_wrap = None + return compilers, ccache, is_cross, exe_wrap + + def _handle_compiler_exceptions(self, exceptions, compilers): + errmsg = 'Unknown compiler(s): ' + str(compilers) + if exceptions: + errmsg += '\nThe follow exceptions were encountered:' + for (c, e) in exceptions.items(): + errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) + raise EnvironmentException(errmsg) + + def _detect_c_or_cpp_compiler(self, lang, evar, want_cross): popen_exceptions = {} + compilers, ccache, is_cross, exe_wrap = self._get_compilers(lang, evar, want_cross) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] try: - basename = os.path.basename(compiler[-1]).lower() - if basename == 'cl' or basename == 'cl.exe': + if 'cl' in compiler or 'cl.exe' in compiler: arg = '/?' else: arg = '--version' @@ -409,49 +423,39 @@ class Environment: continue gtype = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuCCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) + cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler + return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) if 'clang' in out: if 'Apple' in out or for_darwin(want_cross, self): cltype = CLANG_OSX else: cltype = CLANG_STANDARD - return ClangCCompiler(ccache + compiler, version, cltype, is_cross, exe_wrap) + cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler + return cls(ccache + compiler, version, cltype, is_cross, exe_wrap) if 'Microsoft' in out or 'Microsoft' in err: # Visual Studio prints version number to stderr but # everything else to stdout. Why? Lord only knows. version = search_version(err) - return VisualStudioCCompiler(compiler, version, is_cross, exe_wrap) + cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler + return cls(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): ' + str(compilers) - if popen_exceptions: - errmsg += '\nThe follow exceptions were encountered:' - for (c, e) in popen_exceptions.items(): - errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) - raise EnvironmentException(errmsg) + cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler + return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap) + self._handle_compiler_exceptions(popen_exceptions, compilers) + + def detect_c_compiler(self, want_cross): + return self._detect_c_or_cpp_compiler('c', 'CC', want_cross) + + def detect_cpp_compiler(self, want_cross): + return self._detect_c_or_cpp_compiler('cpp', 'CXX', want_cross) def detect_fortran_compiler(self, want_cross): - evar = 'FC' - if self.is_cross_build() and want_cross: - compilers = meson.stringlistify(self.cross_info['fortran']) - is_cross = True - if self.cross_info.need_exe_wrapper(): - exe_wrap = self.cross_info.get('exe_wrapper', None) - else: - exe_wrap = [] - elif evar in os.environ: - compilers = os.environ[evar].split() - is_cross = False - exe_wrap = None - else: - compilers = self.default_fortran - is_cross = False - exe_wrap = None popen_exceptions = {} + compilers, ccache, is_cross, exe_wrap = self._get_compilers('fortran', 'FC', want_cross) for compiler in compilers: - if not isinstance(compiler, list): + if isinstance(compiler, str): compiler = [compiler] for arg in ['--version', '-V']: try: @@ -492,12 +496,7 @@ class Environment: if 'NAG Fortran' in err: return NAGFortranCompiler(compiler, version, is_cross, exe_wrap) - errmsg = 'Unknown compiler(s): ' + str(compilers) - if popen_exceptions: - errmsg += '\nThe follow exceptions were encountered:' - for (c, e) in popen_exceptions.items(): - errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) - raise EnvironmentException(errmsg) + self._handle_compiler_exceptions(popen_exceptions, compilers) def get_scratch_dir(self): return self.scratch_dir @@ -506,40 +505,16 @@ class Environment: path = os.path.split(__file__)[0] return os.path.join(path, 'depfixer.py') - def detect_cpp_compiler(self, want_cross): - evar = 'CXX' - if self.is_cross_build() and want_cross: - compilers = mesonlib.stringlistify(self.cross_info.config['binaries']['cpp']) - ccache = [] - is_cross = True - if self.cross_info.need_exe_wrapper(): - exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None) - else: - exe_wrap = [] - elif evar in os.environ: - compilers = shlex.split(os.environ[evar]) - ccache = [] - is_cross = False - exe_wrap = None - else: - compilers = self.default_cpp - ccache = self.detect_ccache() - is_cross = False - exe_wrap = None + def detect_objc_compiler(self, want_cross): popen_exceptions = {} + compilers, ccache, is_cross, exe_wrap = self._get_compilers('objc', 'OBJC', want_cross) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] - basename = os.path.basename(compiler[-1]).lower() - if basename == 'cl' or basename == 'cl.exe': - arg = '/?' - else: - arg = '--version' try: - p, out, err = Popen_safe(compiler + [arg]) - except OSError as e: + p, out, err = Popen_safe(compiler + ['--version']) + except OSError: popen_exceptions[' '.join(compiler + [arg])] = e - continue version = search_version(out) if 'Free Software Foundation' in out: defines = self.get_gnu_compiler_defines(compiler) @@ -548,75 +523,37 @@ class Environment: continue gtype = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuCPPCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) - if 'clang' in out: - if 'Apple' in out: - cltype = CLANG_OSX - else: - cltype = CLANG_STANDARD - return ClangCPPCompiler(ccache + compiler, version, cltype, is_cross, exe_wrap) - 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:' - for (c, e) in popen_exceptions.items(): - errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) - raise EnvironmentException(errmsg) - - def detect_objc_compiler(self, want_cross): - if self.is_cross_build() and want_cross: - exelist = mesonlib.stringlistify(self.cross_info['objc']) - is_cross = True - if self.cross_info.need_exe_wrapper(): - exe_wrap = self.cross_info.get('exe_wrapper', None) - else: - exe_wrap = [] - else: - exelist = self.get_objc_compiler_exelist() - is_cross = False - exe_wrap = None - try: - p, out, err = Popen_safe(exelist + ['--version']) - except OSError: - raise EnvironmentException('Could not execute ObjC compiler "%s"' % ' '.join(exelist)) - version = search_version(out) - if 'Free Software Foundation' in out: - defines = self.get_gnu_compiler_defines(exelist) - version = self.get_gnu_version_from_defines(defines) - return GnuObjCCompiler(exelist, version, is_cross, exe_wrap, defines) - if out.startswith('Apple LLVM'): - return ClangObjCCompiler(exelist, version, CLANG_OSX, is_cross, exe_wrap) - raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + return GnuObjCCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) + if out.startswith('Apple LLVM'): + return ClangObjCCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap) + if out.startswith('clang'): + return ClangObjCCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap) + self._handle_compiler_exceptions(popen_exceptions, compilers) def detect_objcpp_compiler(self, want_cross): - if self.is_cross_build() and want_cross: - exelist = mesonlib.stringlistify(self.cross_info['objcpp']) - is_cross = True - if self.cross_info.need_exe_wrapper(): - exe_wrap = self.cross_info.get('exe_wrapper', None) - else: - exe_wrap = [] - else: - exelist = self.get_objcpp_compiler_exelist() - is_cross = False - exe_wrap = None - try: - p, out, err = Popen_safe(exelist + ['--version']) - except OSError: - raise EnvironmentException('Could not execute ObjC++ compiler "%s"' % ' '.join(exelist)) - version = search_version(out) - if 'Free Software Foundation' in out: - defines = self.get_gnu_compiler_defines(exelist) - return GnuObjCPPCompiler(exelist, version, is_cross, exe_wrap, defines) - if out.startswith('Apple LLVM'): - return ClangObjCPPCompiler(exelist, version, CLANG_OSX, is_cross, exe_wrap) - raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') + popen_exceptions = {} + compilers, ccache, is_cross, exe_wrap = self._get_compilers('objcpp', 'OBJCXX', want_cross) + for compiler in compilers: + if isinstance(compiler, str): + compiler = [compiler] + try: + p, out, err = Popen_safe(compiler + ['--version']) + except OSError: + popen_exceptions[' '.join(compiler + [arg])] = e + version = search_version(out) + if 'Free Software Foundation' in out: + defines = self.get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[compiler] = 'no pre-processor defines' + continue + gtype = self.get_gnu_compiler_type(defines) + version = self.get_gnu_version_from_defines(defines) + return GnuObjCPPCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines) + if out.startswith('Apple LLVM'): + return ClangObjCPPCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap) + if out.startswith('clang'): + return ClangObjCPPCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap) + self._handle_compiler_exceptions(popen_exceptions, compilers) def detect_java_compiler(self): exelist = ['javac'] @@ -711,30 +648,31 @@ class Environment: def detect_static_linker(self, compiler): if compiler.is_cross: linker = self.cross_info.config['binaries']['ar'] + if isinstance(linker, str): + linker = [linker] else: evar = 'AR' if evar in os.environ: - linker = os.environ[evar].strip() + linker = shlex.split(os.environ[evar]) elif isinstance(compiler, VisualStudioCCompiler): - linker = self.vs_static_linker + linker = [self.vs_static_linker] else: - linker = self.default_static_linker - basename = os.path.basename(linker).lower() - if basename == 'lib' or basename == 'lib.exe': + linker = [self.default_static_linker] + if 'lib' in linker or 'lib.exe' in linker: arg = '/?' else: arg = '--version' try: - p, out, err = Popen_safe([linker, arg]) + p, out, err = Popen_safe(linker + [arg]) except OSError: - raise EnvironmentException('Could not execute static linker "%s".' % linker) + raise EnvironmentException('Could not execute static linker "%s".' % ' '.join(linker)) if '/OUT:' in out or '/OUT:' in err: - return VisualStudioLinker([linker]) + return VisualStudioLinker(linker) if p.returncode == 0: - return ArLinker([linker]) + return ArLinker(linker) if p.returncode == 1 and err.startswith('usage'): # OSX - return ArLinker([linker]) - raise EnvironmentException('Unknown static linker "%s"' % linker) + return ArLinker(linker) + raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linker)) def detect_ccache(self): try: @@ -747,20 +685,6 @@ class Environment: cmdlist = [] return cmdlist - def get_objc_compiler_exelist(self): - ccachelist = self.detect_ccache() - evar = 'OBJCC' - if evar in os.environ: - return os.environ[evar].split() - return ccachelist + self.default_objc - - def get_objcpp_compiler_exelist(self): - ccachelist = self.detect_ccache() - evar = 'OBJCXX' - if evar in os.environ: - return os.environ[evar].split() - return ccachelist + self.default_objcpp - def get_source_dir(self): return self.source_dir diff --git a/run_unittests.py b/run_unittests.py index 16ff35488..f800d0390 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -24,7 +24,7 @@ from pathlib import PurePath import mesonbuild.compilers import mesonbuild.environment import mesonbuild.mesonlib -from mesonbuild.mesonlib import is_windows +from mesonbuild.mesonlib import is_windows, is_osx from mesonbuild.environment import detect_ninja, Environment from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram @@ -725,6 +725,107 @@ class AllPlatformTests(BasePlatformTests): # target internal dependency include_directories: source dir self.assertPathBasenameEqual(incs[7], 'sub1') + def test_compiler_detection(self): + ''' + Test that automatic compiler detection and setting from the environment + both work just fine. This is needed because while running project tests + and other unit tests, we always read CC/CXX/etc from the environment. + ''' + gnu = mesonbuild.compilers.GnuCompiler + clang = mesonbuild.compilers.ClangCompiler + intel = mesonbuild.compilers.IntelCompiler + msvc = mesonbuild.compilers.VisualStudioCCompiler + ar = mesonbuild.compilers.ArLinker + lib = mesonbuild.compilers.VisualStudioLinker + langs = [('c', 'CC'), ('cpp', 'CXX')] + if not is_windows(): + langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] + testdir = os.path.join(self.unit_test_dir, '5 compiler detection') + env = Environment(testdir, self.builddir, self.meson_command, + get_fake_options(self.prefix), []) + for lang, evar in langs: + evalue = None + # Detect with evar and do sanity checks on that + if evar in os.environ: + ecc = getattr(env, 'detect_{}_compiler'.format(lang))(False) + elinker = env.detect_static_linker(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. + if os.path.basename(evalue).startswith('g'): + self.assertIsInstance(ecc, gnu) + self.assertIsInstance(elinker, ar) + elif 'clang' in os.path.basename(evalue): + self.assertIsInstance(ecc, clang) + self.assertIsInstance(elinker, ar) + elif os.path.basename(evalue).startswith('ic'): + self.assertIsInstance(ecc, intel) + self.assertIsInstance(elinker, ar) + elif os.path.basename(evalue).startswith('cl'): + self.assertIsInstance(ecc, msvc) + self.assertIsInstance(elinker, lib) + else: + raise AssertionError('Unknown compiler {!r}'.format(evalue)) + # Check that we actually used the evalue correctly as the compiler + self.assertEqual(ecc.get_exelist(), shlex.split(evalue)) + # Do auto-detection of compiler based on platform, PATH, etc. + cc = getattr(env, 'detect_{}_compiler'.format(lang))(False) + linker = env.detect_static_linker(cc) + # Check compiler type + if isinstance(cc, gnu): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_OSX) + elif is_windows(): + self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_MINGW) + else: + self.assertEqual(cc.gcc_type, mesonbuild.compilers.GCC_STANDARD) + if isinstance(cc, clang): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_OSX) + elif is_windows(): + # Not implemented yet + self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_WIN) + else: + self.assertEqual(cc.clang_type, mesonbuild.compilers.CLANG_STANDARD) + if isinstance(cc, intel): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_OSX) + elif is_windows(): + self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_WIN) + else: + self.assertEqual(cc.icc_type, mesonbuild.compilers.ICC_STANDARD) + if isinstance(cc, msvc): + self.assertTrue(is_windows()) + self.assertIsInstance(linker, lib) + self.assertEqual(cc.id, 'msvc') + # 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 = [sys.executable, wrapper] + cc.get_exelist() + cc.get_always_args() + wrappercc_s = '' + for w in wrappercc: + wrappercc_s += shlex.quote(w) + ' ' + os.environ[evar] = wrappercc_s + wcc = getattr(env, 'detect_{}_compiler'.format(lang))(False) + # Check static linker too + wrapperlinker = [sys.executable, wrapper] + linker.get_exelist() + linker.get_always_args() + wrapperlinker_s = '' + for w in wrapperlinker: + wrapperlinker_s += shlex.quote(w) + ' ' + os.environ['AR'] = wrapperlinker_s + wlinker = env.detect_static_linker(wcc) + # 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) + class WindowsTests(BasePlatformTests): ''' diff --git a/test cases/objc/2 nsstring/meson.build b/test cases/objc/2 nsstring/meson.build index bc997bce3..ec496a2ae 100644 --- a/test cases/objc/2 nsstring/meson.build +++ b/test cases/objc/2 nsstring/meson.build @@ -4,6 +4,9 @@ if host_machine.system() == 'darwin' dep = dependency('appleframeworks', modules : 'foundation') else dep = dependency('gnustep') + if host_machine.system() == 'linux' and meson.get_compiler('objc').get_id() == 'clang' + error('MESON_SKIP_TEST: GNUstep is broken on Linux with Clang') + endif endif exe = executable('stringprog', 'stringprog.m', dependencies : dep) test('stringtest', exe) diff --git a/test cases/unit/5 compiler detection/compiler wrapper.py b/test cases/unit/5 compiler detection/compiler wrapper.py new file mode 100644 index 000000000..fedd3434d --- /dev/null +++ b/test cases/unit/5 compiler detection/compiler wrapper.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import subprocess + +sys.exit(subprocess.call(sys.argv[1:])) diff --git a/test cases/unit/5 compiler detection/meson.build b/test cases/unit/5 compiler detection/meson.build new file mode 100644 index 000000000..5491c6447 --- /dev/null +++ b/test cases/unit/5 compiler detection/meson.build @@ -0,0 +1,8 @@ +project('trivial test', + ['c', 'cpp', 'objc', 'objcpp'], + meson_version : '>=0.27.0') + +executable('trivialc', 'trivial.c') +executable('trivialcpp', 'trivial.cpp') +executable('trivialobjc', 'trivial.m') +executable('trivialobjcpp', 'trivial.mm') diff --git a/test cases/unit/5 compiler detection/trivial.c b/test cases/unit/5 compiler detection/trivial.c new file mode 100644 index 000000000..24ac454c3 --- /dev/null +++ b/test cases/unit/5 compiler detection/trivial.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + printf("Trivial test is working.\n"); + return 0; +} diff --git a/test cases/unit/5 compiler detection/trivial.cc b/test cases/unit/5 compiler detection/trivial.cc new file mode 100644 index 000000000..8aa907b48 --- /dev/null +++ b/test cases/unit/5 compiler detection/trivial.cc @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + std::cout << "C++ seems to be working." << std::endl; + return 0; +} diff --git a/test cases/unit/5 compiler detection/trivial.m b/test cases/unit/5 compiler detection/trivial.m new file mode 100644 index 000000000..f2e2315eb --- /dev/null +++ b/test cases/unit/5 compiler detection/trivial.m @@ -0,0 +1,5 @@ +#import + +int main(int argc, char **argv) { + return 0; +} \ No newline at end of file diff --git a/test cases/unit/5 compiler detection/trivial.mm b/test cases/unit/5 compiler detection/trivial.mm new file mode 100644 index 000000000..927e8104e --- /dev/null +++ b/test cases/unit/5 compiler detection/trivial.mm @@ -0,0 +1,9 @@ +#import + +class MyClass { +}; + +int main(int argc, char **argv) { + return 0; +} +