aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-02-20 16:34:41 -0500
committerGitHub <noreply@github.com>2017-02-20 16:34:41 -0500
commit95248f0f26dc89efcbb62675bcb656e028c5444b (patch)
tree10d29ba0d1b49e440748d36b83965e9dabeaf008
parentd6614ba811e18e1b0f0d0cab502a7c770ee499c8 (diff)
parent7a671e21b9216503edca37c4c956aef38eb7f9aa (diff)
downloadmeson-95248f0f26dc89efcbb62675bcb656e028c5444b.zip
meson-95248f0f26dc89efcbb62675bcb656e028c5444b.tar.gz
meson-95248f0f26dc89efcbb62675bcb656e028c5444b.tar.bz2
Merge pull request #1408 from centricular/detectcompilersbetter
More fixes to compiler detection
-rw-r--r--.travis.yml4
-rw-r--r--authors.txt1
-rw-r--r--mesonbuild/compilers.py16
-rw-r--r--mesonbuild/environment.py244
-rwxr-xr-xrun_unittests.py103
-rw-r--r--test cases/objc/2 nsstring/meson.build3
-rw-r--r--test cases/unit/5 compiler detection/compiler wrapper.py6
-rw-r--r--test cases/unit/5 compiler detection/meson.build8
-rw-r--r--test cases/unit/5 compiler detection/trivial.c6
-rw-r--r--test cases/unit/5 compiler detection/trivial.cc6
-rw-r--r--test cases/unit/5 compiler detection/trivial.m5
-rw-r--r--test cases/unit/5 compiler detection/trivial.mm9
12 files changed, 238 insertions, 173 deletions
diff --git a/.travis.yml b/.travis.yml
index 2acb908..b3346a1 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 c75f84b..85d58c3 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 30f2608..8c2bb92 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 cbfa3ec..88dc4cf 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 16ff354..f800d03 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 bc997bc..ec496a2 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 0000000..fedd343
--- /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 0000000..5491c64
--- /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 0000000..24ac454
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+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 0000000..8aa907b
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.cc
@@ -0,0 +1,6 @@
+#include<iostream>
+
+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 0000000..f2e2315
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.m
@@ -0,0 +1,5 @@
+#import<stdio.h>
+
+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 0000000..927e810
--- /dev/null
+++ b/test cases/unit/5 compiler detection/trivial.mm
@@ -0,0 +1,9 @@
+#import<stdio.h>
+
+class MyClass {
+};
+
+int main(int argc, char **argv) {
+ return 0;
+}
+