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 101386 21c3069ddc4a9d294de06151a7d3486577b1429a
parent 101385 b4218536a9e6b18f0d8de9c8e16abad414fce76a
child 101387 75ac79f11192db4d40b2cb71144a6d49ecbc34c1
push id12983
push usermh@glandium.org
push dateSat, 04 Aug 2012 06:50:57 +0000
treeherdermozilla-inbound@2ef51674316a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs774032
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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_ */
+