Bug 1288313 - Ensure the host and target compilers build for the right endianness. r=chmanchester
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 21 Jul 2016 08:24:45 +0900
changeset 346308 51fe63c13c4c257ca63f4adcc6ab2be97183ce69
parent 346307 ba8cf05d0ee715aabb7b788f2026819a634a50f1
child 346309 933fcf81f9c8661398b077014802441440a84955
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschmanchester
bugs1288313
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1288313 - Ensure the host and target compilers build for the right endianness. r=chmanchester
build/moz.configure/init.configure
build/moz.configure/toolchain.configure
python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
--- 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
@@ -263,16 +263,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():
@@ -303,16 +314,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)
@@ -369,21 +381,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.
@@ -584,16 +601,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',