Bug 1288313 - Ensure the host and target compilers build for the right endianness. r?chmanchester
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -400,20 +400,20 @@ def split_triplet(triplet):
elif cpu.startswith('sparc') or cpu == 'sun4u':
canonical_cpu = 'sparc'
endianness = 'big'
elif cpu.startswith('arm'):
canonical_cpu = 'arm'
endianness = 'big' if cpu.startswith(('armeb', 'armbe')) else 'little'
elif cpu in ('mips', 'mipsel'):
canonical_cpu = 'mips32'
- endianness = 'little' if 'le' in cpu else 'big'
+ endianness = 'little' if 'el' in cpu else 'big'
elif cpu in ('mips64', 'mips64el'):
canonical_cpu = 'mips64'
- endianness = 'little' if 'le' in cpu else 'big'
+ endianness = 'little' if 'el' in cpu else 'big'
elif cpu.startswith('aarch64'):
canonical_cpu = 'aarch64'
endianness = 'little'
else:
die('Unknown CPU type: %s' % cpu)
return namespace(
alias=triplet,
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -267,16 +267,27 @@ def get_compiler_info(compiler, language
''' % {
'if': 'elif' if n else 'if',
'condition': condition,
'name': name,
'value': value,
})
check += '#endif\n'
+ # Also check for endianness. The advantage of living in modern times is
+ # that all the modern compilers we support now have __BYTE_ORDER__ defined
+ # by the preprocessor, except MSVC, which only supports little endian.
+ check += dedent('''\
+ #if _MSC_VER || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ %ENDIANNESS little
+ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ %ENDIANNESS big
+ #endif
+ ''')
+
result = try_preprocess(compiler, language, check)
if not result:
raise FatalCheckError(
'Unknown compiler or compiler not supported.')
data = {}
for line in result.splitlines():
@@ -307,16 +318,17 @@ def get_compiler_info(compiler, language
if version:
version = Version(version)
return namespace(
type=type,
version=version,
cpu=data.get('CPU'),
kernel=data.get('KERNEL'),
+ endianness=data.get('ENDIANNESS'),
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, target):
info = get_compiler_info(compiler, language)
@@ -373,21 +385,26 @@ def check_compiler(compiler, language, t
append_flag('-m32')
elif (info.cpu, target.cpu) in same_arch_different_bits:
append_flag('-m64')
if not info.kernel or info.kernel != target.kernel:
if info.type == 'clang':
append_flag('--target=%s' % target.toolchain)
+ if not info.endianness or info.endianness != target.endianness:
+ if info.type == 'clang':
+ append_flag('--target=%s' % target.toolchain)
+
return namespace(
type=info.type,
version=info.version,
target_cpu=info.cpu,
target_kernel=info.kernel,
+ target_endianness=info.endianness,
flags=flags,
)
@template
def default_c_compilers(host_or_target):
'''Template defining the set of default C compilers for the host and
target platforms.
@@ -588,16 +605,25 @@ def compiler(language, host_or_target, c
if not info.target_kernel or (info.target_kernel !=
host_or_target.kernel):
raise FatalCheckError(
'%s %s compiler target kernel (%s) does not match --%s kernel (%s)'
% (host_or_target_str.capitalize(), language,
info.target_kernel or 'unknown', host_or_target_str,
host_or_target.kernel))
+ if not info.target_endianness or (info.target_endianness !=
+ host_or_target.endianness):
+ raise FatalCheckError(
+ '%s %s compiler target endianness (%s) does not match --%s '
+ 'endianness (%s)'
+ % (host_or_target_str.capitalize(), language,
+ info.target_endianness or 'unknown', host_or_target_str,
+ host_or_target.endianness))
+
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
# that the `checking` message doesn't pretend the compiler can be used
--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
@@ -49,16 +49,18 @@ SUPPORTS_GNUXX11 = {
@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
@@ -69,37 +71,45 @@ 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 = {
+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 = {
+GCC_PLATFORM_X86_64 = FakeCompiler(GCC_PLATFORM_LITTLE_ENDIAN) + {
None: {
'__x86_64__': 1,
},
'-m32': {
'__x86_64__': False,
'__i386__': 1,
},
}
-GCC_PLATFORM_ARM = {
+GCC_PLATFORM_ARM = FakeCompiler(GCC_PLATFORM_LITTLE_ENDIAN) + {
'__arm__': 1,
}
GCC_PLATFORM_LINUX = {
'__linux__': 1,
}
GCC_PLATFORM_DARWIN = {
@@ -914,82 +924,93 @@ class LinuxCrossCompileToolchainTest(Bas
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': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'aarch64-unknown-linux-gnu': little_endian + {
'__aarch64__': 1,
},
- 'ia64-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'ia64-unknown-linux-gnu': little_endian + {
'__ia64__': 1,
},
- 's390x-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 's390x-unknown-linux-gnu': big_endian + {
'__s390x__': 1,
'__s390__': 1,
},
- 's390-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 's390-unknown-linux-gnu': big_endian + {
'__s390__': 1,
},
- 'powerpc64-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'powerpc64-unknown-linux-gnu': big_endian + {
None: {
'__powerpc64__': 1,
'__powerpc__': 1,
},
'-m32': {
'__powerpc64__': False,
},
},
- 'powerpc-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'powerpc-unknown-linux-gnu': big_endian + {
None: {
'__powerpc__': 1,
},
'-m64': {
'__powerpc64__': 1,
},
},
- 'alpha-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'alpha-unknown-linux-gnu': little_endian + {
'__alpha__': 1,
},
- 'hppa-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'hppa-unknown-linux-gnu': big_endian + {
'__hppa__': 1,
},
- 'sparc64-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'sparc64-unknown-linux-gnu': big_endian + {
None: {
'__arch64__': 1,
'__sparc__': 1,
},
'-m32': {
'__arch64__': False,
},
},
- 'sparc-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'sparc-unknown-linux-gnu': big_endian + {
None: {
'__sparc__': 1,
},
'-m64': {
'__arch64__': 1,
},
},
- 'mips64-unknown-linux-gnuabi64': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ 'mips64-unknown-linux-gnuabi64': big_endian + {
'__mips64': 1,
'__mips__': 1,
},
- 'mips-unknown-linux-gnu': FakeCompiler(GCC_PLATFORM_LINUX) + {
+ '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 = {
@@ -1055,16 +1076,29 @@ class LinuxCrossCompileToolchainTest(Bas
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',