Bug 927837 - Don't manage generated files in configure; r=glandium
authorGregory Szorc <gps@mozilla.com>
Wed, 23 Oct 2013 14:43:32 -0700
changeset 167130 58ca27d61309b208feddb36052a7676ba2413df3
parent 167129 9ce0a96f14da416534e2a615a72d81135789d1ef
child 167131 98cb3022ae1094deec33a0f3c68a5e331c5aef4a
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs927837
milestone27.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 927837 - Don't manage generated files in configure; r=glandium
build/ConfigStatus.py
build/autoconf/config.status.m4
config/makefiles/xpidl/Makefile.in
config/rules.mk
configure.in
js/src/build/ConfigStatus.py
js/src/build/autoconf/config.status.m4
js/src/config/moz.build
js/src/config/rules.mk
js/src/configure.in
js/src/moz.build
media/mtransport/third_party/Makefile.in
media/webrtc/Makefile.in
media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
moz.build
netwerk/moz.build
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
xpcom/moz.build
--- a/build/ConfigStatus.py
+++ b/build/ConfigStatus.py
@@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo
 from mozbuild.frontend.emitter import TreeMetadataEmitter
 from mozbuild.frontend.reader import BuildReader
 from mozbuild.mozinfo import write_mozinfo
 
 
 log_manager = LoggingManager()
 
 
-def config_status(topobjdir = '.', topsrcdir = '.',
-                  defines = [], non_global_defines = [], substs = [],
-                  files = [], headers = []):
+def config_status(topobjdir='.', topsrcdir='.',
+        defines=[], non_global_defines=[], substs=[]):
     '''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.
+    variables.
 
     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.
+    containing config.status as the top object directory with the -n option.
 
     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.
+    ConfigEnvironment. 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.
     '''
 
     if 'CONFIG_FILES' in os.environ:
-        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+        raise Exception('Using the CONFIG_FILES environment variable is not '
+            'supported.')
     if 'CONFIG_HEADERS' in os.environ:
-        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+        raise Exception('Using the CONFIG_HEADERS environment variable is not '
+            'supported.')
+
+    if not os.path.isabs(topsrcdir):
+        raise Exception('topsrcdir must be defined as an absolute directory: '
+            '%s' % topsrcdir)
 
     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:
@@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
     definitions = emitter.emit(reader.read_topsrcdir())
 
     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.
-    log_level = logging.INFO
-
-    if options.files or options.headers or options.verbose:
-        log_level = logging.DEBUG
-
+    log_level = logging.DEBUG if options.verbose else logging.INFO
     log_manager.add_terminal_logging(level=log_level)
     log_manager.enable_unstructured()
 
-    if not options.files and not options.headers:
-        print('Reticulating splines...', file=sys.stderr)
-        summary = backend.consume(definitions)
-
-        for line in summary.summaries():
-            print(line, file=sys.stderr)
+    print('Reticulating splines...', file=sys.stderr)
+    summary = backend.consume(definitions)
 
-        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)
+    for line in summary.summaries():
+        print(line, file=sys.stderr)
--- a/build/autoconf/config.status.m4
+++ b/build/autoconf/config.status.m4
@@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([
 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],
+define([_MOZ_AC_OUTPUT],
 [dnl Top source directory in Windows format (as opposed to msys format).
 WIN_TOP_SRC=
 encoding=utf-8
 case "$host_os" in
 mingw*)
     WIN_TOP_SRC=`cd $srcdir; pwd -W`
     encoding=mbcs
     ;;
@@ -116,57 +116,30 @@ dnl Add in the output from the subconfig
 for ac_subst_arg in $_subconfigure_ac_subst_args; do
   variable='$'$ac_subst_arg
   echo "    (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS
 done
 
 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
 ]
 
-__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers']
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
 
 dnl Do the actual work
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     import sys
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
     sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
     from ConfigStatus import config_status
@@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS
 rm -fr confdefs* $ac_clean_files
 dnl Execute config.status, unless --no-create was passed to configure.
 if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
     trap '' EXIT
     exit 1
 fi
 ])
 
+define([m4_fatal],[
+errprint([$1
+])
+m4exit(1)
+])
+
+define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()],
+[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])]
+)])
+
+define([AC_CONFIG_HEADER],
+[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
+])
+
 AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -1,15 +1,14 @@
 # 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/.
 
 SUPPRESS_DEFAULT_RULES := 1
 STANDALONE_MAKEFILE := 1
-NO_MAKEFILE_RULE := 1
 
 include $(topsrcdir)/config/rules.mk
 
 # Building XPIDLs effectively consists of two steps:
 #
 #   1) Staging all .idl files to a common directory.
 #   2) Doing everything with the .idl files.
 #
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -612,21 +612,16 @@ Makefile: $(DEPTH)/backend.RecursiveMake
 
 include $(DEPTH)/backend.RecursiveMakeBackend.built.pp
 
 default:: $(DEPTH)/backend.RecursiveMakeBackend.built
 
 export MOZBUILD_BACKEND_CHECKED=1
 endif
 
-
-# SUBMAKEFILES: List of Makefiles for next level down.
-#   This is used to update or create the Makefiles before invoking them.
-SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
-
 # The root makefile doesn't want to do a plain export/libs, because
 # of the tiers and because of libxul. Suppress the default rules in favor
 # of something else. Makefiles which use this var *must* provide a sensible
 # default rule before including rules.mk
 ifndef SUPPRESS_DEFAULT_RULES
 default all::
 	$(MAKE) export
 ifdef MOZ_PSEUDO_DERECURSE
@@ -644,35 +639,24 @@ ECHO := true
 QUIET := -q
 endif
 
 # Do everything from scratch
 everything::
 	$(MAKE) clean
 	$(MAKE) all
 
-# Target to only regenerate makefiles
-makefiles: $(SUBMAKEFILES)
-ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
-	$(LOOP_OVER_PARALLEL_DIRS)
-	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
-endif
-
 ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
 $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
 endif
 
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
 
 # Dependencies which, if modified, should cause everything to rebuild
 GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
-ifndef NO_MAKEFILE_RULE
-GLOBAL_DEPS += Makefile.in
-endif
 
 ##############################################
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: $(OBJ_TARGETS)
 
 include $(topsrcdir)/config/makefiles/target_libs.mk
 
@@ -737,30 +721,30 @@ endif
 
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
 checkout:
 	$(MAKE) -C $(topsrcdir) -f client.mk checkout
 
-clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+clean clobber realclean clobber_all::
 	-$(RM) $(ALL_TRASH)
 	-$(RM) -r $(ALL_TRASH_DIRS)
 
 ifdef TIERS
 clean clobber realclean clobber_all distclean::
 	$(foreach dir, \
 		$(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \
 		-$(call SUBMAKE,$@,$(dir)))
 else
 clean clobber realclean clobber_all distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 
-distclean:: $(SUBMAKEFILES)
+distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 endif
 
 distclean::
 	-$(RM) -r $(ALL_TRASH_DIRS)
 	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
@@ -1158,44 +1142,16 @@ endif
 ###############################################################################
 # Java rules
 ###############################################################################
 ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
   include $(topsrcdir)/config/makefiles/java-build.mk
 endif
 
 ###############################################################################
-# Update Files Managed by Build Backend
-###############################################################################
-
-ifndef NO_MAKEFILE_RULE
-Makefile: Makefile.in
-	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
-	@$(TOUCH) $@
-endif
-
-ifndef NO_SUBMAKEFILES_RULE
-ifdef SUBMAKEFILES
-# VPATH does not work on some machines in this case, so add $(srcdir)
-$(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
-	@$(TOUCH) "$@"
-endif
-endif
-
-ifdef AUTOUPDATE_CONFIGURE
-$(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
-endif
-
-$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	$(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
-	$(TOUCH) $@
-
-###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
@@ -1620,34 +1576,34 @@ endif
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
 
-TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
   ## Only parse when an echo* or show* target is requested
   ifneq (,$(call isTargetStem,echo,show))
     include $(topsrcdir)/config/makefiles/debugmake.mk
   endif #}
 endif #}
 
 documentation:
 	@cd $(DEPTH)
 	$(DOXYGEN) $(DEPTH)/config/doxygen.cfg
 
 ifdef ENABLE_TESTS
-check:: $(SUBMAKEFILES)
+check::
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 endif
 
 
 FREEZE_VARIABLES = \
   CSRCS \
--- a/configure.in
+++ b/configure.in
@@ -8767,27 +8767,20 @@ HAVE_STATVFS
 HAVE_STATFS64
 HAVE_STATFS
 HAVE_SYS_STATVFS_H
 HAVE_SYS_STATFS_H
 HAVE_SYS_VFS_H
 HAVE_SYS_MOUNT_H
 "
 
-# FUTURE? Consider moving all these to moz.build files.
-AC_CONFIG_HEADER(
-netwerk/necko-config.h
-xpcom/xpcom-config.h
-xpcom/xpcom-private.h
-)
-
 AC_SUBST(STLPORT_LIBS)
 
 export WRITE_MOZINFO=1
-AC_OUTPUT([mozilla-config.h])
+AC_OUTPUT()
 unset WRITE_MOZINFO
 
 # Hack around an Apple bug that affects the egrep that comes with OS X 10.7.
 # "env ARCHPREFERENCE=i386,x86_64 arch egrep" first tries to use the 32-bit
 # Intel part of the egrep fat binary, even on 64-bit systems, and falls back on
 # the 64-bit part if it's not a fat binary, as can happen with MacPorts. We
 # (apparently) only need this hack when egrep's "pattern" is particularly long
 # (as in the following code) and the first egrep on our $PATH is Apple's.  See
--- a/js/src/build/ConfigStatus.py
+++ b/js/src/build/ConfigStatus.py
@@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo
 from mozbuild.frontend.emitter import TreeMetadataEmitter
 from mozbuild.frontend.reader import BuildReader
 from mozbuild.mozinfo import write_mozinfo
 
 
 log_manager = LoggingManager()
 
 
-def config_status(topobjdir = '.', topsrcdir = '.',
-                  defines = [], non_global_defines = [], substs = [],
-                  files = [], headers = []):
+def config_status(topobjdir='.', topsrcdir='.',
+        defines=[], non_global_defines=[], substs=[]):
     '''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.
+    variables.
 
     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.
+    containing config.status as the top object directory with the -n option.
 
     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.
+    ConfigEnvironment. 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.
     '''
 
     if 'CONFIG_FILES' in os.environ:
-        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+        raise Exception('Using the CONFIG_FILES environment variable is not '
+            'supported.')
     if 'CONFIG_HEADERS' in os.environ:
-        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+        raise Exception('Using the CONFIG_HEADERS environment variable is not '
+            'supported.')
+
+    if not os.path.isabs(topsrcdir):
+        raise Exception('topsrcdir must be defined as an absolute directory: '
+            '%s' % topsrcdir)
 
     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:
@@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
     definitions = emitter.emit(reader.read_topsrcdir())
 
     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.
-    log_level = logging.INFO
-
-    if options.files or options.headers or options.verbose:
-        log_level = logging.DEBUG
-
+    log_level = logging.DEBUG if options.verbose else logging.INFO
     log_manager.add_terminal_logging(level=log_level)
     log_manager.enable_unstructured()
 
-    if not options.files and not options.headers:
-        print('Reticulating splines...', file=sys.stderr)
-        summary = backend.consume(definitions)
-
-        for line in summary.summaries():
-            print(line, file=sys.stderr)
+    print('Reticulating splines...', file=sys.stderr)
+    summary = backend.consume(definitions)
 
-        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)
+    for line in summary.summaries():
+        print(line, file=sys.stderr)
--- a/js/src/build/autoconf/config.status.m4
+++ b/js/src/build/autoconf/config.status.m4
@@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([
 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],
+define([_MOZ_AC_OUTPUT],
 [dnl Top source directory in Windows format (as opposed to msys format).
 WIN_TOP_SRC=
 encoding=utf-8
 case "$host_os" in
 mingw*)
     WIN_TOP_SRC=`cd $srcdir; pwd -W`
     encoding=mbcs
     ;;
@@ -116,57 +116,30 @@ dnl Add in the output from the subconfig
 for ac_subst_arg in $_subconfigure_ac_subst_args; do
   variable='$'$ac_subst_arg
   echo "    (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS
 done
 
 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
 ]
 
-__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers']
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
 
 dnl Do the actual work
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     import sys
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
     sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
     from ConfigStatus import config_status
@@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS
 rm -fr confdefs* $ac_clean_files
 dnl Execute config.status, unless --no-create was passed to configure.
 if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
     trap '' EXIT
     exit 1
 fi
 ])
 
+define([m4_fatal],[
+errprint([$1
+])
+m4exit(1)
+])
+
+define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()],
+[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])]
+)])
+
+define([AC_CONFIG_HEADER],
+[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
+])
+
 AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/js/src/config/moz.build
+++ b/js/src/config/moz.build
@@ -1,14 +1,19 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+CONFIGURE_SUBST_FILES += [
+    'autoconf.mk',
+    'emptyvars.mk',
+]
+
 NO_DIST_INSTALL = True
 # For sanity's sake, we compile nsinstall without the wrapped system
 # headers, so that we can use it to set up the wrapped system headers.
 NO_VISIBILITY_FLAGS = True
 
 if CONFIG['HOST_OS_ARCH'] != 'WINNT':
     HOST_SOURCES += [
         'nsinstall.c',
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -612,21 +612,16 @@ Makefile: $(DEPTH)/backend.RecursiveMake
 
 include $(DEPTH)/backend.RecursiveMakeBackend.built.pp
 
 default:: $(DEPTH)/backend.RecursiveMakeBackend.built
 
 export MOZBUILD_BACKEND_CHECKED=1
 endif
 
-
-# SUBMAKEFILES: List of Makefiles for next level down.
-#   This is used to update or create the Makefiles before invoking them.
-SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
-
 # The root makefile doesn't want to do a plain export/libs, because
 # of the tiers and because of libxul. Suppress the default rules in favor
 # of something else. Makefiles which use this var *must* provide a sensible
 # default rule before including rules.mk
 ifndef SUPPRESS_DEFAULT_RULES
 default all::
 	$(MAKE) export
 ifdef MOZ_PSEUDO_DERECURSE
@@ -644,35 +639,24 @@ ECHO := true
 QUIET := -q
 endif
 
 # Do everything from scratch
 everything::
 	$(MAKE) clean
 	$(MAKE) all
 
-# Target to only regenerate makefiles
-makefiles: $(SUBMAKEFILES)
-ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
-	$(LOOP_OVER_PARALLEL_DIRS)
-	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
-endif
-
 ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
 $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
 endif
 
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
 
 # Dependencies which, if modified, should cause everything to rebuild
 GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
-ifndef NO_MAKEFILE_RULE
-GLOBAL_DEPS += Makefile.in
-endif
 
 ##############################################
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: $(OBJ_TARGETS)
 
 include $(topsrcdir)/config/makefiles/target_libs.mk
 
@@ -737,30 +721,30 @@ endif
 
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
 checkout:
 	$(MAKE) -C $(topsrcdir) -f client.mk checkout
 
-clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+clean clobber realclean clobber_all::
 	-$(RM) $(ALL_TRASH)
 	-$(RM) -r $(ALL_TRASH_DIRS)
 
 ifdef TIERS
 clean clobber realclean clobber_all distclean::
 	$(foreach dir, \
 		$(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \
 		-$(call SUBMAKE,$@,$(dir)))
 else
 clean clobber realclean clobber_all distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 
-distclean:: $(SUBMAKEFILES)
+distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 endif
 
 distclean::
 	-$(RM) -r $(ALL_TRASH_DIRS)
 	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
@@ -1158,44 +1142,16 @@ endif
 ###############################################################################
 # Java rules
 ###############################################################################
 ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
   include $(topsrcdir)/config/makefiles/java-build.mk
 endif
 
 ###############################################################################
-# Update Files Managed by Build Backend
-###############################################################################
-
-ifndef NO_MAKEFILE_RULE
-Makefile: Makefile.in
-	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
-	@$(TOUCH) $@
-endif
-
-ifndef NO_SUBMAKEFILES_RULE
-ifdef SUBMAKEFILES
-# VPATH does not work on some machines in this case, so add $(srcdir)
-$(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
-	@$(TOUCH) "$@"
-endif
-endif
-
-ifdef AUTOUPDATE_CONFIGURE
-$(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
-endif
-
-$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	$(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
-	$(TOUCH) $@
-
-###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
@@ -1620,34 +1576,34 @@ endif
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
 
-TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
   ## Only parse when an echo* or show* target is requested
   ifneq (,$(call isTargetStem,echo,show))
     include $(topsrcdir)/config/makefiles/debugmake.mk
   endif #}
 endif #}
 
 documentation:
 	@cd $(DEPTH)
 	$(DOXYGEN) $(DEPTH)/config/doxygen.cfg
 
 ifdef ENABLE_TESTS
-check:: $(SUBMAKEFILES)
+check::
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 endif
 
 
 FREEZE_VARIABLES = \
   CSRCS \
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -5,17 +5,16 @@ dnl License, v. 2.0. If a copy of the MP
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 dnl Process this file with autoconf to produce a configure script.
 dnl ========================================================
 
 AC_PREREQ(2.13)
 AC_INIT(jsapi.h)
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
-AC_CONFIG_HEADER(js-config.h)
 AC_CANONICAL_SYSTEM
 TARGET_CPU="${target_cpu}"
 TARGET_VENDOR="${target_vendor}"
 TARGET_OS="${target_os}"
 
 dnl ========================================================
 dnl =
 dnl = Don't change the following two lines.  Doing so breaks:
@@ -4262,17 +4261,17 @@ AC_HAVE_FUNCS(localeconv)
 
 AC_SUBST(MOZILLA_VERSION)
 
 AC_SUBST(ac_configure_args)
 
 dnl Spit out some output
 dnl ========================================================
 
-AC_OUTPUT([js-confdefs.h config/autoconf.mk config/emptyvars.mk])
+AC_OUTPUT()
 
 # 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_NAME script)
 $MAKE $JS_CONFIG_NAME
 
 # Build jsctypes if it's enabled.
 if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -20,17 +20,24 @@ TEST_DIRS += ['jsapi-tests', 'tests', 'g
 
 MODULE = 'js'
 
 if CONFIG['JS_STANDALONE']:
     LIBRARY_NAME = 'mozjs-%s.%s%s' % (CONFIG['MOZJS_MAJOR_VERSION'], CONFIG['MOZJS_MINOR_VERSION'], CONFIG['MOZJS_ALPHA'])
 else:
     LIBRARY_NAME = 'mozjs'
 
-CONFIGURE_SUBST_FILES += ['devtools/rootAnalysis/Makefile']
+CONFIGURE_SUBST_FILES += [
+    'devtools/rootAnalysis/Makefile',
+    'js-confdefs.h',
+]
+
+CONFIGURE_DEFINE_FILES += [
+    'js-config.h',
+]
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 EXPORTS += [
     'js.msg',
     'jsalloc.h',
     'jsapi.h',
deleted file mode 100644
--- a/media/mtransport/third_party/Makefile.in
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-
-
-NO_SUBMAKEFILES_RULE = 1
deleted file mode 100644
--- a/media/webrtc/Makefile.in
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-
-# These Makefiles don't have corresponding Makefile.ins
-NO_SUBMAKEFILES_RULE = 1
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
+++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
@@ -34,19 +34,16 @@ topsrcdir	= %(topsrcdir)s
 srcdir          = %(srcdir)s
 VPATH           = %(srcdir)s
 
 EXTERNALLY_MANAGED_MAKE_FILE := 1
 
 """
 
 COMMON_FOOTER = """
-# Skip rules that deal with regenerating Makefiles from Makefile.in files.
-NO_MAKEFILE_RULE = 1
-NO_SUBMAKEFILES_RULE = 1
 
 include %(common_mk_path)s
 """
 
 COMMON_MK = """# This file was generated by mozmake.py. Do not edit it directly.
 ifndef COMMON_MK_INCLUDED
 COMMON_MK_INCLUDED := 1
 
--- a/moz.build
+++ b/moz.build
@@ -1,15 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-CONFIGURE_SUBST_FILES += ['tools/update-packaging/Makefile']
+CONFIGURE_SUBST_FILES += [
+    'mozilla-config.h',
+    'tools/update-packaging/Makefile',
+]
 
 if CONFIG['ENABLE_CLANG_PLUGIN']:
   add_tier_dir('base', 'build/clang-plugin', external=True)
 
 add_tier_dir('base', ['config', 'build', 'probes', 'mfbt', 'python'])
 
 if not CONFIG['LIBXUL_SDK']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
--- a/netwerk/moz.build
+++ b/netwerk/moz.build
@@ -31,8 +31,10 @@ PARALLEL_DIRS += ['locales']
 
 if CONFIG['MOZ_DASH']:
     PARALLEL_DIRS += ['dash']
 
 DIRS += ['build']
 TEST_TOOL_DIRS += ['test']
 
 MODULE = 'necko'
+
+CONFIGURE_DEFINE_FILES += ['necko-config.h']
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -24,16 +24,17 @@ from .common import CommonBackend
 from ..frontend.data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
     GeneratedInclude,
     GeneratedWebIDLFile,
+    HeaderFileSubstitution,
     InstallationTarget,
     IPDLFile,
     JavaJarData,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     SandboxDerived,
@@ -88,26 +89,16 @@ class BackendMakeFile(object):
         self.idls = []
         self.xpt_name = None
 
         self.fh = FileAvoidWrite(self.path)
         self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n')
         self.fh.write('\n')
         self.fh.write('MOZBUILD_DERIVED := 1\n')
 
-        # The global rule to incur backend generation generates Makefiles.
-        self.fh.write('NO_MAKEFILE_RULE := 1\n')
-
-        # We can't blindly have a SUBMAKEFILES rule because some of the
-        # Makefile may not have a corresponding Makefile.in. For the case
-        # where a new directory is added, the mozbuild file referencing that
-        # new directory will need updated. This will cause a full backend
-        # scan and build, installing the new Makefile.
-        self.fh.write('NO_SUBMAKEFILES_RULE := 1\n')
-
     def write(self, buf):
         self.fh.write(buf)
 
     def close(self):
         if self.xpt_name:
             self.fh.write('XPT_NAME := %s\n' % self.xpt_name)
 
             # We just recompile all xpidls because it's easier and less error
@@ -343,16 +334,21 @@ class RecursiveMakeBackend(CommonBackend
 
         if isinstance(obj, DirectoryTraversal):
             self._process_directory_traversal(obj, backend_file)
         elif isinstance(obj, ConfigFileSubstitution):
             self._update_from_avoid_write(
                 backend_file.environment.create_config_file(obj.output_path))
             self.backend_input_files.add(obj.input_path)
             self.summary.managed_count += 1
+        elif isinstance(obj, HeaderFileSubstitution):
+            self._update_from_avoid_write(
+                backend_file.environment.create_config_header(obj.output_path))
+            self.backend_input_files.add(obj.input_path)
+            self.summary.managed_count += 1
         elif isinstance(obj, XPIDLFile):
             backend_file.idls.append(obj)
             backend_file.xpt_name = '%s.xpt' % obj.module
         elif isinstance(obj, VariablePassthru):
             # Sorted so output is consistent and we don't bump mtimes.
             for k, v in sorted(obj.variables.items()):
                 if isinstance(v, list):
                     for item in v:
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -99,36 +99,41 @@ class DirectoryTraversal(SandboxDerived)
         self.test_dirs = []
         self.test_tool_dirs = []
         self.tier_dirs = OrderedDict()
         self.tier_static_dirs = OrderedDict()
         self.external_make_dirs = []
         self.parallel_external_make_dirs = []
 
 
-class ConfigFileSubstitution(SandboxDerived):
-    """Describes a config file that will be generated using substitutions.
+class BaseConfigSubstitution(SandboxDerived):
+    """Base class describing autogenerated files as part of config.status."""
 
-    The output_path attribute defines the relative path from topsrcdir of the
-    output file to generate.
-    """
     __slots__ = (
         'input_path',
         'output_path',
         'relpath',
     )
 
     def __init__(self, sandbox):
         SandboxDerived.__init__(self, sandbox)
 
         self.input_path = None
         self.output_path = None
         self.relpath = None
 
 
+class ConfigFileSubstitution(BaseConfigSubstitution):
+    """Describes a config file that will be generated using substitutions."""
+
+
+class HeaderFileSubstitution(BaseConfigSubstitution):
+    """Describes a header file that will be generated using substitutions."""
+
+
 class VariablePassthru(SandboxDerived):
     """A dict of variables to pass through to backend.mk unaltered.
 
     The purpose of this object is to facilitate rapid transitioning of
     variables from Makefile.in to moz.build. In the ideal world, this class
     does not exist and every variable has a richer class representing it.
     As long as we rely on this class, we lose the ability to have flexibility
     in our build backends since we will continue to be tied to our rules.mk.
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -20,16 +20,17 @@ from mozpack.files import FileFinder
 from .data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
     GeneratedInclude,
     GeneratedWebIDLFile,
+    HeaderFileSubstitution,
     InstallationTarget,
     IPDLFile,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     ReaderSummary,
     SandboxWrapped,
@@ -94,24 +95,22 @@ class TreeMetadataEmitter(LoggingMixin):
 
         This is a generator of mozbuild.frontend.data.SandboxDerived instances.
         """
         # We always emit a directory traversal descriptor. This is needed by
         # the recursive make backend.
         for o in self._emit_directory_traversal_from_sandbox(sandbox): yield o
 
         for path in sandbox['CONFIGURE_SUBST_FILES']:
-            if os.path.isabs(path):
-                path = path[1:]
+            yield self._create_substitution(ConfigFileSubstitution, sandbox,
+                path)
 
-            sub = ConfigFileSubstitution(sandbox)
-            sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path)
-            sub.output_path = os.path.join(sandbox['OBJDIR'], path)
-            sub.relpath = path
-            yield sub
+        for path in sandbox['CONFIGURE_DEFINE_FILES']:
+            yield self._create_substitution(HeaderFileSubstitution, sandbox,
+                path)
 
         # XPIDL source files get processed and turned into .h and .xpt files.
         # If there are multiple XPIDL files in a directory, they get linked
         # together into a final .xpt, which has the name defined by either
         # MODULE or XPIDL_MODULE (if the latter is defined).
         xpidl_module = sandbox['MODULE']
         if sandbox['XPIDL_MODULE']:
             xpidl_module = sandbox['XPIDL_MODULE']
@@ -261,16 +260,27 @@ class TreeMetadataEmitter(LoggingMixin):
         for prefix, info in test_manifests.items():
             for path in sandbox.get('%s_MANIFESTS' % prefix, []):
                 for obj in self._process_test_manifest(sandbox, info, path):
                     yield obj
 
         for name, jar in sandbox.get('JAVA_JAR_TARGETS', {}).items():
             yield SandboxWrapped(sandbox, jar)
 
+    def _create_substitution(self, cls, sandbox, path):
+        if os.path.isabs(path):
+            path = path[1:]
+
+        sub = cls(sandbox)
+        sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path)
+        sub.output_path = os.path.join(sandbox['OBJDIR'], path)
+        sub.relpath = path
+
+        return sub
+
     def _process_test_manifest(self, sandbox, info, manifest_path):
         flavor, install_prefix, filter_inactive = info
 
         manifest_path = os.path.normpath(manifest_path)
         path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path))
         manifest_dir = mozpath.dirname(path)
         manifest_reldir = mozpath.dirname(mozpath.relpath(path,
             sandbox['TOPSRCDIR']))
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -345,16 +345,24 @@ VARIABLES = {
 
         This is a substitute for ``AC_OUTPUT`` in autoconf. For each path in this
         list, we will search for a file in the srcdir having the name
         ``{path}.in``. The contents of this file will be read and variable
         patterns like ``@foo@`` will be substituted with the values of the
         ``AC_SUBST`` variables declared during configure.
         """, None),
 
+    'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list, [],
+        """Output files generated from configure/config.status.
+
+        This is a substitute for ``AC_CONFIG_HEADER`` in autoconf. This is very
+        similar to ``CONFIGURE_SUBST_FILES`` except the generation logic takes
+        into account the values of ``AC_DEFINE`` instead of ``AC_SUBST``.
+        """, None),
+
     'MODULE': (unicode, unicode, "",
         """Module name.
 
         Historically, this variable was used to describe where to install header
         files, but that feature is now handled by ``EXPORTS_NAMESPACES``.
         ``MODULE`` will likely be removed in the future.
         """, None),
 
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -206,18 +206,16 @@ class TestRecursiveMakeBackend(BackendTe
         """Ensure backend.mk file is written out properly."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = os.path.join(env.topobjdir, 'backend.mk')
 
         lines = [l.strip() for l in open(p, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
             'MOZBUILD_DERIVED := 1',
-            'NO_MAKEFILE_RULE := 1',
-            'NO_SUBMAKEFILES_RULE := 1',
             'DIRS := dir1',
             'PARALLEL_DIRS := dir2',
             'TEST_DIRS := dir3',
         ])
 
     def test_mtime_no_change(self):
         """Ensure mtime is not updated if file content does not change."""
 
@@ -239,18 +237,16 @@ class TestRecursiveMakeBackend(BackendTe
     def test_external_make_dirs(self):
         """Ensure we have make recursion into external make directories."""
         env = self._consume('external_make_dirs', RecursiveMakeBackend)
 
         backend_path = os.path.join(env.topobjdir, 'backend.mk')
         lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
             'MOZBUILD_DERIVED := 1',
-            'NO_MAKEFILE_RULE := 1',
-            'NO_SUBMAKEFILES_RULE := 1',
             'DIRS := dir',
             'PARALLEL_DIRS := p_dir',
             'DIRS += external',
             'PARALLEL_DIRS += p_external',
         ])
 
     def test_substitute_config_files(self):
         """Ensure substituted config files are produced."""
--- a/xpcom/moz.build
+++ b/xpcom/moz.build
@@ -38,8 +38,13 @@ TEST_TOOL_DIRS += [
 #    'reflect/xptinfo/tests',
 #    'reflect/xptcall/tests,
 #]
 
 if CONFIG['DEHYDRA_PATH']:
     DIRS += ['analysis']
 
 MODULE = 'xpcom'
+
+CONFIGURE_DEFINE_FILES += [
+    'xpcom-config.h',
+    'xpcom-private.h',
+]