Bug 1259382 - Move CC/CXX/HOST_CC/HOST_CXX to moz.configure. r?ted draft
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 05 Apr 2016 10:56:42 +0900
changeset 347606 3ff1146e5f78563657c88a389041a515995c6bed
parent 347605 6e72a7576e5a18b885b6255256f438b75f1c4737
child 347607 c14dc478cfa3616c8ffefea5380b0fb9d89f3d78
push id14625
push userbmo:mh+mozilla@glandium.org
push dateTue, 05 Apr 2016 11:59:43 +0000
reviewersted
bugs1259382
milestone48.0a1
Bug 1259382 - Move CC/CXX/HOST_CC/HOST_CXX to moz.configure. r?ted At the same time, we improve things slightly by deriving HOST_CC from CC in a smarter way, as well as CXX from CC, which we weren't doing previously. Many related things are not moved at the same time to keep the patch somehow "small".
aclocal.m4
browser/config/mozconfigs/linux64/artifact
build/autoconf/toolchain.m4
build/autoconf/wrapper.m4
build/moz.configure/init.configure
build/moz.configure/toolchain.configure
js/src/aclocal.m4
js/src/old-configure.in
mobile/android/config/mozconfigs/android-api-15-frontend/nightly
old-configure.in
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -3,17 +3,16 @@ dnl Local autoconf macros used with mozi
 dnl The contents of this file are under the Public Domain.
 dnl
 
 builtin(include, build/autoconf/hotfixes.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/hooks.m4)dnl
 builtin(include, build/autoconf/config.status.m4)dnl
 builtin(include, build/autoconf/toolchain.m4)dnl
-builtin(include, build/autoconf/wrapper.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/nspr-build.m4)dnl
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
--- a/browser/config/mozconfigs/linux64/artifact
+++ b/browser/config/mozconfigs/linux64/artifact
@@ -1,8 +1,10 @@
 MOZ_AUTOMATION_BUILD_SYMBOLS=0
 MOZ_AUTOMATION_L10N_CHECK=0
 
 NO_CACHE=1
 
 . "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
 
 ac_add_options --enable-artifact-builds
+unset CC
+unset CXX
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -1,51 +1,22 @@
 dnl This Source Code Form is subject to the terms of the Mozilla Public
 dnl License, v. 2.0. If a copy of the MPL was not distributed with this
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 AC_DEFUN([MOZ_TOOL_VARIABLES],
 [
 GNU_AS=
 GNU_LD=
+
 GNU_CC=
 GNU_CXX=
-CC_VERSION='N/A'
-CXX_VERSION='N/A'
-cat <<EOF > conftest.c
-#if defined(_MSC_VER)
-#if defined(__clang__)
-COMPILER clang-cl _MSC_VER
-#else
-COMPILER msvc _MSC_FULL_VER
-#endif
-#elif defined(__clang__)
-COMPILER clang __clang_major__.__clang_minor__.__clang_patchlevel__
-#elif defined(__GNUC__)
-COMPILER gcc __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
-#endif
-EOF
-read dummy compiler CC_VERSION <<EOF
-$($CC -E $CPPFLAGS $CFLAGS conftest.c 2>/dev/null | grep COMPILER)
-EOF
-read dummy cxxcompiler CXX_VERSION <<EOF
-$($CXX -E $CPPFLAGS $CXXFLAGS conftest.c 2>/dev/null | grep COMPILER)
-EOF
-if test "$compiler" != "$cxxcompiler"; then
-    AC_MSG_ERROR([Your C and C++ compilers are different.  You need to use the same compiler.])
-fi
-if test "$CC_VERSION" != "$CXX_VERSION"; then
-    # This may not be strictly necessary, but if we want to drop it, we
-    # should make sure any version checks below apply to both the C and
-    # C++ compiler versions.
-    AC_MSG_ERROR([Your C and C++ compiler versions are different.  You need to use the same compiler version.])
-fi
-CC_VERSION=`echo "$CC_VERSION" | sed 's/ //g'`
-CXX_VERSION=`echo "$CXX_VERSION" | sed 's/ //g'`
-if test "$compiler" = "gcc"; then
+dnl moz.configure ensures that the compilers have the same version
+CXX_VERSION=$CC_VERSION
+if test "$CC_TYPE" = "gcc"; then
     GNU_CC=1
     GNU_CXX=1
     changequote(<<,>>)
     GCC_VERSION_FULL="$CXX_VERSION"
     GCC_VERSION=`echo "$GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/<<$>>1/;'`
 
     GCC_MAJOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print <<$>>1 }'`
     GCC_MINOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print <<$>>2 }'`
@@ -55,32 +26,32 @@ fi
 if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
     GNU_AS=1
 fi
 rm -f conftest.out
 if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
     GNU_LD=1
 fi
 
-if test "$compiler" = "msvc"; then
+if test "$CC_TYPE" = "msvc"; then
      MSVC_VERSION_FULL="$CXX_VERSION"
      CC_VERSION=`echo ${CC_VERSION} | cut -c 1-4`
      CXX_VERSION=`echo ${CXX_VERSION} | cut -c 1-4`
 fi
 
 CLANG_CC=
 CLANG_CXX=
 CLANG_CL=
-if test "$compiler" = "clang"; then
+if test "$CC_TYPE" = "clang"; then
     GNU_CC=1
     GNU_CXX=1
     CLANG_CC=1
     CLANG_CXX=1
 fi
-if test "$compiler" = "clang-cl"; then
+if test "$CC_TYPE" = "clang-cl"; then
     CLANG_CL=1
     # We force clang-cl to emulate Visual C++ 2013 in configure.in, but that
     # is based on the CLANG_CL variable defined here, so make sure that we're
     # getting the right version here manually.
     CC_VERSION=1800
     CXX_VERSION=1800
     MSVC_VERSION_FULL=180030723
     # Build on clang-cl with MSVC 2013 Update 3 with fallback emulation.
@@ -108,29 +79,16 @@ fi
 AC_DEFUN([MOZ_CROSS_COMPILER],
 [
 echo "cross compiling from $host to $target"
 
 _SAVE_CC="$CC"
 _SAVE_CFLAGS="$CFLAGS"
 _SAVE_LDFLAGS="$LDFLAGS"
 
-AC_MSG_CHECKING([for host c compiler])
-AC_CHECK_PROGS(HOST_CC, cc gcc clang cl, "")
-if test -z "$HOST_CC"; then
-    AC_MSG_ERROR([no acceptable c compiler found in \$PATH])
-fi
-AC_MSG_RESULT([$HOST_CC])
-AC_MSG_CHECKING([for host c++ compiler])
-AC_CHECK_PROGS(HOST_CXX, c++ g++ clang++ cl, "")
-if test -z "$HOST_CXX"; then
-    AC_MSG_ERROR([no acceptable c++ compiler found in \$PATH])
-fi
-AC_MSG_RESULT([$HOST_CXX])
-
 if test -z "$HOST_AR_FLAGS"; then
     HOST_AR_FLAGS="$AR_FLAGS"
 fi
 AC_CHECK_PROGS(HOST_RANLIB, $HOST_RANLIB ranlib, ranlib, :)
 AC_CHECK_PROGS(HOST_AR, $HOST_AR ar, ar, :)
 CC="$HOST_CC"
 CFLAGS="$HOST_CFLAGS"
 LDFLAGS="$HOST_LDFLAGS"
@@ -157,21 +115,17 @@ dnl absolute paths would. Trick AC_CHECK
 dnl adding / to PATH. This is temporary until this moves to moz.configure
 dnl (soon).
 _SAVE_PATH=$PATH
 case "${TOOLCHAIN_PREFIX}" in
 /*)
     PATH="/:$PATH"
     ;;
 esac
-AC_CHECK_PROGS(CC, "${TOOLCHAIN_PREFIX}gcc", :)
-unset ac_cv_prog_CC
 AC_PROG_CC
-AC_CHECK_PROGS(CXX, "${TOOLCHAIN_PREFIX}g++", :)
-unset ac_cv_prog_CXX
 AC_PROG_CXX
 
 AC_CHECK_PROGS(RANLIB, "${TOOLCHAIN_PREFIX}ranlib", :)
 AC_CHECK_PROGS(AR, "${TOOLCHAIN_PREFIX}ar", :)
 AC_CHECK_PROGS(AS, "${TOOLCHAIN_PREFIX}as", :)
 AC_CHECK_PROGS(LD, "${TOOLCHAIN_PREFIX}ld", :)
 AC_CHECK_PROGS(STRIP, "${TOOLCHAIN_PREFIX}strip", :)
 AC_CHECK_PROGS(WINDRES, "${TOOLCHAIN_PREFIX}windres", :)
@@ -225,71 +179,47 @@ if test "$GNU_CXX"; then
       MOZ_NEEDS_LIBATOMIC=1
     else
       MOZ_NEEDS_LIBATOMIC=
     fi
     AC_SUBST(MOZ_NEEDS_LIBATOMIC)
 fi
 
 if test -n "$CROSS_COMPILE"; then
-    dnl When cross compile, we have no variable telling us what the host compiler is. Figure it out.
-    cat > conftest.C <<EOF
-#if defined(__clang__)
-COMPILER CLANG __clang_major__.__clang_minor__.__clang_patchlevel__
-#elif defined(__GNUC__)
-COMPILER GCC __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
-#endif
-EOF
-read dummy host_compiler HOST_CC_VERSION <<EOF
-$($HOST_CC -E conftest.C 2>/dev/null | grep COMPILER)
-EOF
-read dummy host_cxxcompiler HOST_CXX_VERSION <<EOF
-$($HOST_CXX -E conftest.C 2>/dev/null | grep COMPILER)
-EOF
-    rm conftest.C
-    if test "$host_compiler" != "$host_cxxcompiler"; then
-        AC_MSG_ERROR([Your C and C++ host compilers are different.  You need to use the same compiler.])
-    fi
-    if test "$HOST_CC_VERSION" != "$HOST_CXX_VERSION"; then
-        # This may not be strictly necessary, but if we want to drop it,
-        # we should make sure any version checks below apply to both the
-        # C and C++ compiler versions.
-        AC_MSG_ERROR([Your C and C++ host compiler versions are different.  You need to use the same compiler version.])
+    dnl moz.configure ensures that the compilers have the same version
+    HOST_CXX_VERSION=$HOST_CC_VERSION
+    if test "$HOST_CC_TYPE" = "gcc" ; then
+	changequote(<<,>>)
+	HOST_GCC_VERSION_FULL="$HOST_CXX_VERSION"
+	HOST_GCC_VERSION=`echo "$HOST_GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/<<$>>1/;'`
+
+	HOST_GCC_MAJOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>1 }'`
+	HOST_GCC_MINOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>2 }'`
+	changequote([,])
+
+	if test "$HOST_GCC_MAJOR_VERSION" -eq 4 -a "$HOST_GCC_MINOR_VERSION" -lt 8 ||
+	   test "$HOST_GCC_MAJOR_VERSION" -lt 4; then
+	    AC_MSG_ERROR([Only GCC 4.8 or newer supported for host compiler])
+	fi
     fi
-    if test -n "$host_compiler"; then
-        if test "$host_compiler" = "GCC" ; then
-            changequote(<<,>>)
-            HOST_GCC_VERSION_FULL="$HOST_CXX_VERSION"
-            HOST_GCC_VERSION=`echo "$HOST_GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/<<$>>1/;'`
 
-            HOST_GCC_MAJOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>1 }'`
-            HOST_GCC_MINOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>2 }'`
-            changequote([,])
-
-            if test "$HOST_GCC_MAJOR_VERSION" -eq 4 -a "$HOST_GCC_MINOR_VERSION" -lt 8 ||
-               test "$HOST_GCC_MAJOR_VERSION" -lt 4; then
-                AC_MSG_ERROR([Only GCC 4.8 or newer supported for host compiler])
-            fi
-        fi
+    HOST_CXXFLAGS="$HOST_CXXFLAGS -std=gnu++11"
 
-        HOST_CXXFLAGS="$HOST_CXXFLAGS -std=gnu++11"
+    _SAVE_CXXFLAGS="$CXXFLAGS"
+    _SAVE_CPPFLAGS="$CPPFLAGS"
+    _SAVE_CXX="$CXX"
+    CXXFLAGS="$HOST_CXXFLAGS"
+    CPPFLAGS="$HOST_CPPFLAGS"
+    CXX="$HOST_CXX"
+    if test "$HOST_CC_TYPE" = clang; then
+	AC_TRY_COMPILE([], [#if !__cpp_static_assert
+			    #error ISO WG21 SG10 feature test macros unsupported
+			    #endif],,AC_MSG_ERROR([Only clang/llvm 3.4 or newer supported]))
+    fi
 
-        _SAVE_CXXFLAGS="$CXXFLAGS"
-        _SAVE_CPPFLAGS="$CPPFLAGS"
-        _SAVE_CXX="$CXX"
-        CXXFLAGS="$HOST_CXXFLAGS"
-        CPPFLAGS="$HOST_CPPFLAGS"
-        CXX="$HOST_CXX"
-        if test "$host_compiler" = CLANG; then
-            AC_TRY_COMPILE([], [#if !__cpp_static_assert
-                                #error ISO WG21 SG10 feature test macros unsupported
-                                #endif],,AC_MSG_ERROR([Only clang/llvm 3.4 or newer supported]))
-        fi
-
-        CXXFLAGS="$_SAVE_CXXFLAGS"
-        CPPFLAGS="$_SAVE_CPPFLAGS"
-        CXX="$_SAVE_CXX"
-    fi
+    CXXFLAGS="$_SAVE_CXXFLAGS"
+    CPPFLAGS="$_SAVE_CPPFLAGS"
+    CXX="$_SAVE_CXX"
 elif test "$GNU_CXX"; then
     HOST_CXXFLAGS="$HOST_CXXFLAGS $_ADDED_CXXFLAGS"
 fi
 AC_LANG_C
 ])
deleted file mode 100644
--- a/build/autoconf/wrapper.m4
+++ /dev/null
@@ -1,25 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-dnl =======================================================================
-dnl = Enable compiling with various compiler wrappers (distcc, ccache, etc)
-dnl =======================================================================
-AC_DEFUN([MOZ_CHECK_COMPILER_WRAPPER],
-[
-if test -n "$COMPILER_WRAPPER"; then
-    case "$CC" in
-    $COMPILER_WRAPPER\ *)
-        :
-        ;;
-    *)
-        CC="$COMPILER_WRAPPER $CC"
-        CXX="$COMPILER_WRAPPER $CXX"
-        _SUBDIR_CC="$CC"
-        _SUBDIR_CXX="$CXX"
-        ac_cv_prog_CC="$CC"
-        ac_cv_prog_CXX="$CXX"
-        ;;
-    esac
-fi
-])
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -257,27 +257,31 @@ early_options = early_options()
 # moz.configure files are executed, so we keep a manual list here, that is
 # checked in old.configure (we'll assume it's the last moz.configure file
 # processed). This is tedious but necessary for now.
 @depends('--help')
 def wanted_mozconfig_variables(help):
      return set([
          'AUTOCONF',
          'AWK',
+         'CC',
          'CCACHE',
+         'CXX',
          'COMPILER_WRAPPER',
          'DISABLE_EXPORT_JS',
          'DISABLE_SHARED_JS',
          'DOXYGEN',
          'DSYMUTIL',
          'EXTERNAL_SOURCE_DIR',
          'GENISOIMAGE',
          'GRADLE',
          'GRADLE_FLAGS',
          'GRADLE_MAVEN_REPOSITORY',
+         'HOST_CC',
+         'HOST_CXX',
          'JS_STANDALONE',
          'L10NBASEDIR',
          'MOZILLABUILD',
          'MOZ_ARTIFACT_BUILDS',
          'MOZ_BUILD_APP',
          'MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE',
          'MOZ_CALLGRIND',
          'MOZ_DMD',
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -67,21 +67,25 @@ def android_ndk_include(compile_env, bui
     if compile_env and build_project in ('mobile/android', 'js'):
         return 'android-ndk.configure'
 
 include(android_ndk_include)
 
 
 # Compiler wrappers
 # ==============================================================
-js_option('--with-compiler-wrapper', env='COMPILER_WRAPPER', nargs=1,
-          help='Enable compiling with wrappers such as distcc and ccache')
+# Normally, we'd use js_option and automatically have those variables
+# propagated to js/src, but things are complicated by possible additional
+# wrappers in CC/CXX, and by other subconfigures that do not handle those
+# options and do need CC/CXX altered.
+option('--with-compiler-wrapper', env='COMPILER_WRAPPER', nargs=1,
+       help='Enable compiling with wrappers such as distcc and ccache')
 
-js_option('--with-ccache', env='CCACHE', nargs='?',
-          help='Enable compiling with ccache')
+option('--with-ccache', env='CCACHE', nargs='?',
+       help='Enable compiling with ccache')
 
 @depends_if('--with-ccache')
 def ccache(value):
     if len(value):
         return value
     # If --with-ccache was given without an explicit value, we default to
     # 'ccache'.
     return 'ccache'
@@ -135,8 +139,285 @@ def toolchain_prefix(value, target, host
     # Special case x86-64 <-> x86 cross compiling until we have the right tests
     # in moz.configure land.
     if cross_compiling and not all(i.cpu in ('x86_64', 'x86')
                                    for i in (target, host)):
         return '%s-' % target.toolchain
 
 set_config('TOOLCHAIN_PREFIX', toolchain_prefix)
 add_old_configure_assignment('TOOLCHAIN_PREFIX', toolchain_prefix)
+
+
+# Compilers
+# ==============================================================
+@imports('os')
+@imports('subprocess')
+@imports(_from='mozbuild.configure.util', _import='LineIO')
+@imports(_from='mozbuild.shellutil', _import='quote')
+@imports(_from='tempfile', _import='mkstemp')
+@imports(_from='textwrap', _import='dedent')
+def check_compiler(compiler, language):
+    check = dedent('''\
+        #if defined(_MSC_VER)
+        #if defined(__clang__)
+        COMPILER clang-cl _MSC_VER
+        #else
+        COMPILER msvc _MSC_FULL_VER
+        #endif
+        #elif defined(__clang__)
+        COMPILER clang __clang_major__.__clang_minor__.__clang_patchlevel__
+        #elif defined(__GNUC__)
+        COMPILER gcc __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
+        #endif
+    ''')
+
+    suffix = {
+        'C': '.c',
+        'C++': '.cpp',
+    }[language]
+
+    fd, path = mkstemp(prefix='conftest.', suffix=suffix)
+    try:
+        source = check.encode('ascii', 'replace')
+
+        log.debug('Creating `%s` with content:', path)
+        with LineIO(lambda l: log.debug('| %s', l)) as out:
+            out.write(source)
+
+        os.write(fd, source)
+        os.close(fd)
+
+        cmd = compiler + ['-E', path]
+        log.debug('Executing: `%s`', quote(*cmd))
+        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        stdout, stderr = proc.communicate()
+        retcode = proc.wait()
+        if retcode == 0:
+            for line in stdout.splitlines():
+                if line.startswith('COMPILER '):
+                    _, type, version = line.split(None, 2)
+                    version = version.replace(' ', '')
+                    return type, version
+            return
+
+        log.debug('The command returned non-zero exit status %d.', retcode)
+        for out, desc in ((stdout, 'output'), (stderr, 'error output')):
+            if out:
+                log.debug('Its %s was:', desc)
+                with LineIO(lambda l: log.debug('| %s', l)) as o:
+                    o.write(out)
+    finally:
+        os.remove(path)
+
+
+@template
+def default_c_compilers(host_or_target):
+    '''Template defining the set of default C compilers for the host and
+    target platforms.
+    `host_or_target` is either `host` or `target` (the @depends functions
+    from init.configure.
+    '''
+    assert host_or_target in (host, target)
+
+    @depends(host_or_target, host, toolchain_prefix)
+    def default_c_compilers(host_or_target, host, toolchain_prefix):
+        if host_or_target.os == 'WINNT':
+            return ('cl', 'clang-cl', 'gcc', 'clang')
+        if host_or_target.os == 'Darwin':
+            return ('clang',)
+        if host_or_target != host:  # cross compilation
+            return ('%sgcc' % toolchain_prefix, 'gcc', 'clang')
+        return ('gcc', 'clang')
+
+    return default_c_compilers
+
+
+@template
+def default_cxx_compilers(c_compiler):
+    '''Template defining the set of default C++ compilers for the host and
+    target platforms.
+    `c_compiler` is the @depends function returning a Compiler instance for
+    the desired platform.
+
+    Because the build system expects the C and C++ compilers to be from the
+    same compiler suite, we derive the default C++ compilers from the C
+    compiler that was found if none was provided.
+    '''
+
+    @depends(c_compiler)
+    def default_cxx_compilers(c_compiler):
+        dir = os.path.dirname(c_compiler.compiler)
+        file = os.path.basename(c_compiler.compiler)
+
+        if c_compiler.type == 'gcc':
+            return (os.path.join(dir, file.replace('gcc', 'g++')),)
+
+        if c_compiler.type == 'clang':
+            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):
+    '''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`
+    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`.
+    '''
+    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
+
+    host_or_target_str = {
+        host: 'host',
+        target: 'target',
+    }[host_or_target]
+
+    var = {
+        ('C', target): 'CC',
+        ('C++', target): 'CXX',
+        ('C', host): 'HOST_CC',
+        ('C++', host): 'HOST_CXX',
+    }[language, host_or_target]
+
+    default_compilers = {
+        'C': lambda: default_c_compilers(host_or_target),
+        'C++': lambda: default_cxx_compilers(c_compiler),
+    }[language]()
+
+    what='the %s %s compiler' % (host_or_target_str, language),
+
+    option(env=var, nargs=1, help='Path to %s' % what)
+
+    # Handle the compiler given by the user through one of the CC/CXX/HOST_CC/
+    # HOST_CXX variables.
+    @depends_if(var)
+    @imports(_from='itertools', _import='takewhile')
+    @imports(_from='mozbuild.shellutil', _import='split', _as='shell_split')
+    def provided_compiler(cmd):
+        # Historically, the compiler variables have contained more than the
+        # path to the compiler itself. So for backwards compatibility, try to
+        # find what is what in there, assuming the first dash-prefixed item is
+        # a compiler option, the item before that is the compiler, and anything
+        # before that is a compiler wrapper.
+        cmd = shell_split(cmd[0])
+
+        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):
+            if value:
+                return value
+            if not cross_compiling:
+                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'))
+
+    @depends(compiler, provided_compiler, compiler_wrapper)
+    @checking('%s version' % what, lambda x: x.version if x else 'not found')
+    @imports(_from='mozbuild.shellutil', _import='quote')
+    def valid_compiler(compiler, provided_compiler, compiler_wrapper):
+        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):]
+            wrapper.extend(provided_wrapper)
+            flags = provided_compiler.flags
+        else:
+            flags = []
+
+        # Ideally, we'd always use the absolute path, but unfortunately, on
+        # Windows, the compiler is very often in a directory containing spaces.
+        # Unfortunately, due to the way autoconf does its compiler tests with
+        # eval, that doesn't work out. So in that case, check that the
+        # compiler can still be found in $PATH, and use the file name instead
+        # of the full path.
+        if quote(compiler) != compiler:
+            full_path = os.path.abspath(compiler)
+            compiler = os.path.basename(compiler)
+            found_compiler = find_program(compiler)
+            if not found_compiler:
+                die('%s is not in your $PATH'
+                    % 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)))
+
+        result = check_compiler(wrapper + [compiler] + flags, language)
+        if result:
+            type, version = result
+            return namespace(
+                wrapper=wrapper,
+                compiler=compiler,
+                flags=flags,
+                type=type,
+                version=version,
+            )
+        die('Failed to get the compiler version')
+
+    if language == 'C++':
+        @depends(valid_compiler, c_compiler)
+        def compiler_suite_consistency(compiler, c_compiler):
+            if compiler.type != c_compiler.type:
+                die('The %s C compiler is %s, while the %s C++ compiler is '
+                    '%s. Need to use the same compiler suite.',
+                    host_or_target_str, c_compiler.type,
+                    host_or_target_str, compiler.type)
+
+            if compiler.version != c_compiler.version:
+                die('The %s C compiler is version %s, while the %s C++ '
+                    'compiler is version %s. Need to use the same compiler '
+                    'version.',
+                    host_or_target_str, c_compiler.version,
+                    host_or_target_str, compiler.version)
+
+    # Set CC/CXX/HOST_CC/HOST_CXX for old-configure, which needs the wrapper
+    # and the flags that were part of the user input for those variables to
+    # be provided.
+    add_old_configure_assignment(var, depends_if(valid_compiler)(
+        lambda x: list(x.wrapper) + [x.compiler] + list(x.flags)))
+
+    # Set CC_TYPE/CC_VERSION/HOST_CC_TYPE/HOST_CC_VERSION to allow
+    # old-configure to do some of its still existing checks.
+    if language == 'C':
+        add_old_configure_assignment(
+            '%s_TYPE' % var, delayed_getattr(valid_compiler, 'type'))
+        add_old_configure_assignment(
+            '%s_VERSION' % var, delayed_getattr(valid_compiler, 'version'))
+
+    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)
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -3,17 +3,16 @@ dnl Local autoconf macros used with mozi
 dnl The contents of this file are under the Public Domain.
 dnl
 
 builtin(include, ../../build/autoconf/hotfixes.m4)dnl
 builtin(include, ../../build/autoconf/acwinpaths.m4)dnl
 builtin(include, ../../build/autoconf/hooks.m4)dnl
 builtin(include, ../../build/autoconf/config.status.m4)dnl
 builtin(include, ../../build/autoconf/toolchain.m4)dnl
-builtin(include, ../../build/autoconf/wrapper.m4)dnl
 builtin(include, ../../build/autoconf/pkg.m4)dnl
 builtin(include, ../../build/autoconf/nspr.m4)dnl
 builtin(include, ../../build/autoconf/nspr-build.m4)dnl
 builtin(include, ../../build/autoconf/codeset.m4)dnl
 builtin(include, ../../build/autoconf/altoptions.m4)dnl
 builtin(include, ../../build/autoconf/mozprog.m4)dnl
 builtin(include, ../../build/autoconf/mozheader.m4)dnl
 builtin(include, ../../build/autoconf/mozcommonheader.m4)dnl
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -157,18 +157,16 @@ else
     fi
     if test -z "$HOST_AR_FLAGS"; then
         HOST_AR_FLAGS='$(AR_FLAGS)'
     fi
 fi
 
 MOZ_TOOL_VARIABLES
 
-MOZ_CHECK_COMPILER_WRAPPER
-
 AC_PROG_CPP
 AC_PROG_CXXCPP
 MOZ_RUST_SUPPORT
 
 dnl Special win32 checks
 dnl ========================================================
 
 # Target the Windows 8.1 SDK by default
--- a/mobile/android/config/mozconfigs/android-api-15-frontend/nightly
+++ b/mobile/android/config/mozconfigs/android-api-15-frontend/nightly
@@ -12,16 +12,19 @@ MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 NO_CACHE=1
 NO_NDK=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
 ac_add_options --with-gradle="$topsrcdir/gradle/bin/gradle"
 export GRADLE_MAVEN_REPOSITORY="file://$topsrcdir/jcentral"
 
+unset HOST_CC
+unset HOST_CXX
+
 ac_add_options --disable-compile-environment
 ac_add_options --disable-tests
 
 # From here on, like ../android-api-15/nightly.
 
 ac_add_options --enable-profiling
 
 # Android
--- a/old-configure.in
+++ b/old-configure.in
@@ -248,22 +248,16 @@ else
     AC_PROG_CXX
     AC_PROG_RANLIB
     MOZ_PATH_PROGS(AS, $AS as, $CC)
     AC_CHECK_PROGS(AR, ar, :)
     AC_CHECK_PROGS(LD, ld, :)
     AC_CHECK_PROGS(STRIP, strip, :)
     AC_CHECK_PROGS(WINDRES, windres, :)
     AC_CHECK_PROGS(OTOOL, otool, :)
-    if test -z "$HOST_CC"; then
-        HOST_CC="$CC"
-    fi
-    if test -z "$HOST_CXX"; then
-        HOST_CXX="$CXX"
-    fi
     if test -z "$HOST_RANLIB"; then
         HOST_RANLIB="$RANLIB"
     fi
     if test -z "$HOST_AR"; then
         HOST_AR="$AR"
     fi
     if test -z "$HOST_AR_FLAGS"; then
         HOST_AR_FLAGS="$AR_FLAGS"
@@ -271,18 +265,16 @@ else
 fi
 
 if test -n "$MOZ_WINCONSOLE"; then
     AC_DEFINE(MOZ_WINCONSOLE)
 fi
 
 MOZ_TOOL_VARIABLES
 
-MOZ_CHECK_COMPILER_WRAPPER
-
 MOZ_RUST_SUPPORT
 
 dnl ========================================================
 dnl Check for MacOS deployment target version
 dnl ========================================================
 
 MOZ_ARG_ENABLE_STRING(macos-target,
                       [  --enable-macos-target=VER (default=10.6)
@@ -1397,18 +1389,16 @@ case "$target" in
         MOZ_FOLD_LIBS_FLAGS=-mnop-fun-dllimport
 
         # We use mix of both POSIX and Win32 printf format across the tree, so format
         # warnings are useless on mingw.
         MOZ_C_SUPPORTS_WARNING(-Wno-, format, ac_c_has_wno_format)
         MOZ_CXX_SUPPORTS_WARNING(-Wno-, format, ac_cxx_has_wno_format)
     else
         TARGET_COMPILER_ABI=msvc
-        HOST_CC='$(CC)'
-        HOST_CXX='$(CXX)'
         HOST_LD='$(LD)'
         if test "$AS_BIN"; then
             AS="$(basename "$AS_BIN")"
         fi
         AR='lib'
         AR_FLAGS='-NOLOGO -OUT:$@'
         AR_EXTRACT=
         RANLIB='echo not_ranlib'