Bug 874078 - Move RecursiveMakeBackend.built rule to rules.mk; r=glandium
authorGregory Szorc <gps@mozilla.com>
Mon, 20 May 2013 23:26:20 -0700
changeset 144847 0931f7400cf2af6e6ee742b6beb17f92069755f8
parent 144846 54553d06c80d790660566074ec02b57fdcb9d768
child 144848 668d1525ef292bf2e3208d0938ea9e134e0175ab
push id368
push userbbajaj@mozilla.com
push dateMon, 09 Sep 2013 22:57:58 +0000
treeherdermozilla-release@5a4f47ae1217 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs874078
milestone24.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 874078 - Move RecursiveMakeBackend.built rule to rules.mk; r=glandium
CLOBBER
Makefile.in
build/ConfigStatus.py
config/rules.mk
js/src/build/ConfigStatus.py
js/src/config/rules.mk
python/mozbuild/mozbuild/backend/base.py
python/mozbuild/mozbuild/backend/recursivemake.py
--- a/CLOBBER
+++ b/CLOBBER
@@ -12,12 +12,12 @@
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
-Landing bug 865806
+Refactored build system core dependencies in bug 874078.
 
 Alternative to clobber is to run ./config.status from the objdir and to
 touch the CLOBBER file in the objdir.
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,16 +33,18 @@ include $(topsrcdir)/config/config.mk
 GARBAGE_DIRS += dist _javagen _profile _tests staticlib
 DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
    config/autoconf.mk \
    unallmakefiles mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 ifndef MOZ_PROFILE_USE
+# We need to explicitly put backend.RecursiveMakeBackend.built here
+# otherwise the rule in rules.mk doesn't run early enough.
 default alldep all:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend.built
 	$(RM) -r $(DIST)/sdk
 	$(RM) -r $(DIST)/include
 	$(RM) -r $(DIST)/private
 	$(RM) -r $(DIST)/public
 	$(RM) -r $(DIST)/bin
 	$(RM) -r _tests
 endif
@@ -68,24 +70,16 @@ config.status: $(topsrcdir)/configure
 	@exit 1
 
 # Build pseudo-external modules first when export is explicitly called
 export::
 	$(RM) -r $(DIST)/sdk
 	$(MAKE) -C config export
 	$(MAKE) tier_nspr
 
-backend.RecursiveMakeBackend.built:
-	@echo "Updating build backend because of moz.build changes."
-	@$(PYTHON) ./config.status
-
-include backend.RecursiveMakeBackend.built.pp
-
-export MOZBUILD_BACKEND_CHECKED=1
-
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 distclean::
--- a/build/ConfigStatus.py
+++ b/build/ConfigStatus.py
@@ -77,17 +77,17 @@ def config_status(topobjdir = '.', topsr
     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 = '.'
+        topobjdir = os.path.abspath('.')
 
     env = ConfigEnvironment(topsrcdir, topobjdir, defines=defines,
             non_global_defines=non_global_defines, substs=substs)
 
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -621,18 +621,24 @@ else
 HOST_OUTOPTION = -o # eol
 endif
 ################################################################################
 
 # Regenerate the build backend if it is out of date. We only check this once
 # per traversal, hence the ifdef and the export. This rule needs to come before
 # other rules for the default target or else it may not run in time.
 ifndef MOZBUILD_BACKEND_CHECKED
-default::
-	$(MAKE) -C $(DEPTH) backend.RecursiveMakeBackend.built
+
+$(DEPTH)/backend.RecursiveMakeBackend.built:
+	@echo "Build configuration changed. Regenerating backend."
+	@cd $(DEPTH) && $(PYTHON) ./config.status
+
+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))
--- a/js/src/build/ConfigStatus.py
+++ b/js/src/build/ConfigStatus.py
@@ -77,17 +77,17 @@ def config_status(topobjdir = '.', topsr
     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 = '.'
+        topobjdir = os.path.abspath('.')
 
     env = ConfigEnvironment(topsrcdir, topobjdir, defines=defines,
             non_global_defines=non_global_defines, substs=substs)
 
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -621,18 +621,24 @@ else
 HOST_OUTOPTION = -o # eol
 endif
 ################################################################################
 
 # Regenerate the build backend if it is out of date. We only check this once
 # per traversal, hence the ifdef and the export. This rule needs to come before
 # other rules for the default target or else it may not run in time.
 ifndef MOZBUILD_BACKEND_CHECKED
-default::
-	$(MAKE) -C $(DEPTH) backend.RecursiveMakeBackend.built
+
+$(DEPTH)/backend.RecursiveMakeBackend.built:
+	@echo "Build configuration changed. Regenerating backend."
+	@cd $(DEPTH) && $(PYTHON) ./config.status
+
+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))
--- a/python/mozbuild/mozbuild/backend/base.py
+++ b/python/mozbuild/mozbuild/backend/base.py
@@ -103,16 +103,38 @@ class BuildBackend(LoggingMixin):
 
         self.environment = environment
         self.summary = BackendConsumeSummary()
 
         # Files whose modification should cause a new read and backend
         # generation.
         self.backend_input_files = set()
 
+        # Pull in Python files for this package as dependencies so backend
+        # regeneration occurs if any of the code affecting it changes.
+        for name, module in sys.modules.items():
+            if not module or not name.startswith('mozbuild'):
+                continue
+
+            p = module.__file__
+
+            # We need to look at the actual source files as opposed to derived
+            # because there may be nothing loading these modules at build time.
+            # Assuming each .pyc comes from a .py file in the same directory is
+            # not a safe assumption. Hence the assert to catch future changes
+            # in behavior. A better solution likely involves loading all
+            # mozbuild modules at the top of the build to force .pyc
+            # generation.
+            if p.endswith('.pyc'):
+                p = p[0:-1]
+
+            assert os.path.exists(p)
+
+            self.backend_input_files.add((os.path.abspath(p)))
+
         self._environments = {}
         self._environments[environment.topobjdir] = environment
 
         self._init()
 
     def _init():
         """Hook point for child classes to perform actions during __init__.
 
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -221,17 +221,22 @@ class RecursiveMakeBackend(BuildBackend)
             self.summary.managed_count += 1
 
         # Write out a dependency file used to determine whether a config.status
         # re-run is needed.
         backend_built_path = os.path.join(self.environment.topobjdir,
             'backend.%s.built' % self.__class__.__name__).replace(os.sep, '/')
         backend_deps = FileAvoidWrite('%s.pp' % backend_built_path)
         inputs = sorted(p.replace(os.sep, '/') for p in self.backend_input_files)
-        backend_deps.write('%s: %s\n' % (backend_built_path, ' '.join(inputs)))
+
+        # We need to use $(DEPTH) so the target here matches what's in
+        # rules.mk. If they are different, the dependencies don't get pulled in
+        # properly.
+        backend_deps.write('$(DEPTH)/backend.RecursiveMakeBackend.built: %s\n' %
+            ' '.join(inputs))
         for path in inputs:
             backend_deps.write('%s:\n' % path)
 
         self._update_from_avoid_write(backend_deps.close())
         self.summary.managed_count += 1
 
     def _process_directory_traversal(self, obj, backend_file):
         """Process a data.DirectoryTraversal instance."""