Bug 1264609 - Derive HOST_CXX from CXX when it makes sense. r=ted
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 22 Apr 2016 08:00:11 +0900
changeset 335013 c4e9581781cdfe7c173b23a5180aa9afe6ceeb7e
parent 335012 7d557a4bf9ac67ea3d50ccd8c9c909fc608d4296
child 335014 3aa433b16d7564a148724f01d6276c8c6e481bb6
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1264609
milestone49.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 1264609 - Derive HOST_CXX from CXX when it makes sense. r=ted
build/moz.configure/toolchain.configure
python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -400,30 +400,35 @@ def default_cxx_compilers(c_compiler):
             return (os.path.join(dir, file.replace('clang', 'clang++')),)
 
         return (c_compiler.compiler,)
 
     return default_cxx_compilers
 
 
 @template
-def compiler(language, host_or_target, c_compiler=None, other_compiler=None):
+def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
+             other_c_compiler=None):
     '''Template handling the generic base checks for the compiler for the
     given `language` on the given platform (`host_or_target`).
     `host_or_target` is either `host` or `target` (the @depends functions
     from init.configure.
-    When the language in 'C++', `c_compiler` is the result of the `compiler`
+    When the language is 'C++', `c_compiler` is the result of the `compiler`
     template for the language 'C' for the same `host_or_target`.
     When `host_or_target` is `host`, `other_compiler` is the result of the
     `compiler` template for the same `language` for `target`.
+    When `host_or_target` is `host` and the language is 'C++',
+    `other_c_compiler` is the result of the `compiler` template for the
+    language 'C' for `target`.
     '''
     assert host_or_target in (host, target)
     assert language in ('C', 'C++')
     assert language == 'C' or c_compiler
     assert host_or_target == target or other_compiler
+    assert language == 'C' or host_or_target == target or other_c_compiler
 
     host_or_target_str = {
         host: 'host',
         target: 'target',
     }[host_or_target]
 
     var = {
         ('C', target): 'CC',
@@ -457,24 +462,29 @@ def compiler(language, host_or_target, c
         without_flags = list(takewhile(lambda x: not x.startswith('-'), cmd))
 
         return namespace(
             wrapper=without_flags[:-1],
             compiler=without_flags[-1],
             flags=cmd[len(without_flags):],
         )
 
-    # Derive the host C compiler from the target C compiler when no explicit
-    # compiler was given and we're not cross compiling.
-    if language == 'C' and host_or_target == host:
-        @depends(provided_compiler, other_compiler, cross_compiling)
-        def provided_compiler(value, other_compiler, cross_compiling):
+    # 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.
+    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
-            if not cross_compiling:
+            c_compiler, other_c_compiler = args if args else (None, None)
+            if not cross_compiling and c_compiler == other_c_compiler:
                 return other_compiler
 
     # 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'))
@@ -602,9 +612,10 @@ def compiler(language, host_or_target, c
 
     return valid_compiler
 
 
 c_compiler = compiler('C', target)
 cxx_compiler = compiler('C++', target, c_compiler=c_compiler)
 host_c_compiler = compiler('C', host, other_compiler=c_compiler)
 host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler,
-                             other_compiler=cxx_compiler)
+                             other_compiler=cxx_compiler,
+                             other_c_compiler=c_compiler)
--- a/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
@@ -727,17 +727,16 @@ class LinuxToolchainTest(BaseToolchainTe
             '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',
         })
 
-    @unittest.expectedFailure  # Bug 1264609
     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,
         })
         afl_clang_result = dict(self.CLANG_3_6_RESULT)
         afl_clang_result['compiler'] = '/usr/bin/afl-clang-fast'
@@ -746,16 +745,38 @@ class LinuxToolchainTest(BaseToolchainTe
         self.do_toolchain_test(paths, {
             'c_compiler': afl_clang_result,
             'cxx_compiler': afl_clangxx_result,
         }, 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 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