--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -190,16 +190,18 @@ def try_preprocess(compiler, language, s
os.close(fd)
cmd = compiler + ['-E', path]
return check_cmd_output(*cmd)
finally:
os.remove(path)
@imports(_from='mozbuild.configure.constants', _import='CompilerType')
+@imports(_from='mozbuild.configure.constants',
+ _import='CPU_preprocessor_checks')
@imports(_from='textwrap', _import='dedent')
def get_compiler_info(compiler, language):
'''Returns information about the given `compiler` (command line in the
form of a list or tuple), in the given `language`.
The returned information includes:
- the compiler type (msvc, clang-cl, clang or gcc)
- the compiler version
@@ -244,16 +246,30 @@ def get_compiler_info(compiler, language
%cplusplus __cplusplus
#elif __STDC_VERSION__
%STDC_VERSION __STDC_VERSION__
#elif __STDC__
%STDC_VERSION 198900L
#endif
''')
+ # While we're doing some preprocessing, we might as well do some more
+ # preprocessor-based tests at the same time, to check the toolchain
+ # matches what we want.
+ for n, (value, condition) in enumerate(CPU_preprocessor_checks.iteritems()):
+ check += dedent('''\
+ #%(if)s %(condition)s
+ %%CPU %(value)s
+ ''' % {
+ 'if': 'elif' if n else 'if',
+ 'condition': condition,
+ 'value': value,
+ })
+ check += '#endif\n'
+
result = try_preprocess(compiler, language, check)
if not result:
raise FatalCheckError(
'Unknown compiler or compiler not supported.')
data = {}
for line in result.splitlines():
@@ -282,23 +298,24 @@ def get_compiler_info(compiler, language
version += '.' + msc_ver[4:]
if version:
version = Version(version)
return namespace(
type=type,
version=version,
+ cpu=data.get('CPU'),
language='C++' if cplusplus else 'C',
language_version=cplusplus if cplusplus else stdc_version,
)
@imports(_from='mozbuild.shellutil', _import='quote')
-def check_compiler(compiler, language):
+def check_compiler(compiler, language, target):
info = get_compiler_info(compiler, language)
flags = []
def append_flag(flag):
if flag not in flags:
if info.type == 'clang-cl':
flags.append('-Xclang')
@@ -328,19 +345,36 @@ def check_compiler(compiler, language):
# We force clang-cl to emulate Visual C++ 2013 Update 3 with fallback to
# cl.exe.
if info.type == 'clang-cl' and info.version != '18.00.30723':
# Those flags are direct clang-cl flags that don't need -Xclang, add
# them directly.
flags.append('-fms-compatibility-version=18.00.30723')
flags.append('-fallback')
+ # Check compiler target
+ # --------------------------------------------------------------------
+ if not info.cpu or info.cpu != target.cpu:
+ if info.type == 'clang':
+ append_flag('--target=%s' % target.toolchain)
+ elif info.type == 'gcc':
+ same_arch_different_bits = (
+ ('x86', 'x86_64'),
+ ('ppc', 'ppc64'),
+ ('sparc', 'sparc64'),
+ )
+ if (target.cpu, info.cpu) in same_arch_different_bits:
+ append_flag('-m32')
+ elif (info.cpu, target.cpu) in same_arch_different_bits:
+ append_flag('-m64')
+
return namespace(
type=info.type,
version=info.version,
+ target_cpu=info.cpu,
flags=flags,
)
@template
def default_c_compilers(host_or_target):
'''Template defining the set of default C compilers for the host and
target platforms.
@@ -452,38 +486,47 @@ def compiler(language, host_or_target, c
compiler=without_flags[-1],
flags=cmd[len(without_flags):],
)
# Derive the host compiler from the corresponding target compiler when no
# explicit compiler was given and we're not cross compiling. For the C++
# compiler, though, prefer to derive from the host C compiler when it
# doesn't match the target C compiler.
+ # As a special case, since clang supports all kinds of targets in the same
+ # executable, when cross compiling with clang, default to the same compiler
+ # as the target compiler, resetting flags.
if host_or_target == host:
args = (c_compiler, other_c_compiler) if other_c_compiler else ()
@depends(provided_compiler, other_compiler, cross_compiling, *args)
def provided_compiler(value, other_compiler, cross_compiling, *args):
if value:
return value
c_compiler, other_c_compiler = args if args else (None, None)
if not cross_compiling and c_compiler == other_c_compiler:
return other_compiler
+ if cross_compiling and other_compiler.type == 'clang':
+ return namespace(**{
+ k: [] if k == 'flags' else v
+ for k, v in other_compiler.__dict__.iteritems()
+ })
# Normally, we'd use `var` instead of `_var`, but the interaction with
# old-configure complicates things, and for now, we a) can't take the plain
# result from check_prog as CC/CXX/HOST_CC/HOST_CXX and b) have to let
# old-configure AC_SUBST it (because it's autoconf doing it, not us)
compiler = check_prog('_%s' % var, what=what, progs=default_compilers,
input=delayed_getattr(provided_compiler, 'compiler'))
- @depends(compiler, provided_compiler, compiler_wrapper)
+ @depends(compiler, provided_compiler, compiler_wrapper, host_or_target)
@checking('whether %s can be used' % what, lambda x: bool(x))
@imports(_from='mozbuild.shellutil', _import='quote')
- def valid_compiler(compiler, provided_compiler, compiler_wrapper):
+ def valid_compiler(compiler, provided_compiler, compiler_wrapper,
+ host_or_target):
wrapper = list(compiler_wrapper or ())
if provided_compiler:
provided_wrapper = list(provided_compiler.wrapper)
# When doing a subconfigure, the compiler is set by old-configure
# and it contains the wrappers from --with-compiler-wrapper and
# --with-ccache.
if provided_wrapper[:len(wrapper)] == wrapper:
provided_wrapper = provided_wrapper[len(wrapper):]
@@ -507,23 +550,32 @@ def compiler(language, host_or_target, c
% quote(os.path.dirname(full_path)))
if os.path.normcase(find_program(compiler)) != os.path.normcase(
full_path):
die('Found `%s` before `%s` in your $PATH. '
'Please reorder your $PATH.',
quote(os.path.dirname(found_compiler)),
quote(os.path.dirname(full_path)))
- info = check_compiler(wrapper + [compiler] + flags, language)
+ info = check_compiler(wrapper + [compiler] + flags, language,
+ host_or_target)
# Check that the additional flags we got are enough to not require any
# more flags.
if info.flags:
flags += info.flags
- info = check_compiler(wrapper + [compiler] + flags, language)
+ info = check_compiler(wrapper + [compiler] + flags, language,
+ host_or_target)
+
+ if not info.target_cpu or info.target_cpu != host_or_target.cpu:
+ raise FatalCheckError(
+ '%s %s compiler target CPU (%s) does not match --%s CPU (%s)'
+ % (host_or_target_str.capitalize(), language,
+ info.target_cpu or 'unknown', host_or_target_str,
+ host_or_target.raw_cpu))
if info.flags:
raise FatalCheckError(
'Unknown compiler or compiler not supported.')
# Compiler version checks
# ===================================================
# Check the compiler version here instead of in `compiler_version` so
--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
@@ -69,16 +69,40 @@ def GXX(version):
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_X86 = {
+ None: {
+ '__i386__': 1,
+ },
+ '-m64': {
+ '__i386__': False,
+ '__x86_64__': 1,
+ },
+}
+
+GCC_PLATFORM_X86_64 = {
+ None: {
+ '__x86_64__': 1,
+ },
+ '-m32': {
+ '__x86_64__': False,
+ '__i386__': 1,
+ },
+}
+
+GCC_PLATFORM_ARM = {
+ '__arm__': 1,
+}
+
@memoize
def CLANG_BASE(version):
version = Version(version)
return FakeCompiler({
'__clang__': 1,
'__clang_major__': version.major,
'__clang_minor__': version.minor,
@@ -102,16 +126,36 @@ 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[None],
+ '--target=x86_64-darwin11.2.0': GCC_PLATFORM_X86_64[None],
+ '--target=i686-linux-gnu': GCC_PLATFORM_X86[None],
+ '--target=i686-darwin11.2.0': GCC_PLATFORM_X86[None],
+ '--target=arm-linux-gnu': GCC_PLATFORM_ARM,
+ }
+ 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 = CLANG_PLATFORM(GCC_PLATFORM_X86)
+
+CLANG_PLATFORM_X86_64 = CLANG_PLATFORM(GCC_PLATFORM_X86_64)
+
+
@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),
@@ -121,27 +165,38 @@ def VS(version):
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_PLATFORM_X86 = {
+ '_M_IX86': 600,
+}
+
+VS_PLATFORM_X86_64 = {
+ '_M_X64': 100,
+}
+
# 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) + {
'*.cpp': {
'__STDC_VERSION__': False,
'__cplusplus': '201103L',
},
'-fms-compatibility-version=18.00.30723': VS('18.00.30723')[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)
@@ -192,28 +247,28 @@ class BaseToolchainTest(BaseConfigureTes
except SystemExit:
self.assertEquals((var, result),
(var, self.out.getvalue().strip()))
return
class LinuxToolchainTest(BaseToolchainTest):
PATHS = {
- '/usr/bin/gcc': GCC_4_9,
- '/usr/bin/g++': GXX_4_9,
- '/usr/bin/gcc-4.7': GCC_4_7,
- '/usr/bin/g++-4.7': GXX_4_7,
- '/usr/bin/gcc-5': GCC_5,
- '/usr/bin/g++-5': GXX_5,
- '/usr/bin/clang': CLANG_3_6,
- '/usr/bin/clang++': CLANGXX_3_6,
- '/usr/bin/clang-3.6': CLANG_3_6,
- '/usr/bin/clang++-3.6': CLANGXX_3_6,
- '/usr/bin/clang-3.3': CLANG_3_3,
- '/usr/bin/clang++-3.3': CLANGXX_3_3,
+ '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86_64,
+ '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_64,
+ '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_64,
+ '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_64,
+ '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_64,
+ '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_64,
+ '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64,
}
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',
@@ -401,18 +456,18 @@ class LinuxToolchainTest(BaseToolchainTe
}
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': CLANG_3_6,
- '/opt/clang/bin/clang++': CLANGXX_3_6,
+ '/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++'
},
@@ -424,18 +479,18 @@ class LinuxToolchainTest(BaseToolchainTe
# 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': CLANG_3_6,
- '/usr/bin/afl-clang-fast++': CLANGXX_3_6,
+ '/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++',
},
@@ -462,16 +517,92 @@ class LinuxToolchainTest(BaseToolchainTe
'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,
+ '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86,
+ '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86,
+ }
+ 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 = LinuxToolchainTest.PATHS
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
@@ -525,24 +656,35 @@ class OSXToolchainTest(BaseToolchainTest
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,
- '/opt/VS_2013u3/bin/cl': VS_2013u3,
- '/opt/VS_2015/bin/cl': VS_2015,
- '/opt/VS_2015u1/bin/cl': VS_2015u1,
- '/usr/bin/cl': VS_2015u2,
- '/usr/bin/clang-cl': CLANG_CL_3_9,
+ '/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,
+ '/usr/bin/cl': VS_2015u2 + VS_PLATFORM_X86,
+ '/usr/bin/clang-cl': CLANG_CL_3_9 + CLANG_CL_PLATFORM_X86,
+ '/usr/bin/gcc': GCC_4_9 + GCC_PLATFORM_X86,
+ '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86,
+ '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86,
+ '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86,
+ '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86,
+ '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86,
+ '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86,
+ '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86,
}
- PATHS.update(LinuxToolchainTest.PATHS)
VS_2013u2_RESULT = (
'This version (18.00.30501) of the MSVC compiler is not supported.\n'
'You must install Visual C++ 2015 Update 2 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 2 or newer in order to build.\n'
@@ -662,51 +804,225 @@ class WindowsToolchainTest(BaseToolchain
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_2015u2 + 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 CrossCompileToolchainTest(BaseToolchainTest):
+
+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,
+ '/usr/bin/cl': VS_2015u2 + 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,
+ '/usr/bin/g++': GXX_4_9 + GCC_PLATFORM_X86_64,
+ '/usr/bin/gcc-4.7': GCC_4_7 + GCC_PLATFORM_X86_64,
+ '/usr/bin/g++-4.7': GXX_4_7 + GCC_PLATFORM_X86_64,
+ '/usr/bin/gcc-5': GCC_5 + GCC_PLATFORM_X86_64,
+ '/usr/bin/g++-5': GXX_5 + GCC_PLATFORM_X86_64,
+ '/usr/bin/clang': CLANG_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++': CLANGXX_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang-3.6': CLANG_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++-3.6': CLANGXX_3_6 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang-3.3': CLANG_3_3 + CLANG_PLATFORM_X86_64,
+ '/usr/bin/clang++-3.3': CLANGXX_3_3 + CLANG_PLATFORM_X86_64,
+ }
+
+ def test_cannot_cross(self):
+ paths = {
+ '/usr/bin/cl': VS_2015u2 + 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,
- '/usr/bin/arm-linux-gnu-g++': GXX_4_9,
- '/usr/bin/arm-linux-gnu-gcc-4.7': GCC_4_7,
- '/usr/bin/arm-linux-gnu-g++-4.7': GXX_4_7,
- '/usr/bin/arm-linux-gnu-gcc-5': GCC_5,
- '/usr/bin/arm-linux-gnu-g++-5': GXX_5,
+ '/usr/bin/arm-linux-gnu-gcc': GCC_4_9 + GCC_PLATFORM_ARM,
+ '/usr/bin/arm-linux-gnu-g++': GXX_4_9 + GCC_PLATFORM_ARM,
+ '/usr/bin/arm-linux-gnu-gcc-4.7': GCC_4_7 + GCC_PLATFORM_ARM,
+ '/usr/bin/arm-linux-gnu-g++-4.7': GXX_4_7 + GCC_PLATFORM_ARM,
+ '/usr/bin/arm-linux-gnu-gcc-5': GCC_5 + GCC_PLATFORM_ARM,
+ '/usr/bin/arm-linux-gnu-g++-5': GXX_5 + GCC_PLATFORM_ARM,
}
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
- def test_cross_gcc(self):
- self.do_toolchain_test(self.PATHS, {
+ PLATFORMS = {
+ 'i686-pc-linux-gnu': GCC_PLATFORM_X86,
+ 'x86_64-pc-linux-gnu': GCC_PLATFORM_X86_64,
+ 'arm-unknown-linux-gnu': GCC_PLATFORM_ARM,
+ 'aarch64-unknown-linux-gnu': {
+ '__aarch64__': 1,
+ },
+ 'ia64-unknown-linux-gnu': {
+ '__ia64__': 1,
+ },
+ 's390x-unknown-linux-gnu': {
+ '__s390x__': 1,
+ '__s390__': 1,
+ },
+ 's390-unknown-linux-gnu': {
+ '__s390__': 1,
+ },
+ 'powerpc64-unknown-linux-gnu': {
+ None: {
+ '__powerpc64__': 1,
+ '__powerpc__': 1,
+ },
+ '-m32': {
+ '__powerpc64__': False,
+ },
+ },
+ 'powerpc-unknown-linux-gnu': {
+ None: {
+ '__powerpc__': 1,
+ },
+ '-m64': {
+ '__powerpc64__': 1,
+ },
+ },
+ 'alpha-unknown-linux-gnu': {
+ '__alpha__': 1,
+ },
+ 'hppa-unknown-linux-gnu': {
+ '__hppa__': 1,
+ },
+ 'sparc64-unknown-linux-gnu': {
+ None: {
+ '__arch64__': 1,
+ '__sparc__': 1,
+ },
+ '-m32': {
+ '__arch64__': False,
+ },
+ },
+ 'sparc-unknown-linux-gnu': {
+ None: {
+ '__sparc__': 1,
+ },
+ '-m64': {
+ '__arch64__': 1,
+ },
+ },
+ 'mips64-unknown-linux-gnuabi64': {
+ '__mips64': 1,
+ '__mips__': 1,
+ },
+ 'mips-unknown-linux-gnu': {
+ '__mips__': 1,
+ },
+ }
+
+ 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': '/usr/bin/arm-linux-gnu-gcc',
+ 'compiler': '%s-gcc' % toolchain_prefix,
},
'cxx_compiler': self.GXX_4_9_RESULT + {
- 'compiler': '/usr/bin/arm-linux-gnu-g++',
+ '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_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={
@@ -749,11 +1065,84 @@ class CrossCompileToolchainTest(BaseTool
'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',
+ })
+
if __name__ == '__main__':
main()