Bug 774032 part 6 - Replace autoconf handling of config files and headers with our own. r=ted
authorMike Hommey <mh+mozilla@glandium.org>
Sat, 04 Aug 2012 08:47:28 +0200
changeset 104531 21c3069ddc4a9d294de06151a7d3486577b1429a
parent 104530 b4218536a9e6b18f0d8de9c8e16abad414fce76a
child 104532 75ac79f11192db4d40b2cb71144a6d49ecbc34c1
push id1989
push userakeybl@mozilla.com
push dateTue, 28 Aug 2012 00:20:43 +0000
treeherdermozilla-aurora@a8e95ae10ea7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs774032
milestone17.0a1
Bug 774032 part 6 - Replace autoconf handling of config files and headers with our own. r=ted
aclocal.m4
allmakefiles.sh
build/ConfigStatus.py
build/Makefile.in
build/autoconf/config.status.m4
build/tests/unit-ConfigStatus.py
client.mk
config/rules.mk
configure.in
gfx/cairo/cairo/src/Makefile.in
js/src/aclocal.m4
js/src/build/ConfigStatus.py
js/src/build/autoconf/config.status.m4
js/src/config/rules.mk
js/src/configure.in
js/src/js-confdefs.h.in
mozilla-config.h.in
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,13 +1,14 @@
 dnl
 dnl Local autoconf macros used with mozilla
 dnl The contents of this file are under the Public Domain.
-dnl 
+dnl
 
+builtin(include, build/autoconf/config.status.m4)dnl
 builtin(include, build/autoconf/toolchain.m4)dnl
 builtin(include, build/autoconf/ccache.m4)dnl
 builtin(include, build/autoconf/nspr.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
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -20,16 +20,17 @@ add_makefiles() {
 }
 
 if [ "$srcdir" = "" ]; then
   srcdir=.
 fi
 
 # Common makefiles used by everyone
 add_makefiles "
+mozilla-config.h
 Makefile
 build/Makefile
 build/pgo/Makefile
 build/pgo/blueprint/Makefile
 build/pgo/js-input/Makefile
 config/Makefile
 config/autoconf.mk
 config/nspr/Makefile
new file mode 100644
--- /dev/null
+++ b/build/ConfigStatus.py
@@ -0,0 +1,313 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Combined with build/autoconf/config.status.m4, ConfigStatus is an almost
+# drop-in replacement for autoconf 2.13's config.status, with features
+# borrowed from autoconf > 2.5, and additional features.
+
+from __future__ import with_statement
+from optparse import OptionParser
+import sys, re, os, posixpath
+from StringIO import StringIO
+# Standalone js doesn't have virtualenv.
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
+from Preprocessor import Preprocessor
+
+# Basic logging facility
+verbose = False
+def log(string):
+    if verbose:
+        print >>sys.stderr, string
+
+# We need relpath, but it is introduced in python 2.6
+# http://docs.python.org/library/os.path.html
+def my_relpath(path, start):
+    """
+    Return a relative version of a path
+    from /usr/lib/python2.6/posixpath.py
+    """
+
+    if not path:
+        raise ValueError("no path specified")
+
+    start_list = os.path.abspath(start).split(os.path.sep)
+    path_list = os.path.abspath(path).split(os.path.sep)
+
+    # Work out how much of the filepath is shared by start and path.
+    i = len(os.path.commonprefix([start_list, path_list]))
+
+    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+    if not rel_list:
+        return os.curdir
+    return os.path.join(*rel_list)
+
+relpath = getattr(os.path, "relpath", my_relpath)
+
+def ensureParentDir(file):
+    '''Ensures the directory parent to the given file exists'''
+    dir = os.path.dirname(file)
+    if dir and not os.path.exists(dir):
+        try:
+            os.makedirs(dir)
+        except OSError, error:
+            if error.errno != errno.EEXIST:
+                raise
+
+class FileAvoidWrite(StringIO):
+    '''file-like object that buffers its output and only writes it to disk
+    if the new contents are different from what the file may already contain.
+    '''
+    def __init__(self, filename):
+        self.filename = filename
+        StringIO.__init__(self)
+
+    def close(self):
+        buf = self.getvalue()
+        StringIO.close(self)
+        try:
+            file = open(self.filename, 'rU')
+        except IOError:
+            pass
+        else:
+            try:
+                 if file.read() == buf:
+                     log("%s is unchanged" % relpath(self.filename, os.curdir))
+                     return
+            except IOError:
+                pass
+            finally:
+                file.close()
+
+        log("creating %s" % relpath(self.filename, os.curdir))
+        ensureParentDir(self.filename)
+        with open(self.filename, 'w') as file:
+            file.write(buf)
+
+    def __enter__(self):
+        return self
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+def shell_escape(s):
+    '''Escape some characters with a backslash, and double dollar signs.
+    '''
+    return re.sub('''([ \t`#$^&*(){}\\|;'"<>?\[\]])''', r'\\\1', str(s)).replace('$', '$$')
+
+class ConfigEnvironment(object):
+    '''A ConfigEnvironment is defined by a source directory and a build
+    directory. It preprocesses files from the source directory and stores
+    the result in the object directory.
+
+     There are two types of files: config files and config headers,
+     each treated through a different member function.
+
+     Creating a ConfigEnvironment requires a few arguments:
+       - topsrcdir and topobjdir are, respectively, the top source and
+         the top object directory.
+       - defines is a list of (name, value) tuples. In autoconf, these are
+         set with AC_DEFINE and AC_DEFINE_UNQUOTED
+       - non_global_defines are a list of names appearing in defines above
+         that are not meant to be exported in ACDEFINES and ALLDEFINES (see
+         below)
+       - substs is a list of (name, value) tuples. In autoconf, these are
+         set with AC_SUBST.
+
+     ConfigEnvironment automatically defines two additional substs variables
+     from all the defines not appearing in non_global_defines:
+       - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on
+         preprocessor command lines. The order in which defines were given
+         when creating the ConfigEnvironment is preserved.
+       - ALLDEFINES contains the defines in the form #define NAME VALUE, in
+         sorted order, for use in config files, for an automatic listing of
+         defines.
+
+    ConfigEnvironment expects a "top_srcdir" subst to be set with the top
+    source directory, in msys format on windows. It is used to derive a
+    "srcdir" subst when treating config files.
+    '''
+
+    def __init__(self, topobjdir = '.', topsrcdir = '.',
+                 defines = [], non_global_defines = [], substs = []):
+        self.defines = dict(defines)
+        self.substs = dict(substs)
+        self.topsrcdir = topsrcdir
+        self.topobjdir = topobjdir
+        global_defines = [name for name, value in defines if not name in non_global_defines]
+        self.substs['ACDEFINES'] = ' '.join(["-D%s=%s" % (name, shell_escape(self.defines[name])) for name in global_defines])
+        self.substs['ALLDEFINES'] = '\n'.join(sorted(["#define %s %s" % (name, self.defines[name]) for name in global_defines]))
+
+    def get_relative_srcdir(self, file):
+        '''Returns the relative source directory for the given file, always
+        using / as a path separator.
+        '''
+        assert(isinstance(file, basestring))
+        dir = posixpath.dirname(relpath(file, self.topobjdir).replace(os.sep, '/'))
+        if dir:
+            return dir
+        return '.'
+
+    def get_file_srcdir(self, file):
+        '''Returns the srcdir for the given file, where srcdir is in msys
+        format on windows, thus derived from top_srcdir.
+        '''
+        dir = self.get_relative_srcdir(file)
+        return posixpath.normpath(posixpath.join(self.substs['top_srcdir'], dir))
+
+    def get_depth(self, file):
+        '''Returns the DEPTH for the given file, that is, the path to the
+        object directory relative to the directory containing the given file.
+        Always uses / as a path separator.
+        '''
+        return relpath(self.topobjdir, os.path.dirname(file)).replace(os.sep, '/')
+
+    def get_input(self, file):
+        '''Returns the input file path in the source tree that can be used
+        to create the given config file or header.
+        '''
+        assert(isinstance(file, basestring))
+        return os.path.normpath(os.path.join(self.topsrcdir, "%s.in" % relpath(file, self.topobjdir)))
+
+    def create_config_file(self, path):
+        '''Creates the given config file. A config file is generated by
+        taking the corresponding source file and replacing occurences of
+        "@VAR@" by the value corresponding to "VAR" in the substs dict.
+
+        Additional substs are defined according to the file being treated:
+            "srcdir" for its the path to its source directory
+            "relativesrcdir" for its source directory relative to the top
+            "DEPTH" for the path to the top object directory
+        '''
+        input = self.get_input(path)
+        pp = Preprocessor()
+        pp.context.update(self.substs)
+        pp.context.update(srcdir = self.get_file_srcdir(path))
+        pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
+        pp.context.update(DEPTH = self.get_depth(path))
+        pp.do_filter('attemptSubstitution')
+        pp.setMarker(None)
+        with FileAvoidWrite(path) as pp.out:
+            pp.do_include(input)
+
+    def create_config_header(self, path):
+        '''Creates the given config header. A config header is generated by
+        taking the corresponding source file and replacing some #define/#undef
+        occurences:
+            "#undef NAME" is turned into "#define NAME VALUE"
+            "#define NAME" is unchanged
+            "#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
+            "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
+            Whitespaces are preserved.
+        '''
+        with open(self.get_input(path), 'rU') as input:
+            ensureParentDir(path)
+            output = FileAvoidWrite(path)
+            r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
+            for l in input:
+                m = r.match(l)
+                if m:
+                    cmd = m.group('cmd')
+                    name = m.group('name')
+                    value = m.group('value')
+                    if name:
+                        if name in self.defines:
+                            if cmd == 'define' and value:
+                                l = l[:m.start('value')] + str(self.defines[name]) + l[m.end('value'):]
+                            elif cmd == 'undef':
+                                l = l[:m.start('cmd')] + 'define' + l[m.end('cmd'):m.end('name')] + ' ' + str(self.defines[name]) + l[m.end('name'):]
+                        elif cmd == 'undef':
+                           l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
+
+                output.write(l)
+            output.close()
+
+def config_status(topobjdir = '.', topsrcdir = '.',
+                  defines = [], non_global_defines = [], substs = [],
+                  files = [], headers = []):
+    '''Main function, providing config.status functionality.
+
+    Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
+    variables, but like config.status from autoconf 2.6, single files may be
+    generated with the --file and --header options. Several such options can
+    be given to generate several files at the same time.
+
+    Without the -n option, this program acts as config.status and considers
+    the current directory as the top object directory, even when config.status
+    is in a different directory. It will, however, treat the directory
+    containing config.status as the top object directory with the -n option,
+    while files given to the --file and --header arguments are considered
+    relative to the current directory.
+
+    The --recheck option, like with the original config.status, runs configure
+    again, with the options given in the "ac_configure_args" subst.
+
+    The options to this function are passed when creating the
+    ConfigEnvironment, except for files and headers, which contain the list
+    of files and headers to be generated by default. These lists, as well as
+    the actual wrapper script around this function, are meant to be generated
+    by configure. See build/autoconf/config.status.m4.
+
+    Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS,
+    but like config.status behaviour with --file and --header, providing
+    files or headers on the command line inhibits the default generation of
+    files when given headers and headers when given files.
+
+    Unlike config.status, the FILE:TEMPLATE syntax is not supported for
+    files and headers. The template is always the filename suffixed with
+    '.in', in the corresponding directory under the top source directory.
+    '''
+
+    if 'CONFIG_FILES' in os.environ:
+        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+    if 'CONFIG_HEADERS' in os.environ:
+        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+
+    parser = OptionParser()
+    parser.add_option('--recheck', dest='recheck', action='store_true',
+                      help='update config.status by reconfiguring in the same conditions')
+    parser.add_option('--file', dest='files', metavar='FILE', action='append',
+                      help='instantiate the configuration file FILE')
+    parser.add_option('--header', dest='headers', metavar='FILE', action='append',
+                      help='instantiate the configuration header FILE')
+    parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+                      help='display verbose output')
+    parser.add_option('-n', dest='not_topobjdir', action='store_true',
+                      help='do not consider current directory as top object directory')
+    (options, args) = parser.parse_args()
+
+    # Without -n, the current directory is meant to be the top object directory
+    if not options.not_topobjdir:
+        topobjdir = '.'
+
+    env = ConfigEnvironment(topobjdir = topobjdir, topsrcdir = topsrcdir,
+                            defines = defines, non_global_defines = non_global_defines,
+                            substs = substs)
+
+    if options.recheck:
+        # Execute configure from the top object directory
+        if not os.path.isabs(topsrcdir):
+            topsrcdir = relpath(topsrcdir, topobjdir)
+        os.chdir(topobjdir)
+        os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion']))
+
+    if options.files:
+        files = options.files
+        headers = []
+    if options.headers:
+        headers = options.headers
+        if not options.files:
+            files = []
+    # Default to display messages when giving --file or --headers on the
+    # command line.
+    if options.files or options.headers or options.verbose:
+        global verbose
+        verbose = True
+    if not options.files and not options.headers:
+        print >>sys.stderr, "creating config files and headers..."
+        files = [os.path.join(topobjdir, f) for f in files]
+        headers = [os.path.join(topobjdir, f) for f in headers]
+
+    for file in files:
+        env.create_config_file(file)
+    for header in headers:
+        env.create_config_header(header)
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -258,9 +258,13 @@ check::
 endif
 
 ifeq ($(OS_ARCH),Linux)
 libs:: $(topsrcdir)/tools/rb/fix-linux-stack.pl
 	$(INSTALL) $< $(DIST)/bin
 endif
 
 GARBAGE += $(srcdir)/automationutils.pyc
+
+# Test for ConfigStatus.py
+check::
+	$(PYTHON) $(srcdir)/tests/unit-ConfigStatus.py
 endif # ENABLE_TESTS
new file mode 100644
--- /dev/null
+++ b/build/autoconf/config.status.m4
@@ -0,0 +1,167 @@
+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 For use in AC_SUBST replacement
+define([MOZ_DIVERSION_SUBST], 11)
+
+dnl Replace AC_SUBST to store values in a format suitable for python.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_SUBST(),bar)
+define([AC_SUBST],
+[ifdef([AC_SUBST_$1], ,
+[define([AC_SUBST_$1], )dnl
+AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
+        (''' $1 ''', r''' [$]$1 ''')
+AC_DIVERT_POP()dnl
+])])
+
+dnl Wrap AC_DEFINE to store values in a format suitable for python.
+dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h,
+dnl which is #included during some compile checks.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_DEFINE(),bar)
+define([_MOZ_AC_DEFINE], defn([AC_DEFINE]))
+define([AC_DEFINE],
+[cat >> confdefs.pytmp <<\EOF
+        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE([$1], [$2]), $#, 3, _MOZ_AC_DEFINE([$1], [$2], [$3]),_MOZ_AC_DEFINE([$1]))dnl
+])
+
+dnl Wrap AC_DEFINE_UNQUOTED to store values in a format suitable for
+dnl python.
+define([_MOZ_AC_DEFINE_UNQUOTED], defn([AC_DEFINE_UNQUOTED]))
+define([AC_DEFINE_UNQUOTED],
+[cat >> confdefs.pytmp <<EOF
+        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
+])
+
+dnl Replace AC_OUTPUT to create and call a python config.status
+define([AC_OUTPUT],
+[dnl Top source directory in Windows format (as opposed to msys format).
+WIN_TOP_SRC=
+case "$host_os" in
+mingw*)
+    WIN_TOP_SRC=`cd $srcdir; pwd -W`
+    ;;
+esac
+AC_SUBST(WIN_TOP_SRC)
+
+dnl Used in all Makefile.in files
+top_srcdir=$srcdir
+AC_SUBST(top_srcdir)
+
+dnl Picked from autoconf 2.13
+trap '' 1 2 15
+AC_CACHE_SAVE
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+: ${CONFIG_STATUS=./config.status}
+
+dnl We're going to need [ ] for python syntax.
+changequote(<<<, >>>)dnl
+echo creating $CONFIG_STATUS
+
+cat > $CONFIG_STATUS <<EOF
+#!${PYTHON}
+
+import os, sys
+dnl topsrcdir is the top source directory in native form, as opposed to a
+dnl form suitable for make.
+topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
+if not os.path.isabs(topsrcdir):
+    topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
+dnl Don't rely on virtualenv here. Standalone js doesn't use it.
+sys.path.append(os.path.join(topsrcdir, 'build'))
+from ConfigStatus import config_status
+
+args = {
+    'topsrcdir': topsrcdir,
+    'topobjdir': os.path.dirname(<<<__file__>>>),
+
+dnl All defines and substs are stored with an additional space at the beginning
+dnl and at the end of the string, to avoid any problem with values starting or
+dnl ending with quotes.
+    'defines': [(name[1:-1], value[1:-1]) for name, value in [
+EOF
+
+dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but
+dnl lacks the final comma (see above).
+sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS
+rm confdefs.pytmp confdefs.h
+
+cat >> $CONFIG_STATUS <<\EOF
+    ] ],
+
+    'substs': [(name[1:-1], value[1:-1]) for name, value in [
+EOF
+
+dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
+dnl expected format, but lacks the final comma (see above).
+sed 's/$/,/' >> $CONFIG_STATUS <<EOF
+undivert(MOZ_DIVERSION_SUBST)dnl
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+    ] ],
+
+dnl List of files to apply AC_SUBSTs to. This is the list of files given
+dnl as an argument to AC_OUTPUT ($1)
+    'files': [
+EOF
+
+for out in $1; do
+  echo "        '$out'," >> $CONFIG_STATUS
+done
+
+cat >> $CONFIG_STATUS <<\EOF
+    ],
+
+dnl List of header files to apply AC_DEFINEs to. This is stored in the
+dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER.
+    'headers': [
+EOF
+
+ifdef(<<<AC_LIST_HEADER>>>, <<<
+HEADERS="AC_LIST_HEADER"
+for header in $HEADERS; do
+  echo "        '$header'," >> $CONFIG_STATUS
+done
+>>>)dnl
+
+cat >> $CONFIG_STATUS <<\EOF
+    ],
+
+dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
+    'non_global_defines': [
+EOF
+
+if test -n "$_NON_GLOBAL_ACDEFINES"; then
+  for var in $_NON_GLOBAL_ACDEFINES; do
+    echo "        '$var'," >> $CONFIG_STATUS
+  done
+fi
+
+cat >> $CONFIG_STATUS <<\EOF
+    ]
+}
+
+dnl Do the actual work
+config_status(**args)
+EOF
+changequote([, ])
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+dnl Execute config.status, unless --no-create was passed to configure.
+test "$no_create" = yes || ${PYTHON} $CONFIG_STATUS || exit 1
+])
new file mode 100644
--- /dev/null
+++ b/build/tests/unit-ConfigStatus.py
@@ -0,0 +1,282 @@
+from __future__ import with_statement
+import os
+from StringIO import StringIO
+import unittest
+from mozunit import main, MockedOpen
+import ConfigStatus
+from ConfigStatus import FileAvoidWrite
+
+class ConfigEnvironment(ConfigStatus.ConfigEnvironment):
+    def __init__(self, **args):
+        ConfigStatus.ConfigEnvironment.__init__(self, **args)
+        # Be helpful to unit tests
+        if not 'top_srcdir' in self.substs:
+            self.substs['top_srcdir'] = self.topsrcdir.replace(os.sep, '/')
+
+class TestFileAvoidWrite(unittest.TestCase):
+    def test_file_avoid_write(self):
+        '''Test the FileAvoidWrite class
+        '''
+        with MockedOpen({'file': 'content'}):
+            # Overwriting an existing file replaces its content
+            with FileAvoidWrite('file') as file:
+                file.write('bazqux')
+            self.assertEqual(open('file', 'r').read(), 'bazqux')
+
+            # Creating a new file (obviously) stores its content
+            with FileAvoidWrite('file2') as file:
+                file.write('content')
+            self.assertEqual(open('file2').read(), 'content')
+
+        class MyMockedOpen(MockedOpen):
+            '''MockedOpen extension to raise an exception if something
+            attempts to write in an opened file.
+            '''
+            def __call__(self, name, mode):
+                if 'w' in mode:
+                    raise Exception, 'Unexpected open with write mode'
+                return MockedOpen.__call__(self, name, mode)
+
+        with MyMockedOpen({'file': 'content'}):
+            # Validate that MyMockedOpen works as intended
+            file = FileAvoidWrite('file')
+            file.write('foobar')
+            self.assertRaises(Exception, file.close)
+
+            # Check that no write actually happens when writing the
+            # same content as what already is in the file
+            with FileAvoidWrite('file') as file:
+                file.write('content')
+
+
+class TestEnvironment(unittest.TestCase):
+    def test_auto_substs(self):
+        '''Test the automatically set values of ACDEFINES and ALLDEFINES.
+        '''
+        env = ConfigEnvironment(
+                  defines = [ ('foo', 'bar'), ('baz', 'qux 42'),
+                              ('abc', 'def'), ('extra', 'foobar') ],
+                  non_global_defines = ['extra', 'ignore'])
+        # non_global_defines should be filtered out in ACDEFINES and
+        # ALLDEFINES.
+        # Original order of the defines need to be respected in ACDEFINES
+        self.assertEqual(env.substs['ACDEFINES'], '-Dfoo=bar -Dbaz=qux\\ 42 -Dabc=def')
+        # ALLDEFINES, on the other hand, needs to be sorted
+        self.assertEqual(env.substs['ALLDEFINES'], '''#define abc def
+#define baz qux 42
+#define foo bar''')
+
+    def test_config_file(self):
+        '''Test the creation of config files.
+        '''
+        with MockedOpen({'file.in': '''#ifdef foo
+@foo@
+@bar@
+'''}):
+            env = ConfigEnvironment(substs = [ ('foo', 'bar baz') ])
+            env.create_config_file('file')
+            self.assertEqual(open('file', 'r').read(), '''#ifdef foo
+bar baz
+@bar@
+''')
+
+    def test_config_header(self):
+        '''Test the creation of config headers.
+        '''
+        with MockedOpen({'file.in': '''
+/* Comment */
+#define foo
+#define foo 42
+#undef foo
+#define bar
+#define bar 42
+#undef bar
+
+# undef baz
+
+#ifdef foo
+#   undef   foo
+#  define foo    42
+  #     define   foo   42   
+#endif
+'''}):
+            env = ConfigEnvironment(defines = [ ('foo', 'baz qux'), ('baz', 1) ])
+            env.create_config_header('file')
+            self.assertEqual(open('file','r').read(), '''
+/* Comment */
+#define foo
+#define foo baz qux
+#define foo baz qux
+#define bar
+#define bar 42
+/* #undef bar */
+
+# define baz 1
+
+#ifdef foo
+#   define   foo baz qux
+#  define foo    baz qux
+  #     define   foo   baz qux   
+#endif
+''')
+
+# Tests for get_relative_srcdir, get_depth, get_input and get_file_srcdir,
+# depending on various cases of top source directory and top build
+# directory location.
+class TestPaths(unittest.TestCase):
+    def setUp(self):
+        self.dir = os.path.basename(os.path.abspath(os.curdir))
+        self.absolute = os.path.normpath('/absolute')
+
+class TestPathsLocalBuildDir(TestPaths):
+    def get_env(self, topsrcdir):
+        env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = '.')
+        self.assertEqual(env.get_relative_srcdir('file'), '.')
+        self.assertEqual(env.get_relative_srcdir('dir/file'), 'dir')
+        self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), 'deeply/nested/path/to')
+        self.assertEqual(env.get_depth('file'), '.')
+        self.assertEqual(env.get_depth('dir/file'), '..')
+        self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../..')
+        return env
+
+    def test_paths_local_build_local_src(self):
+        env = self.get_env('.')
+        self.assertEqual(env.get_input('file'), 'file.in')
+        self.assertEqual(env.get_input('dir/file'), os.path.join('dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('file'), '.')
+        self.assertEqual(env.get_file_srcdir('dir/file'), 'dir')
+
+    def test_paths_local_build_parent_src(self):
+        env = self.get_env('..')
+        self.assertEqual(env.get_input('file'), os.path.join('..', 'file.in'))
+        self.assertEqual(env.get_input('dir/file'), os.path.join('..', 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('file'), '..')
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../dir')
+
+    def test_paths_local_build_absolute_src(self):
+        env = self.get_env(self.absolute)
+        self.assertEqual(env.get_input('file'), os.path.join(self.absolute, 'file.in'))
+        self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_input('%s/file' % self.dir), os.path.join(self.absolute, self.dir, 'file.in'))
+        self.assertEqual(env.get_file_srcdir('file'), '/absolute')
+        self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/dir')
+        self.assertEqual(env.get_file_srcdir('%s/file' % dir), '/absolute/%s' % dir)
+
+class TestPathsParentBuildDir(TestPaths):
+    def get_env(self, topsrcdir):
+        env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = '..')
+        self.assertEqual(env.get_relative_srcdir('..'), '.')
+        self.assertEqual(env.get_relative_srcdir('file'), self.dir)
+        self.assertEqual(env.get_relative_srcdir('dir/file'), '%s/dir' % self.dir)
+        self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), '%s/deeply/nested/path/to' % self.dir)
+        self.assertEqual(env.get_depth('../file'), '.')
+        self.assertEqual(env.get_depth('file'), '..')
+        self.assertEqual(env.get_depth('dir/file'), '../..')
+        self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../../..')
+        return env
+
+    def test_paths_parent_build_parent_src(self):
+        env = self.get_env('..')
+        self.assertEqual(env.get_input('../file'), os.path.join('..', 'file.in'))
+        self.assertEqual(env.get_input('file'), os.path.join('..', self.dir, 'file.in'))
+        self.assertEqual(env.get_input('dir/file'), os.path.join('..', self.dir, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('../file'), '..')
+        self.assertEqual(env.get_file_srcdir('file'), '../%s' % self.dir)
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../%s/dir' % self.dir)
+
+    def test_paths_parent_build_ancestor_src(self):
+        env = self.get_env('../..')
+        self.assertEqual(env.get_input('../file'), os.path.join('..', '..', 'file.in'))
+        self.assertEqual(env.get_input('file'), os.path.join('..', '..', self.dir, 'file.in'))
+        self.assertEqual(env.get_input('dir/file'), os.path.join('..', '..', self.dir, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('../file'), '../..')
+        self.assertEqual(env.get_file_srcdir('file'), '../../%s' % self.dir)
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../../%s/dir' % self.dir)
+
+    def test_paths_parent_build_absolute_src(self):
+        env = self.get_env(self.absolute)
+        self.assertEqual(env.get_input('../file'), os.path.join(self.absolute, 'file.in'))
+        self.assertEqual(env.get_input('file'), os.path.join(self.absolute, self.dir, 'file.in'))
+        self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, self.dir, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('../file'), '/absolute')
+        self.assertEqual(env.get_file_srcdir('file'), '/absolute/%s' % self.dir)
+        self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/%s/dir' % self.dir)
+
+class TestPathsRelativeBuild(TestPaths):
+    def get_env(self, topsrcdir):
+        env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = 'relative')
+        self.assertEqual(env.get_relative_srcdir('relative/file'), '.')
+        self.assertEqual(env.get_relative_srcdir('relative/dir/file'), 'dir')
+        self.assertEqual(env.get_relative_srcdir('relative/deeply/nested/path/to/file'), 'deeply/nested/path/to')
+        self.assertEqual(env.get_depth('relative/file'), '.')
+        self.assertEqual(env.get_depth('relative/dir/file'), '..')
+        self.assertEqual(env.get_depth('relative/deeply/nested/path/to/file'), '../../../..')
+        return env
+
+    def test_paths_relative_build_relative_src(self):
+        env = self.get_env('relative')
+        self.assertEqual(env.get_input('relative/file'), os.path.join('relative', 'file.in'))
+        self.assertEqual(env.get_input('relative/dir/file'), os.path.join('relative', 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('relative/file'), 'relative')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), 'relative/dir')
+
+    def test_paths_relative_build_local_src(self):
+        env = self.get_env('.')
+        self.assertEqual(env.get_input('relative/file'), 'file.in')
+        self.assertEqual(env.get_input('relative/dir/file'), os.path.join('dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('relative/file'), '.')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), 'dir')
+
+    def test_paths_relative_build_parent_src(self):
+        env = self.get_env('..')
+        self.assertEqual(env.get_input('relative/file'), os.path.join('..', 'file.in'))
+        self.assertEqual(env.get_input('relative/dir/file'), os.path.join('..', 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('relative/file'), '..')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../dir')
+
+    def test_paths_relative_build_absolute_src(self):
+        env = self.get_env(self.absolute)
+        self.assertEqual(env.get_input('relative/file'), os.path.join(self.absolute, 'file.in'))
+        self.assertEqual(env.get_input('relative/dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('relative/file'), '/absolute')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '/absolute/dir')
+
+class TestPathsAbsoluteBuild(unittest.TestCase):
+    def setUp(self):
+        self.absolute_build = os.path.normpath('/absolute/build')
+
+    def get_env(self, topsrcdir):
+        env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = self.absolute_build)
+        self.assertEqual(env.get_relative_srcdir('/absolute/build/file'), '.')
+        self.assertEqual(env.get_relative_srcdir('/absolute/build/dir/file'), 'dir')
+        self.assertEqual(env.get_relative_srcdir('/absolute/build/deeply/nested/path/to/file'), 'deeply/nested/path/to')
+        self.assertEqual(env.get_depth('/absolute/build/file'), '.')
+        self.assertEqual(env.get_depth('/absolute/build/dir/file'), '..')
+        self.assertEqual(env.get_depth('/absolute/build/deeply/nested/path/to/file'), '../../../..')
+        return env
+
+    def test_paths_absolute_build_same_src(self):
+        env = self.get_env(self.absolute_build)
+        self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(self.absolute_build, 'file.in'))
+        self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(self.absolute_build, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute/build')
+        self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/build/dir')
+
+    def test_paths_absolute_build_ancestor_src(self):
+        absolute = os.path.dirname(self.absolute_build)
+        env = self.get_env(absolute)
+        self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
+        self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute')
+        self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/dir')
+
+    def test_paths_absolute_build_different_src(self):
+        absolute = os.path.normpath('/some/path')
+        env = self.get_env(absolute)
+        self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
+        self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/some/path')
+        self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/some/path/dir')
+
+if __name__ == "__main__":
+    main()
--- a/client.mk
+++ b/client.mk
@@ -315,18 +315,17 @@ ifneq (,$(MAKEFILE))
 $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
 else
 $(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)
 endif
 	@$(MAKE) -f $(TOPSRCDIR)/client.mk configure
 
 ifneq (,$(CONFIG_STATUS))
 $(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
-	cd $(OBJDIR); \
-	  CONFIG_FILES=config/autoconf.mk ./config.status
+	$(OBJDIR)/config.status -n --file=$(OBJDIR)/config/autoconf.mk
 endif
 
 
 ####################################
 # Depend
 
 depend:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
 	$(MOZ_MAKE) export && $(MOZ_MAKE) depend
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1148,37 +1148,36 @@ endif
 
 GARBAGE_DIRS += $(_JAVA_DIR)
 
 ###############################################################################
 # Update Makefiles
 ###############################################################################
 
 ifndef NO_MAKEFILE_RULE
-# Note: Passing depth to make-makefile is optional.
-#       It saves the script some work, though.
 Makefile: Makefile.in
-	@$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH)
+	@$(DEPTH)/config.status -n --file=Makefile
 endif
 
 ifndef NO_SUBMAKEFILES_RULE
 ifdef SUBMAKEFILES
 # VPATH does not work on some machines in this case, so add $(srcdir)
 $(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(if $(subsrcdir),cd $(subsrcdir) && )$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir)$(addprefix /,$(subsrcdir)) -d $(DEPTH) $(@:$(subsrcdir)/%=%)
+	$(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file=$@
 endif
 endif
 
 ifdef AUTOUPDATE_CONFIGURE
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
+	(cd $(topsrcdir) && $(AUTOCONF)) && $(DEPTH)/config.status -n --recheck)
 endif
 
 $(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status
+	$(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
+	$(TOUCH) $@
 
 ###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ################################################################################
 # Copy each element of EXPORTS to $(DIST)/include
 
--- a/configure.in
+++ b/configure.in
@@ -1028,17 +1028,16 @@ DLL_PREFIX=lib
 LIB_PREFIX=lib
 DLL_SUFFIX=.so
 OBJ_SUFFIX=o
 LIB_SUFFIX=a
 ASM_SUFFIX=s
 IMPORT_LIB_SUFFIX=
 TARGET_MD_ARCH=unix
 DIRENT_INO=d_ino
-WIN_TOP_SRC=
 MOZ_USER_DIR=".mozilla"
 
 MOZ_JPEG_CFLAGS=
 MOZ_JPEG_LIBS='$(call EXPAND_LIBNAME_PATH,mozjpeg,$(DEPTH)/media/libjpeg)'
 MOZ_BZ2_CFLAGS=
 MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)'
 MOZ_PNG_CFLAGS=
 MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/media/libpng)'
@@ -7982,18 +7981,16 @@ if test "$MOZ_TREE_CAIRO"; then
     MOZ_CAIRO_LIBS='$(call EXPAND_LIBNAME_PATH,mozcairo,$(DEPTH)/gfx/cairo/cairo/src)'" $CAIRO_FT_LIBS"
     MOZ_CAIRO_OSLIBS='${CAIRO_FT_OSLIBS}'
 
     if test "$MOZ_X11"; then
         MOZ_CAIRO_OSLIBS="$MOZ_CAIRO_OSLIBS $XLDFLAGS -lXrender -lfreetype -lfontconfig"
     fi
 
     CAIRO_FEATURES_H=gfx/cairo/cairo/src/cairo-features.h
-    mv -f $CAIRO_FEATURES_H "$CAIRO_FEATURES_H".orig 2> /dev/null
-
 else
     PKG_CHECK_MODULES(CAIRO, cairo >= $CAIRO_VERSION)
     MOZ_CAIRO_CFLAGS="$CAIRO_CFLAGS"
     MOZ_CAIRO_LIBS="$CAIRO_LIBS"
     PKG_CHECK_MODULES(CAIRO_TEE, cairo-tee >= $CAIRO_VERSION)
     if test "$MOZ_X11"; then
         PKG_CHECK_MODULES(CAIRO_XRENDER, cairo-xlib-xrender >= $CAIRO_VERSION)
         MOZ_CAIRO_LIBS="$MOZ_CAIRO_LIBS $XLDFLAGS $CAIRO_XRENDER_LIBS"
@@ -8666,24 +8663,16 @@ if test "$ACCESSIBILITY" -a "$MOZ_ENABLE
     ATK_MAJOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $1 }'`
     ATK_MINOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $2 }'`
     ATK_REV_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $3 }'`
     AC_DEFINE_UNQUOTED(ATK_MAJOR_VERSION, $ATK_MAJOR_VERSION)
     AC_DEFINE_UNQUOTED(ATK_MINOR_VERSION, $ATK_MINOR_VERSION)
     AC_DEFINE_UNQUOTED(ATK_REV_VERSION, $ATK_REV_VERSION)
 fi
 
-case "$host_os" in
-mingw*)
-    WIN_TOP_SRC=`cd $srcdir; pwd -W`
-    ;;
-esac
-
-AC_SUBST(WIN_TOP_SRC)
-
 AC_SUBST(MOZILLA_VERSION)
 
 AC_SUBST(ac_configure_args)
 
 dnl Spit out some output
 dnl ========================================================
 
 dnl The following defines are used by xpcom
@@ -8725,90 +8714,16 @@ case "$host" in
 *-apple-darwin11*)
     FIXED_EGREP="env ARCHPREFERENCE=i386,x86_64 arch egrep"
     ;;
 *)
     FIXED_EGREP="egrep"
     ;;
 esac
 
-# Save the defines header file before autoconf removes it.
-# (Do not add AC_DEFINE calls after this line.)
-  _CONFIG_TMP=confdefs-tmp.h
-  _CONFIG_DEFS_H=mozilla-config.h
-
-  cat > $_CONFIG_TMP <<\EOF
-/* List of defines generated by configure. Included with preprocessor flag,
- * -include, to avoid long list of -D defines on the compile command-line.
- * Do not edit.
- */
-
-#ifndef _MOZILLA_CONFIG_H_
-#define _MOZILLA_CONFIG_H_
-EOF
-
-_EGREP_PATTERN='^#define ('
-if test -n "$_NON_GLOBAL_ACDEFINES"; then
-    for f in $_NON_GLOBAL_ACDEFINES; do
-        _EGREP_PATTERN="${_EGREP_PATTERN}$f|"
-    done
-fi
-_EGREP_PATTERN="${_EGREP_PATTERN}dummy_never_defined)"
-
-  sort confdefs.h | $FIXED_EGREP -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
-
-  if test "$?" != 0; then
-    AC_MSG_ERROR([Error outputting config definitions])
-  fi
-
-  cat >> $_CONFIG_TMP <<\EOF
-
-/* The c99 defining the limit macros (UINT32_MAX for example), says:
- * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
- * is defined before <stdint.h> is included. */
-#define __STDC_LIMIT_MACROS
-
-/* Force-include hunspell_alloc_hooks.h for hunspell, so that we don't need to
- * modify it directly.
- *
- * HUNSPELL_STATIC is defined in extensions/spellcheck/hunspell/src/Makefile.in,
- * unless --enable-system-hunspell is defined.
- */
-#if defined(HUNSPELL_STATIC)
-#include "hunspell_alloc_hooks.h"
-#endif
-
-#endif /* _MOZILLA_CONFIG_H_ */
-
-EOF
-
-  # Only write mozilla-config.h when something changes (or it doesn't exist)
-  if cmp -s $_CONFIG_TMP $_CONFIG_DEFS_H; then
-    rm $_CONFIG_TMP
-  else
-    AC_MSG_RESULT("creating $_CONFIG_DEFS_H")
-    mv -f $_CONFIG_TMP $_CONFIG_DEFS_H
-
-    echo ==== $_CONFIG_DEFS_H =================================
-    cat $_CONFIG_DEFS_H
-  fi
-
-dnl Probably shouldn't call this manually but we always want the output of DEFS
-rm -f confdefs.h.save
-mv confdefs.h confdefs.h.save
-$FIXED_EGREP -v "$_EGREP_PATTERN" confdefs.h.save > confdefs.h
-if test "$?" != 0; then
-  AC_MSG_ERROR([Error outputting confdefs.h])
-fi
-AC_OUTPUT_MAKE_DEFS()
-ACDEFINES=$DEFS
-AC_SUBST(ACDEFINES)
-rm -f confdefs.h
-mv confdefs.h.save confdefs.h
-
 dnl Create a virtualenv where we can install local Python packages
 AC_MSG_RESULT([Creating Python virtualenv])
 rm -rf _virtualenv
 mkdir -p _virtualenv
 MACOSX_DEPLOYMENT_TARGET= PYTHONDONTWRITEBYTECODE= $PYTHON $_topsrcdir/python/virtualenv/virtualenv.py --system-site-packages ./_virtualenv
 case "$host_os" in
 mingw*)
     PYTHON=$MOZ_BUILD_ROOT/_virtualenv/Scripts/python.exe
@@ -8828,37 +8743,19 @@ MACOSX_DEPLOYMENT_TARGET= LDFLAGS="${HOS
   $PYTHON $_topsrcdir/build/virtualenv/populate_virtualenv.py \
     $_topsrcdir $_topsrcdir/build/virtualenv/packages.txt \
   || exit 1
 
 dnl Load the list of Makefiles to generate.
 dnl   To add new Makefiles, edit allmakefiles.sh.
 dnl   allmakefiles.sh sets the variable, MAKEFILES.
 . ${srcdir}/allmakefiles.sh
-dnl
-dnl Run a perl script to quickly create the makefiles.
-dnl If it succeeds, it outputs a shell command to set CONFIG_FILES
-dnl   for the files it cannot handle correctly. This way, config.status
-dnl   will handle these files.
-dnl If it fails, nothing is set and config.status will run as usual.
-dnl
-dnl This does not change the $MAKEFILES variable.
-dnl
-echo $MAKEFILES | ${PERL} $srcdir/build/autoconf/acoutput-fast.pl > conftest.sh
-res="$?"
-if test "$res" != 0; then
-    exit $res
-fi
-. ./conftest.sh
-rm conftest.sh
 
 echo $MAKEFILES > unallmakefiles
 
-mv -f config/autoconf.mk config/autoconf.mk.orig 2> /dev/null
-
 AC_OUTPUT($MAKEFILES)
 
 # Generate Makefiles for WebRTC directly from .gyp files
 if test "${OS_TARGET}" = "WINNT"; then
    if test "$HAVE_64BIT_OS"; then
       OS_BITS=64
    else
       OS_BITS=32
@@ -8908,26 +8805,16 @@ OS_TARGET=${OS_TARGET} TARGET_CPU=${TARG
 MOZ_WIDGET_TOOLKIT=${MOZ_WIDGET_TOOLKIT} UNIVERSAL_BINARY=${UNIVERSAL_BINARY} \
   $PYTHON ${_topsrcdir}/config/writemozinfo.py ./mozinfo.json.tmp
 if cmp -s ./mozinfo.json.tmp ./mozinfo.json; then
   rm ./mozinfo.json.tmp
 else
   mv -f ./mozinfo.json.tmp ./mozinfo.json
 fi
 
-dnl Prevent the regeneration of cairo-features.h forcing rebuilds of gfx stuff
-if test "$CAIRO_FEATURES_H"; then
-  if cmp -s $CAIRO_FEATURES_H "$CAIRO_FEATURES_H".orig; then
-    echo "$CAIRO_FEATURES_H is unchanged"
-    mv -f "$CAIRO_FEATURES_H".orig "$CAIRO_FEATURES_H" 2> /dev/null
-  else
-    rm -f "$CAIRO_FEATURES_H".orig 2> /dev/null
-  fi
-fi
-
 # Run jemalloc configure script
 
 if test "$MOZ_JEMALLOC" -a "$MOZ_MEMORY"; then
   ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
   if test "$OS_ARCH" = "Linux"; then
     MANGLE="malloc calloc valloc free realloc memalign posix_memalign malloc_usable_size"
     MANGLED=
     JEMALLOC_WRAPPER=
@@ -9126,18 +9013,8 @@ export MOZ_ZLIB_LIBS
 export MOZ_APP_NAME
 export STLPORT_CPPFLAGS
 export STLPORT_LDFLAGS
 export STLPORT_LIBS
 AC_OUTPUT_SUBDIRS(js/src)
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 
 fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
-
-dnl Prevent the regeneration of autoconf.mk forcing rebuilds of the world
-dnl Needs to be at the end to respect possible changes from NSPR configure
-if cmp -s config/autoconf.mk config/autoconf.mk.orig; then
-  echo "config/autoconf.mk is unchanged"
-  mv -f config/autoconf.mk.orig config/autoconf.mk 2> /dev/null
-else
-  rm -f config/autoconf.mk.orig 2> /dev/null
-fi
-
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -228,9 +228,9 @@ endif
 ifndef MOZ_TREE_PIXMAN
 CFLAGS += $(MOZ_PIXMAN_CFLAGS)
 CXXFLAGS += $(MOZ_PIXMAN_CFLAGS)
 else
 DEFINES += -DMOZ_TREE_PIXMAN
 endif
 
 cairo-features.h: $(srcdir)/cairo-features.h.in $(GLOBAL_DEPS)
-	$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) ./$@
+	$(DEPTH)/config.status -n --file=$@
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -1,13 +1,14 @@
 dnl
 dnl Local autoconf macros used with mozilla
 dnl The contents of this file are under the Public Domain.
 dnl
 
+builtin(include, build/autoconf/config.status.m4)dnl
 builtin(include, build/autoconf/toolchain.m4)dnl
 builtin(include, build/autoconf/ccache.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/moznbytetype.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
new file mode 100644
--- /dev/null
+++ b/js/src/build/ConfigStatus.py
@@ -0,0 +1,313 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Combined with build/autoconf/config.status.m4, ConfigStatus is an almost
+# drop-in replacement for autoconf 2.13's config.status, with features
+# borrowed from autoconf > 2.5, and additional features.
+
+from __future__ import with_statement
+from optparse import OptionParser
+import sys, re, os, posixpath
+from StringIO import StringIO
+# Standalone js doesn't have virtualenv.
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
+from Preprocessor import Preprocessor
+
+# Basic logging facility
+verbose = False
+def log(string):
+    if verbose:
+        print >>sys.stderr, string
+
+# We need relpath, but it is introduced in python 2.6
+# http://docs.python.org/library/os.path.html
+def my_relpath(path, start):
+    """
+    Return a relative version of a path
+    from /usr/lib/python2.6/posixpath.py
+    """
+
+    if not path:
+        raise ValueError("no path specified")
+
+    start_list = os.path.abspath(start).split(os.path.sep)
+    path_list = os.path.abspath(path).split(os.path.sep)
+
+    # Work out how much of the filepath is shared by start and path.
+    i = len(os.path.commonprefix([start_list, path_list]))
+
+    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
+    if not rel_list:
+        return os.curdir
+    return os.path.join(*rel_list)
+
+relpath = getattr(os.path, "relpath", my_relpath)
+
+def ensureParentDir(file):
+    '''Ensures the directory parent to the given file exists'''
+    dir = os.path.dirname(file)
+    if dir and not os.path.exists(dir):
+        try:
+            os.makedirs(dir)
+        except OSError, error:
+            if error.errno != errno.EEXIST:
+                raise
+
+class FileAvoidWrite(StringIO):
+    '''file-like object that buffers its output and only writes it to disk
+    if the new contents are different from what the file may already contain.
+    '''
+    def __init__(self, filename):
+        self.filename = filename
+        StringIO.__init__(self)
+
+    def close(self):
+        buf = self.getvalue()
+        StringIO.close(self)
+        try:
+            file = open(self.filename, 'rU')
+        except IOError:
+            pass
+        else:
+            try:
+                 if file.read() == buf:
+                     log("%s is unchanged" % relpath(self.filename, os.curdir))
+                     return
+            except IOError:
+                pass
+            finally:
+                file.close()
+
+        log("creating %s" % relpath(self.filename, os.curdir))
+        ensureParentDir(self.filename)
+        with open(self.filename, 'w') as file:
+            file.write(buf)
+
+    def __enter__(self):
+        return self
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+def shell_escape(s):
+    '''Escape some characters with a backslash, and double dollar signs.
+    '''
+    return re.sub('''([ \t`#$^&*(){}\\|;'"<>?\[\]])''', r'\\\1', str(s)).replace('$', '$$')
+
+class ConfigEnvironment(object):
+    '''A ConfigEnvironment is defined by a source directory and a build
+    directory. It preprocesses files from the source directory and stores
+    the result in the object directory.
+
+     There are two types of files: config files and config headers,
+     each treated through a different member function.
+
+     Creating a ConfigEnvironment requires a few arguments:
+       - topsrcdir and topobjdir are, respectively, the top source and
+         the top object directory.
+       - defines is a list of (name, value) tuples. In autoconf, these are
+         set with AC_DEFINE and AC_DEFINE_UNQUOTED
+       - non_global_defines are a list of names appearing in defines above
+         that are not meant to be exported in ACDEFINES and ALLDEFINES (see
+         below)
+       - substs is a list of (name, value) tuples. In autoconf, these are
+         set with AC_SUBST.
+
+     ConfigEnvironment automatically defines two additional substs variables
+     from all the defines not appearing in non_global_defines:
+       - ACDEFINES contains the defines in the form -DNAME=VALUE, for use on
+         preprocessor command lines. The order in which defines were given
+         when creating the ConfigEnvironment is preserved.
+       - ALLDEFINES contains the defines in the form #define NAME VALUE, in
+         sorted order, for use in config files, for an automatic listing of
+         defines.
+
+    ConfigEnvironment expects a "top_srcdir" subst to be set with the top
+    source directory, in msys format on windows. It is used to derive a
+    "srcdir" subst when treating config files.
+    '''
+
+    def __init__(self, topobjdir = '.', topsrcdir = '.',
+                 defines = [], non_global_defines = [], substs = []):
+        self.defines = dict(defines)
+        self.substs = dict(substs)
+        self.topsrcdir = topsrcdir
+        self.topobjdir = topobjdir
+        global_defines = [name for name, value in defines if not name in non_global_defines]
+        self.substs['ACDEFINES'] = ' '.join(["-D%s=%s" % (name, shell_escape(self.defines[name])) for name in global_defines])
+        self.substs['ALLDEFINES'] = '\n'.join(sorted(["#define %s %s" % (name, self.defines[name]) for name in global_defines]))
+
+    def get_relative_srcdir(self, file):
+        '''Returns the relative source directory for the given file, always
+        using / as a path separator.
+        '''
+        assert(isinstance(file, basestring))
+        dir = posixpath.dirname(relpath(file, self.topobjdir).replace(os.sep, '/'))
+        if dir:
+            return dir
+        return '.'
+
+    def get_file_srcdir(self, file):
+        '''Returns the srcdir for the given file, where srcdir is in msys
+        format on windows, thus derived from top_srcdir.
+        '''
+        dir = self.get_relative_srcdir(file)
+        return posixpath.normpath(posixpath.join(self.substs['top_srcdir'], dir))
+
+    def get_depth(self, file):
+        '''Returns the DEPTH for the given file, that is, the path to the
+        object directory relative to the directory containing the given file.
+        Always uses / as a path separator.
+        '''
+        return relpath(self.topobjdir, os.path.dirname(file)).replace(os.sep, '/')
+
+    def get_input(self, file):
+        '''Returns the input file path in the source tree that can be used
+        to create the given config file or header.
+        '''
+        assert(isinstance(file, basestring))
+        return os.path.normpath(os.path.join(self.topsrcdir, "%s.in" % relpath(file, self.topobjdir)))
+
+    def create_config_file(self, path):
+        '''Creates the given config file. A config file is generated by
+        taking the corresponding source file and replacing occurences of
+        "@VAR@" by the value corresponding to "VAR" in the substs dict.
+
+        Additional substs are defined according to the file being treated:
+            "srcdir" for its the path to its source directory
+            "relativesrcdir" for its source directory relative to the top
+            "DEPTH" for the path to the top object directory
+        '''
+        input = self.get_input(path)
+        pp = Preprocessor()
+        pp.context.update(self.substs)
+        pp.context.update(srcdir = self.get_file_srcdir(path))
+        pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
+        pp.context.update(DEPTH = self.get_depth(path))
+        pp.do_filter('attemptSubstitution')
+        pp.setMarker(None)
+        with FileAvoidWrite(path) as pp.out:
+            pp.do_include(input)
+
+    def create_config_header(self, path):
+        '''Creates the given config header. A config header is generated by
+        taking the corresponding source file and replacing some #define/#undef
+        occurences:
+            "#undef NAME" is turned into "#define NAME VALUE"
+            "#define NAME" is unchanged
+            "#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
+            "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
+            Whitespaces are preserved.
+        '''
+        with open(self.get_input(path), 'rU') as input:
+            ensureParentDir(path)
+            output = FileAvoidWrite(path)
+            r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
+            for l in input:
+                m = r.match(l)
+                if m:
+                    cmd = m.group('cmd')
+                    name = m.group('name')
+                    value = m.group('value')
+                    if name:
+                        if name in self.defines:
+                            if cmd == 'define' and value:
+                                l = l[:m.start('value')] + str(self.defines[name]) + l[m.end('value'):]
+                            elif cmd == 'undef':
+                                l = l[:m.start('cmd')] + 'define' + l[m.end('cmd'):m.end('name')] + ' ' + str(self.defines[name]) + l[m.end('name'):]
+                        elif cmd == 'undef':
+                           l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
+
+                output.write(l)
+            output.close()
+
+def config_status(topobjdir = '.', topsrcdir = '.',
+                  defines = [], non_global_defines = [], substs = [],
+                  files = [], headers = []):
+    '''Main function, providing config.status functionality.
+
+    Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
+    variables, but like config.status from autoconf 2.6, single files may be
+    generated with the --file and --header options. Several such options can
+    be given to generate several files at the same time.
+
+    Without the -n option, this program acts as config.status and considers
+    the current directory as the top object directory, even when config.status
+    is in a different directory. It will, however, treat the directory
+    containing config.status as the top object directory with the -n option,
+    while files given to the --file and --header arguments are considered
+    relative to the current directory.
+
+    The --recheck option, like with the original config.status, runs configure
+    again, with the options given in the "ac_configure_args" subst.
+
+    The options to this function are passed when creating the
+    ConfigEnvironment, except for files and headers, which contain the list
+    of files and headers to be generated by default. These lists, as well as
+    the actual wrapper script around this function, are meant to be generated
+    by configure. See build/autoconf/config.status.m4.
+
+    Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS,
+    but like config.status behaviour with --file and --header, providing
+    files or headers on the command line inhibits the default generation of
+    files when given headers and headers when given files.
+
+    Unlike config.status, the FILE:TEMPLATE syntax is not supported for
+    files and headers. The template is always the filename suffixed with
+    '.in', in the corresponding directory under the top source directory.
+    '''
+
+    if 'CONFIG_FILES' in os.environ:
+        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+    if 'CONFIG_HEADERS' in os.environ:
+        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+
+    parser = OptionParser()
+    parser.add_option('--recheck', dest='recheck', action='store_true',
+                      help='update config.status by reconfiguring in the same conditions')
+    parser.add_option('--file', dest='files', metavar='FILE', action='append',
+                      help='instantiate the configuration file FILE')
+    parser.add_option('--header', dest='headers', metavar='FILE', action='append',
+                      help='instantiate the configuration header FILE')
+    parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+                      help='display verbose output')
+    parser.add_option('-n', dest='not_topobjdir', action='store_true',
+                      help='do not consider current directory as top object directory')
+    (options, args) = parser.parse_args()
+
+    # Without -n, the current directory is meant to be the top object directory
+    if not options.not_topobjdir:
+        topobjdir = '.'
+
+    env = ConfigEnvironment(topobjdir = topobjdir, topsrcdir = topsrcdir,
+                            defines = defines, non_global_defines = non_global_defines,
+                            substs = substs)
+
+    if options.recheck:
+        # Execute configure from the top object directory
+        if not os.path.isabs(topsrcdir):
+            topsrcdir = relpath(topsrcdir, topobjdir)
+        os.chdir(topobjdir)
+        os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion']))
+
+    if options.files:
+        files = options.files
+        headers = []
+    if options.headers:
+        headers = options.headers
+        if not options.files:
+            files = []
+    # Default to display messages when giving --file or --headers on the
+    # command line.
+    if options.files or options.headers or options.verbose:
+        global verbose
+        verbose = True
+    if not options.files and not options.headers:
+        print >>sys.stderr, "creating config files and headers..."
+        files = [os.path.join(topobjdir, f) for f in files]
+        headers = [os.path.join(topobjdir, f) for f in headers]
+
+    for file in files:
+        env.create_config_file(file)
+    for header in headers:
+        env.create_config_header(header)
new file mode 100644
--- /dev/null
+++ b/js/src/build/autoconf/config.status.m4
@@ -0,0 +1,167 @@
+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 For use in AC_SUBST replacement
+define([MOZ_DIVERSION_SUBST], 11)
+
+dnl Replace AC_SUBST to store values in a format suitable for python.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_SUBST(),bar)
+define([AC_SUBST],
+[ifdef([AC_SUBST_$1], ,
+[define([AC_SUBST_$1], )dnl
+AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
+        (''' $1 ''', r''' [$]$1 ''')
+AC_DIVERT_POP()dnl
+])])
+
+dnl Wrap AC_DEFINE to store values in a format suitable for python.
+dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h,
+dnl which is #included during some compile checks.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_DEFINE(),bar)
+define([_MOZ_AC_DEFINE], defn([AC_DEFINE]))
+define([AC_DEFINE],
+[cat >> confdefs.pytmp <<\EOF
+        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE([$1], [$2]), $#, 3, _MOZ_AC_DEFINE([$1], [$2], [$3]),_MOZ_AC_DEFINE([$1]))dnl
+])
+
+dnl Wrap AC_DEFINE_UNQUOTED to store values in a format suitable for
+dnl python.
+define([_MOZ_AC_DEFINE_UNQUOTED], defn([AC_DEFINE_UNQUOTED]))
+define([AC_DEFINE_UNQUOTED],
+[cat >> confdefs.pytmp <<EOF
+        (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
+])
+
+dnl Replace AC_OUTPUT to create and call a python config.status
+define([AC_OUTPUT],
+[dnl Top source directory in Windows format (as opposed to msys format).
+WIN_TOP_SRC=
+case "$host_os" in
+mingw*)
+    WIN_TOP_SRC=`cd $srcdir; pwd -W`
+    ;;
+esac
+AC_SUBST(WIN_TOP_SRC)
+
+dnl Used in all Makefile.in files
+top_srcdir=$srcdir
+AC_SUBST(top_srcdir)
+
+dnl Picked from autoconf 2.13
+trap '' 1 2 15
+AC_CACHE_SAVE
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+: ${CONFIG_STATUS=./config.status}
+
+dnl We're going to need [ ] for python syntax.
+changequote(<<<, >>>)dnl
+echo creating $CONFIG_STATUS
+
+cat > $CONFIG_STATUS <<EOF
+#!${PYTHON}
+
+import os, sys
+dnl topsrcdir is the top source directory in native form, as opposed to a
+dnl form suitable for make.
+topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
+if not os.path.isabs(topsrcdir):
+    topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
+dnl Don't rely on virtualenv here. Standalone js doesn't use it.
+sys.path.append(os.path.join(topsrcdir, 'build'))
+from ConfigStatus import config_status
+
+args = {
+    'topsrcdir': topsrcdir,
+    'topobjdir': os.path.dirname(<<<__file__>>>),
+
+dnl All defines and substs are stored with an additional space at the beginning
+dnl and at the end of the string, to avoid any problem with values starting or
+dnl ending with quotes.
+    'defines': [(name[1:-1], value[1:-1]) for name, value in [
+EOF
+
+dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but
+dnl lacks the final comma (see above).
+sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS
+rm confdefs.pytmp confdefs.h
+
+cat >> $CONFIG_STATUS <<\EOF
+    ] ],
+
+    'substs': [(name[1:-1], value[1:-1]) for name, value in [
+EOF
+
+dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
+dnl expected format, but lacks the final comma (see above).
+sed 's/$/,/' >> $CONFIG_STATUS <<EOF
+undivert(MOZ_DIVERSION_SUBST)dnl
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+    ] ],
+
+dnl List of files to apply AC_SUBSTs to. This is the list of files given
+dnl as an argument to AC_OUTPUT ($1)
+    'files': [
+EOF
+
+for out in $1; do
+  echo "        '$out'," >> $CONFIG_STATUS
+done
+
+cat >> $CONFIG_STATUS <<\EOF
+    ],
+
+dnl List of header files to apply AC_DEFINEs to. This is stored in the
+dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER.
+    'headers': [
+EOF
+
+ifdef(<<<AC_LIST_HEADER>>>, <<<
+HEADERS="AC_LIST_HEADER"
+for header in $HEADERS; do
+  echo "        '$header'," >> $CONFIG_STATUS
+done
+>>>)dnl
+
+cat >> $CONFIG_STATUS <<\EOF
+    ],
+
+dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
+    'non_global_defines': [
+EOF
+
+if test -n "$_NON_GLOBAL_ACDEFINES"; then
+  for var in $_NON_GLOBAL_ACDEFINES; do
+    echo "        '$var'," >> $CONFIG_STATUS
+  done
+fi
+
+cat >> $CONFIG_STATUS <<\EOF
+    ]
+}
+
+dnl Do the actual work
+config_status(**args)
+EOF
+changequote([, ])
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+dnl Execute config.status, unless --no-create was passed to configure.
+test "$no_create" = yes || ${PYTHON} $CONFIG_STATUS || exit 1
+])
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1148,37 +1148,36 @@ endif
 
 GARBAGE_DIRS += $(_JAVA_DIR)
 
 ###############################################################################
 # Update Makefiles
 ###############################################################################
 
 ifndef NO_MAKEFILE_RULE
-# Note: Passing depth to make-makefile is optional.
-#       It saves the script some work, though.
 Makefile: Makefile.in
-	@$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH)
+	@$(DEPTH)/config.status -n --file=Makefile
 endif
 
 ifndef NO_SUBMAKEFILES_RULE
 ifdef SUBMAKEFILES
 # VPATH does not work on some machines in this case, so add $(srcdir)
 $(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(if $(subsrcdir),cd $(subsrcdir) && )$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir)$(addprefix /,$(subsrcdir)) -d $(DEPTH) $(@:$(subsrcdir)/%=%)
+	$(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file=$@
 endif
 endif
 
 ifdef AUTOUPDATE_CONFIGURE
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
+	(cd $(topsrcdir) && $(AUTOCONF)) && $(DEPTH)/config.status -n --recheck)
 endif
 
 $(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	cd $(DEPTH) && CONFIG_HEADERS= CONFIG_FILES=config/autoconf.mk ./config.status
+	$(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
+	$(TOUCH) $@
 
 ###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ################################################################################
 # Copy each element of EXPORTS to $(DIST)/include
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -869,17 +869,16 @@ DLL_PREFIX=lib
 LIB_PREFIX=lib
 DLL_SUFFIX=.so
 OBJ_SUFFIX=o
 LIB_SUFFIX=a
 ASM_SUFFIX=s
 IMPORT_LIB_SUFFIX=
 TARGET_MD_ARCH=unix
 DIRENT_INO=d_ino
-WIN_TOP_SRC=
 MOZ_USER_DIR=".mozilla"
 
 MOZ_JS_LIBS='-L$(libdir) -lmozjs'
 MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib'
 
 MOZ_COMPONENT_NSPR_LIBS='-L$(LIBXUL_DIST)/bin $(NSPR_LIBS)'
 
 USE_DEPENDENT_LIBS=1
@@ -4475,96 +4474,25 @@ fi
 
 dnl ========================================================
 dnl JavaScript shell
 dnl ========================================================
 
 AC_HAVE_FUNCS(setlocale)
 AC_HAVE_FUNCS(localeconv)
 
-case "$host_os" in
-mingw*)
-    WIN_TOP_SRC=`cd $srcdir; pwd -W`
-    ;;
-esac
-
-AC_SUBST(WIN_TOP_SRC)
-
 AC_SUBST(MOZILLA_VERSION)
 
 AC_SUBST(ac_configure_args)
 
 dnl Spit out some output
 dnl ========================================================
 
-# Save the defines header file before autoconf removes it.
-# (Do not add AC_DEFINE calls after this line.)
-  _CONFIG_TMP=confdefs-tmp.h
-  _CONFIG_DEFS_H=js-confdefs.h
-
-  cat > $_CONFIG_TMP <<\EOF
-/* List of defines generated by configure. Included with preprocessor flag,
- * -include, to avoid long list of -D defines on the compile command-line.
- * Do not edit.
- */
-
-#ifndef _JS_CONFDEFS_H_
-#define _JS_CONFDEFS_H_
-EOF
-
-_EGREP_PATTERN='^#define ('
-if test -n "$_NON_GLOBAL_ACDEFINES"; then
-    for f in $_NON_GLOBAL_ACDEFINES; do
-        _EGREP_PATTERN="${_EGREP_PATTERN}$f|"
-    done
-fi
-_EGREP_PATTERN="${_EGREP_PATTERN}dummy_never_defined)"
-
-  sort confdefs.h | egrep -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
-
-  if test "$?" != 0; then
-    AC_MSG_ERROR([Error outputting config definitions])
-  fi
-
-  cat >> $_CONFIG_TMP <<\EOF
-
-/* The c99 defining the limit macros (UINT32_MAX for example), says:
- * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
- * is defined before <stdint.h> is included. */
-#define __STDC_LIMIT_MACROS
-
-#endif /* _JS_CONFDEFS_H_ */
-
-EOF
-
-  # Only write js-confdefs.h when something changes (or it doesn't exist)
-  if cmp -s $_CONFIG_TMP $_CONFIG_DEFS_H; then
-    rm $_CONFIG_TMP
-  else
-    AC_MSG_RESULT("creating $_CONFIG_DEFS_H")
-    mv -f $_CONFIG_TMP $_CONFIG_DEFS_H
-
-    echo ==== $_CONFIG_DEFS_H =================================
-    cat $_CONFIG_DEFS_H
-  fi
-
-dnl Probably shouldn't call this manually but we always want the output of DEFS
-rm -f confdefs.h.save
-mv confdefs.h confdefs.h.save
-egrep -v "$_EGREP_PATTERN" confdefs.h.save > confdefs.h
-if test "$?" != 0; then
-  AC_MSG_ERROR([Error outputting confdefs.h])
-fi
-AC_OUTPUT_MAKE_DEFS()
-ACDEFINES=$DEFS
-AC_SUBST(ACDEFINES)
-rm -f confdefs.h
-mv confdefs.h.save confdefs.h
-
 MAKEFILES="
+  js-confdefs.h
   Makefile
   shell/Makefile
   config/Makefile
   config/autoconf.mk
   config/expandlibs_config.py
 "
 
 if test "$JS_NATIVE_EDITLINE"; then
@@ -4581,47 +4509,20 @@ fi
 
 if test "$ENABLE_TESTS"; then
   MAKEFILES="$MAKEFILES
     jsapi-tests/Makefile
     tests/Makefile
   "
 fi
 
-dnl
-dnl Run a perl script to quickly create the makefiles.
-dnl If it succeeds, it outputs a shell command to set CONFIG_FILES
-dnl   for the files it cannot handle correctly. This way, config.status
-dnl   will handle these files.
-dnl If it fails, nothing is set and config.status will run as usual.
-dnl
-dnl This does not change the $MAKEFILES variable.
-dnl
-echo $MAKEFILES | ${PERL} $srcdir/build/autoconf/acoutput-fast.pl > conftest.sh
-res="$?"
-if test "$res" != 0; then
-    exit $res
-fi
-. ./conftest.sh
-rm conftest.sh
-
 echo $MAKEFILES > unallmakefiles
 
-mv -f config/autoconf.mk config/autoconf.mk.orig 2> /dev/null
-
 AC_OUTPUT($MAKEFILES)
 
-dnl Prevent the regeneration of autoconf.mk forcing rebuilds of the world
-if cmp -s config/autoconf.mk config/autoconf.mk.orig; then
-  echo "config/autoconf.mk is unchanged"
-  mv -f config/autoconf.mk.orig config/autoconf.mk 2> /dev/null
-else
-  rm -f config/autoconf.mk.orig 2> /dev/null
-fi
-
 # Produce the js-config script at configure time; see the comments for
 # 'js-config' in Makefile.in.
 AC_MSG_RESULT(invoking $MAKE to create js-config script)
 $MAKE js-config
 
 # Build jsctypes if it's enabled.
 if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
   # Run the libffi 'configure' script.
new file mode 100644
--- /dev/null
+++ b/js/src/js-confdefs.h.in
@@ -0,0 +1,17 @@
+/* List of defines generated by configure. Included with preprocessor flag,
+ * -include, to avoid long list of -D defines on the compile command-line.
+ * Do not edit.
+ */
+
+#ifndef _JS_CONFDEFS_H_
+#define _JS_CONFDEFS_H_
+
+@ALLDEFINES@
+
+/* The c99 defining the limit macros (UINT32_MAX for example), says:
+ * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
+ * is defined before <stdint.h> is included. */
+#define __STDC_LIMIT_MACROS
+
+#endif /* _JS_CONFDEFS_H_ */
+
new file mode 100644
--- /dev/null
+++ b/mozilla-config.h.in
@@ -0,0 +1,27 @@
+/* List of defines generated by configure. Included with preprocessor flag,
+ * -include, to avoid long list of -D defines on the compile command-line.
+ * Do not edit.
+ */
+
+#ifndef _MOZILLA_CONFIG_H_
+#define _MOZILLA_CONFIG_H_
+
+@ALLDEFINES@
+
+/* The c99 defining the limit macros (UINT32_MAX for example), says:
+ * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
+ * is defined before <stdint.h> is included. */
+#define __STDC_LIMIT_MACROS
+
+/* Force-include hunspell_alloc_hooks.h for hunspell, so that we don't need to
+ * modify it directly.
+ *
+ * HUNSPELL_STATIC is defined in extensions/spellcheck/hunspell/src/Makefile.in,
+ * unless --enable-system-hunspell is defined.
+ */
+#if defined(HUNSPELL_STATIC)
+#include "hunspell_alloc_hooks.h"
+#endif
+
+#endif /* _MOZILLA_CONFIG_H_ */
+