Merge pull request #1408 from centricular/detectcompilersbetter
More fixes to compiler detection
This commit is contained in:
commit
95248f0f26
|
@ -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 FROM jpakkane/mesonci:yakkety > Dockerfile; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> 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 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" == "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) ./run_tests.py --backend=ninja -- $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
|
||||||
|
|
|
@ -65,3 +65,4 @@ Mike Sinkovsky
|
||||||
Dima Krasner
|
Dima Krasner
|
||||||
Fabio Porcedda
|
Fabio Porcedda
|
||||||
Rodrigo Lourenço
|
Rodrigo Lourenço
|
||||||
|
Sebastian Stang
|
||||||
|
|
|
@ -2404,11 +2404,9 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
|
||||||
|
|
||||||
class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
|
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)
|
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
|
GnuCompiler.__init__(self, gcc_type, defines)
|
||||||
# if this breaks your use case.
|
|
||||||
GnuCompiler.__init__(self, GCC_STANDARD, defines)
|
|
||||||
default_warn_args = ['-Wall', '-Winvalid-pch']
|
default_warn_args = ['-Wall', '-Winvalid-pch']
|
||||||
self.warn_args = {'1': default_warn_args,
|
self.warn_args = {'1': default_warn_args,
|
||||||
'2': default_warn_args + ['-Wextra'],
|
'2': default_warn_args + ['-Wextra'],
|
||||||
|
@ -2416,11 +2414,9 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
|
||||||
|
|
||||||
class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
|
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)
|
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
|
GnuCompiler.__init__(self, gcc_type, defines)
|
||||||
# if this breaks your use case.
|
|
||||||
GnuCompiler.__init__(self, GCC_STANDARD, defines)
|
|
||||||
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
|
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
|
||||||
self.warn_args = {'1': default_warn_args,
|
self.warn_args = {'1': default_warn_args,
|
||||||
'2': default_warn_args + ['-Wextra'],
|
'2': default_warn_args + ['-Wextra'],
|
||||||
|
@ -2549,13 +2545,13 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
|
||||||
|
|
||||||
class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler):
|
class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler):
|
||||||
def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
|
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)
|
ClangCompiler.__init__(self, cltype)
|
||||||
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
|
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
|
||||||
|
|
||||||
class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler):
|
class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler):
|
||||||
def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None):
|
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)
|
ClangCompiler.__init__(self, cltype)
|
||||||
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
|
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage']
|
||||||
|
|
||||||
|
|
|
@ -367,10 +367,13 @@ class Environment:
|
||||||
# We ignore Cygwin for now, and treat it as a standard GCC
|
# We ignore Cygwin for now, and treat it as a standard GCC
|
||||||
return GCC_STANDARD
|
return GCC_STANDARD
|
||||||
|
|
||||||
def detect_c_compiler(self, want_cross):
|
def _get_compilers(self, lang, evar, want_cross):
|
||||||
evar = 'CC'
|
'''
|
||||||
|
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:
|
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 = []
|
ccache = []
|
||||||
is_cross = True
|
is_cross = True
|
||||||
if self.cross_info.need_exe_wrapper():
|
if self.cross_info.need_exe_wrapper():
|
||||||
|
@ -378,22 +381,33 @@ class Environment:
|
||||||
else:
|
else:
|
||||||
exe_wrap = []
|
exe_wrap = []
|
||||||
elif evar in os.environ:
|
elif evar in os.environ:
|
||||||
compilers = shlex.split(os.environ[evar])
|
compilers = [shlex.split(os.environ[evar])]
|
||||||
ccache = []
|
ccache = []
|
||||||
is_cross = False
|
is_cross = False
|
||||||
exe_wrap = None
|
exe_wrap = None
|
||||||
else:
|
else:
|
||||||
compilers = self.default_c
|
compilers = getattr(self, 'default_' + lang)
|
||||||
ccache = self.detect_ccache()
|
ccache = self.detect_ccache()
|
||||||
is_cross = False
|
is_cross = False
|
||||||
exe_wrap = None
|
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 = {}
|
popen_exceptions = {}
|
||||||
|
compilers, ccache, is_cross, exe_wrap = self._get_compilers(lang, evar, want_cross)
|
||||||
for compiler in compilers:
|
for compiler in compilers:
|
||||||
if isinstance(compiler, str):
|
if isinstance(compiler, str):
|
||||||
compiler = [compiler]
|
compiler = [compiler]
|
||||||
try:
|
try:
|
||||||
basename = os.path.basename(compiler[-1]).lower()
|
if 'cl' in compiler or 'cl.exe' in compiler:
|
||||||
if basename == 'cl' or basename == 'cl.exe':
|
|
||||||
arg = '/?'
|
arg = '/?'
|
||||||
else:
|
else:
|
||||||
arg = '--version'
|
arg = '--version'
|
||||||
|
@ -409,49 +423,39 @@ class Environment:
|
||||||
continue
|
continue
|
||||||
gtype = self.get_gnu_compiler_type(defines)
|
gtype = self.get_gnu_compiler_type(defines)
|
||||||
version = self.get_gnu_version_from_defines(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 'clang' in out:
|
||||||
if 'Apple' in out or for_darwin(want_cross, self):
|
if 'Apple' in out or for_darwin(want_cross, self):
|
||||||
cltype = CLANG_OSX
|
cltype = CLANG_OSX
|
||||||
else:
|
else:
|
||||||
cltype = CLANG_STANDARD
|
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:
|
if 'Microsoft' in out or 'Microsoft' in err:
|
||||||
# Visual Studio prints version number to stderr but
|
# Visual Studio prints version number to stderr but
|
||||||
# everything else to stdout. Why? Lord only knows.
|
# everything else to stdout. Why? Lord only knows.
|
||||||
version = search_version(err)
|
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:
|
if '(ICC)' in out:
|
||||||
# TODO: add microsoft add check OSX
|
# TODO: add microsoft add check OSX
|
||||||
inteltype = ICC_STANDARD
|
inteltype = ICC_STANDARD
|
||||||
return IntelCCompiler(ccache + compiler, version, inteltype, is_cross, exe_wrap)
|
cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
|
||||||
errmsg = 'Unknown compiler(s): ' + str(compilers)
|
return cls(ccache + compiler, version, inteltype, is_cross, exe_wrap)
|
||||||
if popen_exceptions:
|
self._handle_compiler_exceptions(popen_exceptions, compilers)
|
||||||
errmsg += '\nThe follow exceptions were encountered:'
|
|
||||||
for (c, e) in popen_exceptions.items():
|
def detect_c_compiler(self, want_cross):
|
||||||
errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e)
|
return self._detect_c_or_cpp_compiler('c', 'CC', want_cross)
|
||||||
raise EnvironmentException(errmsg)
|
|
||||||
|
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):
|
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 = {}
|
popen_exceptions = {}
|
||||||
|
compilers, ccache, is_cross, exe_wrap = self._get_compilers('fortran', 'FC', want_cross)
|
||||||
for compiler in compilers:
|
for compiler in compilers:
|
||||||
if not isinstance(compiler, list):
|
if isinstance(compiler, str):
|
||||||
compiler = [compiler]
|
compiler = [compiler]
|
||||||
for arg in ['--version', '-V']:
|
for arg in ['--version', '-V']:
|
||||||
try:
|
try:
|
||||||
|
@ -492,12 +496,7 @@ class Environment:
|
||||||
|
|
||||||
if 'NAG Fortran' in err:
|
if 'NAG Fortran' in err:
|
||||||
return NAGFortranCompiler(compiler, version, is_cross, exe_wrap)
|
return NAGFortranCompiler(compiler, version, is_cross, exe_wrap)
|
||||||
errmsg = 'Unknown compiler(s): ' + str(compilers)
|
self._handle_compiler_exceptions(popen_exceptions, 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 get_scratch_dir(self):
|
def get_scratch_dir(self):
|
||||||
return self.scratch_dir
|
return self.scratch_dir
|
||||||
|
@ -506,40 +505,16 @@ class Environment:
|
||||||
path = os.path.split(__file__)[0]
|
path = os.path.split(__file__)[0]
|
||||||
return os.path.join(path, 'depfixer.py')
|
return os.path.join(path, 'depfixer.py')
|
||||||
|
|
||||||
def detect_cpp_compiler(self, want_cross):
|
def detect_objc_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
|
|
||||||
popen_exceptions = {}
|
popen_exceptions = {}
|
||||||
|
compilers, ccache, is_cross, exe_wrap = self._get_compilers('objc', 'OBJC', want_cross)
|
||||||
for compiler in compilers:
|
for compiler in compilers:
|
||||||
if isinstance(compiler, str):
|
if isinstance(compiler, str):
|
||||||
compiler = [compiler]
|
compiler = [compiler]
|
||||||
basename = os.path.basename(compiler[-1]).lower()
|
|
||||||
if basename == 'cl' or basename == 'cl.exe':
|
|
||||||
arg = '/?'
|
|
||||||
else:
|
|
||||||
arg = '--version'
|
|
||||||
try:
|
try:
|
||||||
p, out, err = Popen_safe(compiler + [arg])
|
p, out, err = Popen_safe(compiler + ['--version'])
|
||||||
except OSError as e:
|
except OSError:
|
||||||
popen_exceptions[' '.join(compiler + [arg])] = e
|
popen_exceptions[' '.join(compiler + [arg])] = e
|
||||||
continue
|
|
||||||
version = search_version(out)
|
version = search_version(out)
|
||||||
if 'Free Software Foundation' in out:
|
if 'Free Software Foundation' in out:
|
||||||
defines = self.get_gnu_compiler_defines(compiler)
|
defines = self.get_gnu_compiler_defines(compiler)
|
||||||
|
@ -548,75 +523,37 @@ class Environment:
|
||||||
continue
|
continue
|
||||||
gtype = self.get_gnu_compiler_type(defines)
|
gtype = self.get_gnu_compiler_type(defines)
|
||||||
version = self.get_gnu_version_from_defines(defines)
|
version = self.get_gnu_version_from_defines(defines)
|
||||||
return GnuCPPCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
|
return GnuObjCCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
|
||||||
if 'clang' in out:
|
if out.startswith('Apple LLVM'):
|
||||||
if 'Apple' in out:
|
return ClangObjCCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap)
|
||||||
cltype = CLANG_OSX
|
if out.startswith('clang'):
|
||||||
else:
|
return ClangObjCCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap)
|
||||||
cltype = CLANG_STANDARD
|
self._handle_compiler_exceptions(popen_exceptions, compilers)
|
||||||
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) + '"')
|
|
||||||
|
|
||||||
def detect_objcpp_compiler(self, want_cross):
|
def detect_objcpp_compiler(self, want_cross):
|
||||||
if self.is_cross_build() and want_cross:
|
popen_exceptions = {}
|
||||||
exelist = mesonlib.stringlistify(self.cross_info['objcpp'])
|
compilers, ccache, is_cross, exe_wrap = self._get_compilers('objcpp', 'OBJCXX', want_cross)
|
||||||
is_cross = True
|
for compiler in compilers:
|
||||||
if self.cross_info.need_exe_wrapper():
|
if isinstance(compiler, str):
|
||||||
exe_wrap = self.cross_info.get('exe_wrapper', None)
|
compiler = [compiler]
|
||||||
else:
|
try:
|
||||||
exe_wrap = []
|
p, out, err = Popen_safe(compiler + ['--version'])
|
||||||
else:
|
except OSError:
|
||||||
exelist = self.get_objcpp_compiler_exelist()
|
popen_exceptions[' '.join(compiler + [arg])] = e
|
||||||
is_cross = False
|
version = search_version(out)
|
||||||
exe_wrap = None
|
if 'Free Software Foundation' in out:
|
||||||
try:
|
defines = self.get_gnu_compiler_defines(compiler)
|
||||||
p, out, err = Popen_safe(exelist + ['--version'])
|
if not defines:
|
||||||
except OSError:
|
popen_exceptions[compiler] = 'no pre-processor defines'
|
||||||
raise EnvironmentException('Could not execute ObjC++ compiler "%s"' % ' '.join(exelist))
|
continue
|
||||||
version = search_version(out)
|
gtype = self.get_gnu_compiler_type(defines)
|
||||||
if 'Free Software Foundation' in out:
|
version = self.get_gnu_version_from_defines(defines)
|
||||||
defines = self.get_gnu_compiler_defines(exelist)
|
return GnuObjCPPCompiler(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
|
||||||
return GnuObjCPPCompiler(exelist, version, is_cross, exe_wrap, defines)
|
if out.startswith('Apple LLVM'):
|
||||||
if out.startswith('Apple LLVM'):
|
return ClangObjCPPCompiler(ccache + compiler, version, CLANG_OSX, is_cross, exe_wrap)
|
||||||
return ClangObjCPPCompiler(exelist, version, CLANG_OSX, is_cross, exe_wrap)
|
if out.startswith('clang'):
|
||||||
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
|
return ClangObjCPPCompiler(ccache + compiler, version, CLANG_STANDARD, is_cross, exe_wrap)
|
||||||
|
self._handle_compiler_exceptions(popen_exceptions, compilers)
|
||||||
|
|
||||||
def detect_java_compiler(self):
|
def detect_java_compiler(self):
|
||||||
exelist = ['javac']
|
exelist = ['javac']
|
||||||
|
@ -711,30 +648,31 @@ class Environment:
|
||||||
def detect_static_linker(self, compiler):
|
def detect_static_linker(self, compiler):
|
||||||
if compiler.is_cross:
|
if compiler.is_cross:
|
||||||
linker = self.cross_info.config['binaries']['ar']
|
linker = self.cross_info.config['binaries']['ar']
|
||||||
|
if isinstance(linker, str):
|
||||||
|
linker = [linker]
|
||||||
else:
|
else:
|
||||||
evar = 'AR'
|
evar = 'AR'
|
||||||
if evar in os.environ:
|
if evar in os.environ:
|
||||||
linker = os.environ[evar].strip()
|
linker = shlex.split(os.environ[evar])
|
||||||
elif isinstance(compiler, VisualStudioCCompiler):
|
elif isinstance(compiler, VisualStudioCCompiler):
|
||||||
linker = self.vs_static_linker
|
linker = [self.vs_static_linker]
|
||||||
else:
|
else:
|
||||||
linker = self.default_static_linker
|
linker = [self.default_static_linker]
|
||||||
basename = os.path.basename(linker).lower()
|
if 'lib' in linker or 'lib.exe' in linker:
|
||||||
if basename == 'lib' or basename == 'lib.exe':
|
|
||||||
arg = '/?'
|
arg = '/?'
|
||||||
else:
|
else:
|
||||||
arg = '--version'
|
arg = '--version'
|
||||||
try:
|
try:
|
||||||
p, out, err = Popen_safe([linker, arg])
|
p, out, err = Popen_safe(linker + [arg])
|
||||||
except OSError:
|
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:
|
if '/OUT:' in out or '/OUT:' in err:
|
||||||
return VisualStudioLinker([linker])
|
return VisualStudioLinker(linker)
|
||||||
if p.returncode == 0:
|
if p.returncode == 0:
|
||||||
return ArLinker([linker])
|
return ArLinker(linker)
|
||||||
if p.returncode == 1 and err.startswith('usage'): # OSX
|
if p.returncode == 1 and err.startswith('usage'): # OSX
|
||||||
return ArLinker([linker])
|
return ArLinker(linker)
|
||||||
raise EnvironmentException('Unknown static linker "%s"' % linker)
|
raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linker))
|
||||||
|
|
||||||
def detect_ccache(self):
|
def detect_ccache(self):
|
||||||
try:
|
try:
|
||||||
|
@ -747,20 +685,6 @@ class Environment:
|
||||||
cmdlist = []
|
cmdlist = []
|
||||||
return 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):
|
def get_source_dir(self):
|
||||||
return self.source_dir
|
return self.source_dir
|
||||||
|
|
||||||
|
|
103
run_unittests.py
103
run_unittests.py
|
@ -24,7 +24,7 @@ from pathlib import PurePath
|
||||||
import mesonbuild.compilers
|
import mesonbuild.compilers
|
||||||
import mesonbuild.environment
|
import mesonbuild.environment
|
||||||
import mesonbuild.mesonlib
|
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.environment import detect_ninja, Environment
|
||||||
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
|
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
|
||||||
|
|
||||||
|
@ -725,6 +725,107 @@ class AllPlatformTests(BasePlatformTests):
|
||||||
# target internal dependency include_directories: source dir
|
# target internal dependency include_directories: source dir
|
||||||
self.assertPathBasenameEqual(incs[7], 'sub1')
|
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):
|
class WindowsTests(BasePlatformTests):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -4,6 +4,9 @@ if host_machine.system() == 'darwin'
|
||||||
dep = dependency('appleframeworks', modules : 'foundation')
|
dep = dependency('appleframeworks', modules : 'foundation')
|
||||||
else
|
else
|
||||||
dep = dependency('gnustep')
|
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
|
endif
|
||||||
exe = executable('stringprog', 'stringprog.m', dependencies : dep)
|
exe = executable('stringprog', 'stringprog.m', dependencies : dep)
|
||||||
test('stringtest', exe)
|
test('stringtest', exe)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
sys.exit(subprocess.call(sys.argv[1:]))
|
|
@ -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')
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
printf("Trivial test is working.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include<iostream>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::cout << "C++ seems to be working." << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import<stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#import<stdio.h>
|
||||||
|
|
||||||
|
class MyClass {
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue