diff options
Diffstat (limited to 'python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py')
-rw-r--r-- | python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py | 1271 |
1 files changed, 1271 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py new file mode 100644 index 000000000..2ef93792b --- /dev/null +++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py @@ -0,0 +1,1271 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from __future__ import absolute_import, print_function, unicode_literals + +import logging +import os + +from StringIO import StringIO + +from mozunit import main + +from common import BaseConfigureTest +from mozbuild.configure.util import Version +from mozbuild.util import memoize +from mozpack import path as mozpath +from test_toolchain_helpers import ( + FakeCompiler, + CompilerResult, +) + + +DEFAULT_C99 = { + '__STDC_VERSION__': '199901L', +} + +DEFAULT_C11 = { + '__STDC_VERSION__': '201112L', +} + +DEFAULT_CXX_97 = { + '__cplusplus': '199711L', +} + +DEFAULT_CXX_11 = { + '__cplusplus': '201103L', +} + +DEFAULT_CXX_14 = { + '__cplusplus': '201402L', +} + +SUPPORTS_GNU99 = { + '-std=gnu99': DEFAULT_C99, +} + +SUPPORTS_GNUXX11 = { + '-std=gnu++11': DEFAULT_CXX_11, +} + +SUPPORTS_CXX14 = { + '-std=c++14': DEFAULT_CXX_14, +} + + +@memoize +def GCC_BASE(version): + version = Version(version) + return FakeCompiler({ + '__GNUC__': version.major, + '__GNUC_MINOR__': version.minor, + '__GNUC_PATCHLEVEL__': version.patch, + '__STDC__': 1, + '__ORDER_LITTLE_ENDIAN__': 1234, + '__ORDER_BIG_ENDIAN__': 4321, + }) + + +@memoize +def GCC(version): + return GCC_BASE(version) + SUPPORTS_GNU99 + + +@memoize +def GXX(version): + return GCC_BASE(version) + DEFAULT_CXX_97 + SUPPORTS_GNUXX11 + + +GCC_4_7 = GCC('4.7.3') +GXX_4_7 = GXX('4.7.3') +GCC_4_9 = GCC('4.9.3') +GXX_4_9 = GXX('4.9.3') +GCC_5 = GCC('5.2.1') + DEFAULT_C11 +GXX_5 = GXX('5.2.1') + +GCC_PLATFORM_LITTLE_ENDIAN = { + '__BYTE_ORDER__': 1234, +} + +GCC_PLATFORM_BIG_ENDIAN = { + '__BYTE_ORDER__': 4321, +} + +GCC_PLATFORM_X86 = FakeCompiler(GCC_PLATFORM_LITTLE_ENDIAN) + { + None: { + '__i386__': 1, + }, + '-m64': { + '__i386__': False, + '__x86_64__': 1, + }, +} + +GCC_PLATFORM_X86_64 = FakeCompiler(GCC_PLATFORM_LITTLE_ENDIAN) + { + None: { + '__x86_64__': 1, + }, + '-m32': { + '__x86_64__': False, + '__i386__': 1, + }, +} + +GCC_PLATFORM_ARM = FakeCompiler(GCC_PLATFORM_LITTLE_ENDIAN) + { + '__arm__': 1, +} + +GCC_PLATFORM_LINUX = { + '__linux__': 1, +} + +GCC_PLATFORM_DARWIN = { + '__APPLE__': 1, +} + +GCC_PLATFORM_WIN = { + '_WIN32': 1, + 'WINNT': 1, +} + +GCC_PLATFORM_X86_LINUX = FakeCompiler(GCC_PLATFORM_X86, GCC_PLATFORM_LINUX) +GCC_PLATFORM_X86_64_LINUX = FakeCompiler(GCC_PLATFORM_X86_64, + GCC_PLATFORM_LINUX) +GCC_PLATFORM_ARM_LINUX = FakeCompiler(GCC_PLATFORM_ARM, GCC_PLATFORM_LINUX) +GCC_PLATFORM_X86_OSX = FakeCompiler(GCC_PLATFORM_X86, GCC_PLATFORM_DARWIN) +GCC_PLATFORM_X86_64_OSX = FakeCompiler(GCC_PLATFORM_X86_64, + GCC_PLATFORM_DARWIN) +GCC_PLATFORM_X86_WIN = FakeCompiler(GCC_PLATFORM_X86, GCC_PLATFORM_WIN) +GCC_PLATFORM_X86_64_WIN = FakeCompiler(GCC_PLATFORM_X86_64, GCC_PLATFORM_WIN) + + +@memoize +def CLANG_BASE(version): + version = Version(version) + return FakeCompiler({ + '__clang__': 1, + '__clang_major__': version.major, + '__clang_minor__': version.minor, + '__clang_patchlevel__': version.patch, + }) + + +@memoize +def CLANG(version): + return GCC_BASE('4.2.1') + CLANG_BASE(version) + SUPPORTS_GNU99 + + +@memoize +def CLANGXX(version): + return (GCC_BASE('4.2.1') + CLANG_BASE(version) + DEFAULT_CXX_97 + + SUPPORTS_GNUXX11) + + +CLANG_3_3 = CLANG('3.3.0') + DEFAULT_C99 +CLANGXX_3_3 = CLANGXX('3.3.0') +CLANG_3_6 = CLANG('3.6.2') + DEFAULT_C11 +CLANGXX_3_6 = CLANGXX('3.6.2') + { + '-std=gnu++11': { + '__has_feature(cxx_alignof)': '1', + }, +} + + +def CLANG_PLATFORM(gcc_platform): + base = { + '--target=x86_64-linux-gnu': GCC_PLATFORM_X86_64_LINUX[None], + '--target=x86_64-darwin11.2.0': GCC_PLATFORM_X86_64_OSX[None], + '--target=i686-linux-gnu': GCC_PLATFORM_X86_LINUX[None], + '--target=i686-darwin11.2.0': GCC_PLATFORM_X86_OSX[None], + '--target=arm-linux-gnu': GCC_PLATFORM_ARM_LINUX[None], + } + undo_gcc_platform = { + k: {symbol: False for symbol in gcc_platform[None]} + for k in base + } + return FakeCompiler(gcc_platform, undo_gcc_platform, base) + + +CLANG_PLATFORM_X86_LINUX = CLANG_PLATFORM(GCC_PLATFORM_X86_LINUX) +CLANG_PLATFORM_X86_64_LINUX = CLANG_PLATFORM(GCC_PLATFORM_X86_64_LINUX) +CLANG_PLATFORM_X86_OSX = CLANG_PLATFORM(GCC_PLATFORM_X86_OSX) +CLANG_PLATFORM_X86_64_OSX = CLANG_PLATFORM(GCC_PLATFORM_X86_64_OSX) +CLANG_PLATFORM_X86_WIN = CLANG_PLATFORM(GCC_PLATFORM_X86_WIN) +CLANG_PLATFORM_X86_64_WIN = CLANG_PLATFORM(GCC_PLATFORM_X86_64_WIN) + + +@memoize +def VS(version): + version = Version(version) + return FakeCompiler({ + None: { + '_MSC_VER': '%02d%02d' % (version.major, version.minor), + '_MSC_FULL_VER': '%02d%02d%05d' % (version.major, version.minor, + version.patch), + }, + '*.cpp': DEFAULT_CXX_97, + }) + + +VS_2013u2 = VS('18.00.30501') +VS_2013u3 = VS('18.00.30723') +VS_2015 = VS('19.00.23026') +VS_2015u1 = VS('19.00.23506') +VS_2015u2 = VS('19.00.23918') +VS_2015u3 = VS('19.00.24213') + +VS_PLATFORM_X86 = { + '_M_IX86': 600, + '_WIN32': 1, +} + +VS_PLATFORM_X86_64 = { + '_M_X64': 100, + '_WIN32': 1, + '_WIN64': 1, +} + +# Note: In reality, the -std=gnu* options are only supported when preceded by +# -Xclang. +CLANG_CL_3_9 = (CLANG_BASE('3.9.0') + VS('18.00.00000') + DEFAULT_C11 + + SUPPORTS_GNU99 + SUPPORTS_GNUXX11 + SUPPORTS_CXX14) + { + '*.cpp': { + '__STDC_VERSION__': False, + '__cplusplus': '201103L', + }, + '-fms-compatibility-version=19.00.24213': VS('19.00.24213')[None], +} + +CLANG_CL_PLATFORM_X86 = FakeCompiler(VS_PLATFORM_X86, GCC_PLATFORM_X86[None]) +CLANG_CL_PLATFORM_X86_64 = FakeCompiler(VS_PLATFORM_X86_64, GCC_PLATFORM_X86_64[None]) + + +class BaseToolchainTest(BaseConfigureTest): + def setUp(self): + super(BaseToolchainTest, self).setUp() + self.out = StringIO() + self.logger = logging.getLogger('BaseToolchainTest') + self.logger.setLevel(logging.ERROR) + self.handler = logging.StreamHandler(self.out) + self.logger.addHandler(self.handler) + + def tearDown(self): + self.logger.removeHandler(self.handler) + del self.handler + del self.out + super(BaseToolchainTest, self).tearDown() + + def do_toolchain_test(self, paths, results, args=[], environ={}): + '''Helper to test the toolchain checks from toolchain.configure. + + - `paths` is a dict associating compiler paths to FakeCompiler + definitions from above. + - `results` is a dict associating result variable names from + toolchain.configure (c_compiler, cxx_compiler, host_c_compiler, + host_cxx_compiler) with a result. + The result can either be an error string, or a CompilerResult + corresponding to the object returned by toolchain.configure checks. + When the results for host_c_compiler are identical to c_compiler, + they can be omitted. Likewise for host_cxx_compiler vs. + cxx_compiler. + ''' + environ = dict(environ) + if 'PATH' not in environ: + environ['PATH'] = os.pathsep.join( + mozpath.abspath(p) for p in ('/bin', '/usr/bin')) + + sandbox = self.get_sandbox(paths, {}, args, environ, + logger=self.logger) + + for var in ('c_compiler', 'cxx_compiler', 'host_c_compiler', + 'host_cxx_compiler'): + if var in results: + result = results[var] + elif var.startswith('host_'): + result = results.get(var[5:], {}) + else: + result = {} + try: + self.out.truncate(0) + compiler = sandbox._value_for(sandbox[var]) + # Add var on both ends to make it clear which of the + # variables is failing the test when that happens. + self.assertEquals((var, compiler), (var, result)) + except SystemExit: + self.assertEquals((var, result), + (var, self.out.getvalue().strip())) + return + + +class LinuxToolchainTest(BaseToolchainTest): + PATHS = { + '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_64_LINUX, + '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_64_LINUX, + '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_LINUX, + '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_64_LINUX, + '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_LINUX, + '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_64_LINUX, + '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64_LINUX, + } + GCC_4_7_RESULT = ('Only GCC 4.8 or newer is supported ' + '(found version 4.7.3).') + GXX_4_7_RESULT = GCC_4_7_RESULT + GCC_4_9_RESULT = CompilerResult( + flags=['-std=gnu99'], + version='4.9.3', + type='gcc', + compiler='/usr/bin/gcc', + language='C', + ) + GXX_4_9_RESULT = CompilerResult( + flags=['-std=gnu++11'], + version='4.9.3', + type='gcc', + compiler='/usr/bin/g++', + language='C++', + ) + GCC_5_RESULT = CompilerResult( + flags=['-std=gnu99'], + version='5.2.1', + type='gcc', + compiler='/usr/bin/gcc-5', + language='C', + ) + GXX_5_RESULT = CompilerResult( + flags=['-std=gnu++11'], + version='5.2.1', + type='gcc', + compiler='/usr/bin/g++-5', + language='C++', + ) + CLANG_3_3_RESULT = CompilerResult( + flags=[], + version='3.3.0', + type='clang', + compiler='/usr/bin/clang-3.3', + language='C', + ) + CLANGXX_3_3_RESULT = 'Only clang/llvm 3.6 or newer is supported.' + CLANG_3_6_RESULT = CompilerResult( + flags=['-std=gnu99'], + version='3.6.2', + type='clang', + compiler='/usr/bin/clang', + language='C', + ) + CLANGXX_3_6_RESULT = CompilerResult( + flags=['-std=gnu++11'], + version='3.6.2', + type='clang', + compiler='/usr/bin/clang++', + language='C++', + ) + + def test_gcc(self): + # We'll try gcc and clang, and find gcc first. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': self.GXX_4_9_RESULT, + }) + + def test_unsupported_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_7_RESULT, + }, environ={ + 'CC': 'gcc-4.7', + 'CXX': 'g++-4.7', + }) + + # Maybe this should be reporting the mismatched version instead. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': self.GXX_4_7_RESULT, + }, environ={ + 'CXX': 'g++-4.7', + }) + + def test_overridden_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_5_RESULT, + 'cxx_compiler': self.GXX_5_RESULT, + }, environ={ + 'CC': 'gcc-5', + 'CXX': 'g++-5', + }) + + def test_guess_cxx(self): + # When CXX is not set, we guess it from CC. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_5_RESULT, + 'cxx_compiler': self.GXX_5_RESULT, + }, environ={ + 'CC': 'gcc-5', + }) + + def test_mismatched_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': ( + 'The target C compiler is version 4.9.3, while the target ' + 'C++ compiler is version 5.2.1. Need to use the same compiler ' + 'version.'), + }, environ={ + 'CXX': 'g++-5', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': self.GXX_4_9_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': ( + 'The host C compiler is version 4.9.3, while the host ' + 'C++ compiler is version 5.2.1. Need to use the same compiler ' + 'version.'), + }, environ={ + 'HOST_CXX': 'g++-5', + }) + + def test_mismatched_compiler(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': ( + 'The target C compiler is gcc, while the target C++ compiler ' + 'is clang. Need to use the same compiler suite.'), + }, environ={ + 'CXX': 'clang++', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': self.GXX_4_9_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': ( + 'The host C compiler is gcc, while the host C++ compiler ' + 'is clang. Need to use the same compiler suite.'), + }, environ={ + 'HOST_CXX': 'clang++', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': '`%s` is not a C compiler.' + % mozpath.abspath('/usr/bin/g++'), + }, environ={ + 'CC': 'g++', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': '`%s` is not a C++ compiler.' + % mozpath.abspath('/usr/bin/gcc'), + }, environ={ + 'CXX': 'gcc', + }) + + def test_clang(self): + # We'll try gcc and clang, but since there is no gcc (gcc-x.y doesn't + # count), find clang. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) not in ('gcc', 'g++') + } + self.do_toolchain_test(paths, { + 'c_compiler': self.CLANG_3_6_RESULT, + 'cxx_compiler': self.CLANGXX_3_6_RESULT, + }) + + def test_guess_cxx_clang(self): + # When CXX is not set, we guess it from CC. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'compiler': '/usr/bin/clang-3.6', + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'compiler': '/usr/bin/clang++-3.6', + }, + }, environ={ + 'CC': 'clang-3.6', + }) + + def test_unsupported_clang(self): + # clang 3.3 C compiler is perfectly fine, but we need more for C++. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_3_RESULT, + 'cxx_compiler': self.CLANGXX_3_3_RESULT, + }, environ={ + 'CC': 'clang-3.3', + 'CXX': 'clang++-3.3', + }) + + def test_no_supported_compiler(self): + # Even if there are gcc-x.y or clang-x.y compilers available, we + # don't try them. This could be considered something to improve. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) not in ('gcc', 'g++', 'clang', 'clang++') + } + self.do_toolchain_test(paths, { + 'c_compiler': 'Cannot find the target C compiler', + }) + + def test_absolute_path(self): + paths = dict(self.PATHS) + paths.update({ + '/opt/clang/bin/clang': paths['/usr/bin/clang'], + '/opt/clang/bin/clang++': paths['/usr/bin/clang++'], + }) + result = { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'compiler': '/opt/clang/bin/clang', + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'compiler': '/opt/clang/bin/clang++' + }, + } + self.do_toolchain_test(paths, result, environ={ + 'CC': '/opt/clang/bin/clang', + 'CXX': '/opt/clang/bin/clang++', + }) + # With CXX guess too. + self.do_toolchain_test(paths, result, environ={ + 'CC': '/opt/clang/bin/clang', + }) + + def test_atypical_name(self): + paths = dict(self.PATHS) + paths.update({ + '/usr/bin/afl-clang-fast': paths['/usr/bin/clang'], + '/usr/bin/afl-clang-fast++': paths['/usr/bin/clang++'], + }) + self.do_toolchain_test(paths, { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'compiler': '/usr/bin/afl-clang-fast', + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'compiler': '/usr/bin/afl-clang-fast++', + }, + }, environ={ + 'CC': 'afl-clang-fast', + 'CXX': 'afl-clang-fast++', + }) + + def test_mixed_compilers(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT, + 'cxx_compiler': self.CLANGXX_3_6_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }, environ={ + 'CC': 'clang', + 'HOST_CC': 'gcc', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT, + 'cxx_compiler': self.CLANGXX_3_6_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }, environ={ + 'CC': 'clang', + 'CXX': 'clang++', + 'HOST_CC': 'gcc', + }) + + +class LinuxSimpleCrossToolchainTest(BaseToolchainTest): + TARGET = 'i686-pc-linux-gnu' + PATHS = LinuxToolchainTest.PATHS + GCC_4_9_RESULT = LinuxToolchainTest.GCC_4_9_RESULT + GXX_4_9_RESULT = LinuxToolchainTest.GXX_4_9_RESULT + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + + def test_cross_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT + { + 'flags': ['-m32'] + }, + 'cxx_compiler': self.GXX_4_9_RESULT + { + 'flags': ['-m32'] + }, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }) + + def test_cross_clang(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'flags': ['--target=i686-linux-gnu'], + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'flags': ['--target=i686-linux-gnu'], + }, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'clang', + }) + + +class LinuxX86_64CrossToolchainTest(BaseToolchainTest): + HOST = 'i686-pc-linux-gnu' + TARGET = 'x86_64-pc-linux-gnu' + PATHS = { + '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_LINUX, + '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_LINUX, + '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_LINUX, + '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_LINUX, + } + GCC_4_9_RESULT = LinuxToolchainTest.GCC_4_9_RESULT + GXX_4_9_RESULT = LinuxToolchainTest.GXX_4_9_RESULT + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + + def test_cross_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_9_RESULT + { + 'flags': ['-m64'] + }, + 'cxx_compiler': self.GXX_4_9_RESULT + { + 'flags': ['-m64'] + }, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }) + + def test_cross_clang(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'flags': ['--target=x86_64-linux-gnu'], + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'flags': ['--target=x86_64-linux-gnu'], + }, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'clang', + }) + + +class OSXToolchainTest(BaseToolchainTest): + HOST = 'x86_64-apple-darwin11.2.0' + PATHS = { + '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_64_OSX, + '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_64_OSX, + '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_OSX, + '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_64_OSX, + '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_OSX, + '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_64_OSX, + '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64_OSX, + } + CLANG_3_3_RESULT = LinuxToolchainTest.CLANG_3_3_RESULT + CLANGXX_3_3_RESULT = LinuxToolchainTest.CLANGXX_3_3_RESULT + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + GCC_4_7_RESULT = LinuxToolchainTest.GCC_4_7_RESULT + GCC_5_RESULT = LinuxToolchainTest.GCC_5_RESULT + GXX_5_RESULT = LinuxToolchainTest.GXX_5_RESULT + + def test_clang(self): + # We only try clang because gcc is known not to work. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT, + 'cxx_compiler': self.CLANGXX_3_6_RESULT, + }) + + def test_not_gcc(self): + # We won't pick GCC if it's the only thing available. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) not in ('clang', 'clang++') + } + self.do_toolchain_test(paths, { + 'c_compiler': 'Cannot find the target C compiler', + }) + + def test_unsupported_clang(self): + # clang 3.3 C compiler is perfectly fine, but we need more for C++. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_3_RESULT, + 'cxx_compiler': self.CLANGXX_3_3_RESULT, + }, environ={ + 'CC': 'clang-3.3', + 'CXX': 'clang++-3.3', + }) + + def test_forced_gcc(self): + # GCC can still be forced if the user really wants it. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_5_RESULT, + 'cxx_compiler': self.GXX_5_RESULT, + }, environ={ + 'CC': 'gcc-5', + 'CXX': 'g++-5', + }) + + def test_forced_unsupported_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_7_RESULT, + }, environ={ + 'CC': 'gcc-4.7', + 'CXX': 'g++-4.7', + }) + + +class WindowsToolchainTest(BaseToolchainTest): + HOST = 'i686-pc-mingw32' + + # For the purpose of this test, it doesn't matter that the paths are not + # real Windows paths. + PATHS = { + '/opt/VS_2013u2/bin/cl': VS_2013u2 + VS_PLATFORM_X86, + '/opt/VS_2013u3/bin/cl': VS_2013u3 + VS_PLATFORM_X86, + '/opt/VS_2015/bin/cl': VS_2015 + VS_PLATFORM_X86, + '/opt/VS_2015u1/bin/cl': VS_2015u1 + VS_PLATFORM_X86, + '/opt/VS_2015u2/bin/cl': VS_2015u2 + VS_PLATFORM_X86, + '/usr/bin/cl': VS_2015u3 + VS_PLATFORM_X86, + '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86, + '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_WIN, + '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_WIN, + '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_WIN, + '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_WIN, + '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_WIN, + '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_WIN, + '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_WIN, + '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_WIN, + '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_WIN, + '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_WIN, + '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_WIN, + '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_WIN, + } + + VS_2013u2_RESULT = ( + 'This version (18.00.30501) of the MSVC compiler is not supported.\n' + 'You must install Visual C++ 2015 Update 3 or newer in order to build.\n' + 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') + VS_2013u3_RESULT = ( + 'This version (18.00.30723) of the MSVC compiler is not supported.\n' + 'You must install Visual C++ 2015 Update 3 or newer in order to build.\n' + 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') + VS_2015_RESULT = ( + 'This version (19.00.23026) of the MSVC compiler is not supported.\n' + 'You must install Visual C++ 2015 Update 3 or newer in order to build.\n' + 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') + VS_2015u1_RESULT = ( + 'This version (19.00.23506) of the MSVC compiler is not supported.\n' + 'You must install Visual C++ 2015 Update 3 or newer in order to build.\n' + 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') + VS_2015u2_RESULT = ( + 'This version (19.00.23918) of the MSVC compiler is not supported.\n' + 'You must install Visual C++ 2015 Update 3 or newer in order to build.\n' + 'See https://developer.mozilla.org/en/Windows_Build_Prerequisites') + VS_2015u3_RESULT = CompilerResult( + flags=[], + version='19.00.24213', + type='msvc', + compiler='/usr/bin/cl', + language='C', + ) + VSXX_2015u3_RESULT = CompilerResult( + flags=[], + version='19.00.24213', + type='msvc', + compiler='/usr/bin/cl', + language='C++', + ) + CLANG_CL_3_9_RESULT = CompilerResult( + flags=['-Xclang', '-std=gnu99', + '-fms-compatibility-version=19.00.24213', '-fallback'], + version='19.00.24213', + type='clang-cl', + compiler='/usr/bin/clang-cl', + language='C', + ) + CLANGXX_CL_3_9_RESULT = CompilerResult( + flags=['-Xclang', '-std=c++14', + '-fms-compatibility-version=19.00.24213', '-fallback'], + version='19.00.24213', + type='clang-cl', + compiler='/usr/bin/clang-cl', + language='C++', + ) + CLANG_3_3_RESULT = LinuxToolchainTest.CLANG_3_3_RESULT + CLANGXX_3_3_RESULT = LinuxToolchainTest.CLANGXX_3_3_RESULT + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + GCC_4_7_RESULT = LinuxToolchainTest.GCC_4_7_RESULT + GCC_4_9_RESULT = LinuxToolchainTest.GCC_4_9_RESULT + GXX_4_9_RESULT = LinuxToolchainTest.GXX_4_9_RESULT + GCC_5_RESULT = LinuxToolchainTest.GCC_5_RESULT + GXX_5_RESULT = LinuxToolchainTest.GXX_5_RESULT + + # VS2015u3 or greater is required. + def test_msvc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2015u3_RESULT, + 'cxx_compiler': self.VSXX_2015u3_RESULT, + }) + + def test_unsupported_msvc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2015u2_RESULT, + }, environ={ + 'CC': '/opt/VS_2015u2/bin/cl', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2015u1_RESULT, + }, environ={ + 'CC': '/opt/VS_2015u1/bin/cl', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2015_RESULT, + }, environ={ + 'CC': '/opt/VS_2015/bin/cl', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2013u3_RESULT, + }, environ={ + 'CC': '/opt/VS_2013u3/bin/cl', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.VS_2013u2_RESULT, + }, environ={ + 'CC': '/opt/VS_2013u2/bin/cl', + }) + + def test_clang_cl(self): + # We'll pick clang-cl if msvc can't be found. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) != 'cl' + } + self.do_toolchain_test(paths, { + 'c_compiler': self.CLANG_CL_3_9_RESULT, + 'cxx_compiler': self.CLANGXX_CL_3_9_RESULT, + }) + + def test_gcc(self): + # We'll pick GCC if msvc and clang-cl can't be found. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) not in ('cl', 'clang-cl') + } + self.do_toolchain_test(paths, { + 'c_compiler': self.GCC_4_9_RESULT, + 'cxx_compiler': self.GXX_4_9_RESULT, + }) + + def test_overridden_unsupported_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.GCC_4_7_RESULT, + }, environ={ + 'CC': 'gcc-4.7', + 'CXX': 'g++-4.7', + }) + + def test_clang(self): + # We'll pick clang if nothing else is found. + paths = { + k: v for k, v in self.PATHS.iteritems() + if os.path.basename(k) not in ('cl', 'clang-cl', 'gcc') + } + self.do_toolchain_test(paths, { + 'c_compiler': self.CLANG_3_6_RESULT, + 'cxx_compiler': self.CLANGXX_3_6_RESULT, + }) + + def test_overridden_unsupported_clang(self): + # clang 3.3 C compiler is perfectly fine, but we need more for C++. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_3_RESULT, + 'cxx_compiler': self.CLANGXX_3_3_RESULT, + }, environ={ + 'CC': 'clang-3.3', + 'CXX': 'clang++-3.3', + }) + + def test_cannot_cross(self): + paths = { + '/usr/bin/cl': VS_2015u3 + VS_PLATFORM_X86_64, + } + self.do_toolchain_test(paths, { + 'c_compiler': ('Target C compiler target CPU (x86_64) ' + 'does not match --target CPU (i686)'), + }) + + +class Windows64ToolchainTest(WindowsToolchainTest): + HOST = 'x86_64-pc-mingw32' + + # For the purpose of this test, it doesn't matter that the paths are not + # real Windows paths. + PATHS = { + '/opt/VS_2013u2/bin/cl': VS_2013u2 + VS_PLATFORM_X86_64, + '/opt/VS_2013u3/bin/cl': VS_2013u3 + VS_PLATFORM_X86_64, + '/opt/VS_2015/bin/cl': VS_2015 + VS_PLATFORM_X86_64, + '/opt/VS_2015u1/bin/cl': VS_2015u1 + VS_PLATFORM_X86_64, + '/opt/VS_2015u2/bin/cl': VS_2015u2 + VS_PLATFORM_X86_64, + '/usr/bin/cl': VS_2015u3 + VS_PLATFORM_X86_64, + '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86_64, + '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_64_WIN, + '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_64_WIN, + '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_WIN, + '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_64_WIN, + '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_64_WIN, + '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_64_WIN, + '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64_WIN, + } + + def test_cannot_cross(self): + paths = { + '/usr/bin/cl': VS_2015u3 + VS_PLATFORM_X86, + } + self.do_toolchain_test(paths, { + 'c_compiler': ('Target C compiler target CPU (x86) ' + 'does not match --target CPU (x86_64)'), + }) + + +class LinuxCrossCompileToolchainTest(BaseToolchainTest): + TARGET = 'arm-unknown-linux-gnu' + PATHS = { + '/usr/bin/arm-linux-gnu-gcc': GCC_4_9 + GCC_PLATFORM_ARM_LINUX, + '/usr/bin/arm-linux-gnu-g++': GXX_4_9 + GCC_PLATFORM_ARM_LINUX, + '/usr/bin/arm-linux-gnu-gcc-4.7': GCC_4_7 + GCC_PLATFORM_ARM_LINUX, + '/usr/bin/arm-linux-gnu-g++-4.7': GXX_4_7 + GCC_PLATFORM_ARM_LINUX, + '/usr/bin/arm-linux-gnu-gcc-5': GCC_5 + GCC_PLATFORM_ARM_LINUX, + '/usr/bin/arm-linux-gnu-g++-5': GXX_5 + GCC_PLATFORM_ARM_LINUX, + } + PATHS.update(LinuxToolchainTest.PATHS) + ARM_GCC_4_7_RESULT = LinuxToolchainTest.GXX_4_7_RESULT + ARM_GCC_5_RESULT = LinuxToolchainTest.GCC_5_RESULT + { + 'compiler': '/usr/bin/arm-linux-gnu-gcc-5', + } + ARM_GXX_5_RESULT = LinuxToolchainTest.GXX_5_RESULT + { + 'compiler': '/usr/bin/arm-linux-gnu-g++-5', + } + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + GCC_4_9_RESULT = LinuxToolchainTest.GCC_4_9_RESULT + GXX_4_9_RESULT = LinuxToolchainTest.GXX_4_9_RESULT + + little_endian = FakeCompiler(GCC_PLATFORM_LINUX, + GCC_PLATFORM_LITTLE_ENDIAN) + big_endian = FakeCompiler(GCC_PLATFORM_LINUX, GCC_PLATFORM_BIG_ENDIAN) + + PLATFORMS = { + 'i686-pc-linux-gnu': GCC_PLATFORM_X86_LINUX, + 'x86_64-pc-linux-gnu': GCC_PLATFORM_X86_64_LINUX, + 'arm-unknown-linux-gnu': GCC_PLATFORM_ARM_LINUX, + 'aarch64-unknown-linux-gnu': little_endian + { + '__aarch64__': 1, + }, + 'ia64-unknown-linux-gnu': little_endian + { + '__ia64__': 1, + }, + 's390x-unknown-linux-gnu': big_endian + { + '__s390x__': 1, + '__s390__': 1, + }, + 's390-unknown-linux-gnu': big_endian + { + '__s390__': 1, + }, + 'powerpc64-unknown-linux-gnu': big_endian + { + None: { + '__powerpc64__': 1, + '__powerpc__': 1, + }, + '-m32': { + '__powerpc64__': False, + }, + }, + 'powerpc-unknown-linux-gnu': big_endian + { + None: { + '__powerpc__': 1, + }, + '-m64': { + '__powerpc64__': 1, + }, + }, + 'alpha-unknown-linux-gnu': little_endian + { + '__alpha__': 1, + }, + 'hppa-unknown-linux-gnu': big_endian + { + '__hppa__': 1, + }, + 'sparc64-unknown-linux-gnu': big_endian + { + None: { + '__arch64__': 1, + '__sparc__': 1, + }, + '-m32': { + '__arch64__': False, + }, + }, + 'sparc-unknown-linux-gnu': big_endian + { + None: { + '__sparc__': 1, + }, + '-m64': { + '__arch64__': 1, + }, + }, + 'mips64-unknown-linux-gnuabi64': big_endian + { + '__mips64': 1, + '__mips__': 1, + }, + 'mips-unknown-linux-gnu': big_endian + { + '__mips__': 1, + }, + } + + PLATFORMS['powerpc64le-unknown-linux-gnu'] = \ + PLATFORMS['powerpc64-unknown-linux-gnu'] + GCC_PLATFORM_LITTLE_ENDIAN + PLATFORMS['mips64el-unknown-linux-gnuabi64'] = \ + PLATFORMS['mips64-unknown-linux-gnuabi64'] + GCC_PLATFORM_LITTLE_ENDIAN + PLATFORMS['mipsel-unknown-linux-gnu'] = \ + PLATFORMS['mips-unknown-linux-gnu'] + GCC_PLATFORM_LITTLE_ENDIAN + + def do_test_cross_gcc_32_64(self, host, target): + self.HOST = host + self.TARGET = target + paths = { + '/usr/bin/gcc': GCC_4_9 + self.PLATFORMS[host], + '/usr/bin/g++': GXX_4_9 + self.PLATFORMS[host], + } + cross_flags = { + 'flags': ['-m64' if '64' in target else '-m32'] + } + self.do_toolchain_test(paths, { + 'c_compiler': self.GCC_4_9_RESULT + cross_flags, + 'cxx_compiler': self.GXX_4_9_RESULT + cross_flags, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }) + self.HOST = LinuxCrossCompileToolchainTest.HOST + self.TARGET = LinuxCrossCompileToolchainTest.TARGET + + def test_cross_x86_x64(self): + self.do_test_cross_gcc_32_64( + 'i686-pc-linux-gnu', 'x86_64-pc-linux-gnu') + self.do_test_cross_gcc_32_64( + 'x86_64-pc-linux-gnu', 'i686-pc-linux-gnu') + + def test_cross_sparc_sparc64(self): + self.do_test_cross_gcc_32_64( + 'sparc-unknown-linux-gnu', 'sparc64-unknown-linux-gnu') + self.do_test_cross_gcc_32_64( + 'sparc64-unknown-linux-gnu', 'sparc-unknown-linux-gnu') + + def test_cross_ppc_ppc64(self): + self.do_test_cross_gcc_32_64( + 'powerpc-unknown-linux-gnu', 'powerpc64-unknown-linux-gnu') + self.do_test_cross_gcc_32_64( + 'powerpc64-unknown-linux-gnu', 'powerpc-unknown-linux-gnu') + + def do_test_cross_gcc(self, host, target): + self.HOST = host + self.TARGET = target + host_cpu = host.split('-')[0] + cpu, manufacturer, os = target.split('-', 2) + toolchain_prefix = '/usr/bin/%s-%s' % (cpu, os) + paths = { + '/usr/bin/gcc': GCC_4_9 + self.PLATFORMS[host], + '/usr/bin/g++': GXX_4_9 + self.PLATFORMS[host], + } + self.do_toolchain_test(paths, { + 'c_compiler': ('Target C compiler target CPU (%s) ' + 'does not match --target CPU (%s)' + % (host_cpu, cpu)), + }) + + paths.update({ + '%s-gcc' % toolchain_prefix: GCC_4_9 + self.PLATFORMS[target], + '%s-g++' % toolchain_prefix: GXX_4_9 + self.PLATFORMS[target], + }) + self.do_toolchain_test(paths, { + 'c_compiler': self.GCC_4_9_RESULT + { + 'compiler': '%s-gcc' % toolchain_prefix, + }, + 'cxx_compiler': self.GXX_4_9_RESULT + { + 'compiler': '%s-g++' % toolchain_prefix, + }, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }) + self.HOST = LinuxCrossCompileToolchainTest.HOST + self.TARGET = LinuxCrossCompileToolchainTest.TARGET + + def test_cross_gcc_misc(self): + for target in self.PLATFORMS: + if not target.endswith('-pc-linux-gnu'): + self.do_test_cross_gcc('x86_64-pc-linux-gnu', target) + + def test_cannot_cross(self): + self.TARGET = 'mipsel-unknown-linux-gnu' + + paths = { + '/usr/bin/gcc': GCC_4_9 + self.PLATFORMS['mips-unknown-linux-gnu'], + '/usr/bin/g++': GXX_4_9 + self.PLATFORMS['mips-unknown-linux-gnu'], + } + self.do_toolchain_test(paths, { + 'c_compiler': ('Target C compiler target endianness (big) ' + 'does not match --target endianness (little)'), + }) + self.TARGET = LinuxCrossCompileToolchainTest.TARGET + + def test_overridden_cross_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.ARM_GCC_5_RESULT, + 'cxx_compiler': self.ARM_GXX_5_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }, environ={ + 'CC': 'arm-linux-gnu-gcc-5', + 'CXX': 'arm-linux-gnu-g++-5', + }) + + def test_overridden_unsupported_cross_gcc(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.ARM_GCC_4_7_RESULT, + }, environ={ + 'CC': 'arm-linux-gnu-gcc-4.7', + 'CXX': 'arm-linux-gnu-g++-4.7', + }) + + def test_guess_cross_cxx(self): + # When CXX is not set, we guess it from CC. + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.ARM_GCC_5_RESULT, + 'cxx_compiler': self.ARM_GXX_5_RESULT, + 'host_c_compiler': self.GCC_4_9_RESULT, + 'host_cxx_compiler': self.GXX_4_9_RESULT, + }, environ={ + 'CC': 'arm-linux-gnu-gcc-5', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.ARM_GCC_5_RESULT, + 'cxx_compiler': self.ARM_GXX_5_RESULT, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'arm-linux-gnu-gcc-5', + 'HOST_CC': 'clang', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.ARM_GCC_5_RESULT, + 'cxx_compiler': self.ARM_GXX_5_RESULT, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'arm-linux-gnu-gcc-5', + 'CXX': 'arm-linux-gnu-g++-5', + 'HOST_CC': 'clang', + }) + + def test_cross_clang(self): + cross_clang_result = self.CLANG_3_6_RESULT + { + 'flags': ['--target=arm-linux-gnu'], + } + cross_clangxx_result = self.CLANGXX_3_6_RESULT + { + 'flags': ['--target=arm-linux-gnu'], + } + self.do_toolchain_test(self.PATHS, { + 'c_compiler': cross_clang_result, + 'cxx_compiler': cross_clangxx_result, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'clang', + 'HOST_CC': 'clang', + }) + + self.do_toolchain_test(self.PATHS, { + 'c_compiler': cross_clang_result, + 'cxx_compiler': cross_clangxx_result, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'clang', + }) + + def test_cross_atypical_clang(self): + paths = dict(self.PATHS) + paths.update({ + '/usr/bin/afl-clang-fast': paths['/usr/bin/clang'], + '/usr/bin/afl-clang-fast++': paths['/usr/bin/clang++'], + }) + afl_clang_result = self.CLANG_3_6_RESULT + { + 'compiler': '/usr/bin/afl-clang-fast', + } + afl_clangxx_result = self.CLANGXX_3_6_RESULT + { + 'compiler': '/usr/bin/afl-clang-fast++', + } + self.do_toolchain_test(paths, { + 'c_compiler': afl_clang_result + { + 'flags': ['--target=arm-linux-gnu'], + }, + 'cxx_compiler': afl_clangxx_result + { + 'flags': ['--target=arm-linux-gnu'], + }, + 'host_c_compiler': afl_clang_result, + 'host_cxx_compiler': afl_clangxx_result, + }, environ={ + 'CC': 'afl-clang-fast', + 'CXX': 'afl-clang-fast++', + }) + + +class OSXCrossToolchainTest(BaseToolchainTest): + TARGET = 'i686-apple-darwin11.2.0' + PATHS = LinuxToolchainTest.PATHS + CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT + CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT + + def test_osx_cross(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': self.CLANG_3_6_RESULT + { + 'flags': ['--target=i686-darwin11.2.0'], + }, + 'cxx_compiler': self.CLANGXX_3_6_RESULT + { + 'flags': ['--target=i686-darwin11.2.0'], + }, + 'host_c_compiler': self.CLANG_3_6_RESULT, + 'host_cxx_compiler': self.CLANGXX_3_6_RESULT, + }, environ={ + 'CC': 'clang', + }) + + def test_cannot_osx_cross(self): + self.do_toolchain_test(self.PATHS, { + 'c_compiler': 'Target C compiler target kernel (Linux) does not ' + 'match --target kernel (Darwin)', + }, environ={ + 'CC': 'gcc', + }) + + +if __name__ == '__main__': + main() |