Bug 1297718 - Add config.status to sys.modules for dependency detection; r=glandium
authorMike Shal <mshal@mozilla.com>
Fri, 26 Aug 2016 10:04:07 -0400
changeset 312373 c2bacde849ce570486fe81bdd370038ff86d224d
parent 312372 b7e5426f358a1ffb9ca6ac458a8537ba794ea52a
child 312374 9b827786ca68a923bacef503c9a52369381b3170
push id20447
push userkwierso@gmail.com
push dateFri, 02 Sep 2016 20:36:44 +0000
treeherderfx-team@969397f22187 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs1297718
milestone51.0a1
Bug 1297718 - Add config.status to sys.modules for dependency detection; r=glandium MozReview-Commit-ID: J5WaTPYc0vJ
python/mozbuild/mozbuild/action/file_generate.py
python/mozbuild/mozbuild/backend/configenvironment.py
--- a/python/mozbuild/mozbuild/action/file_generate.py
+++ b/python/mozbuild/mozbuild/action/file_generate.py
@@ -56,28 +56,44 @@ def main(argv):
         print('Error: script "{0}" is missing a {1} method'.format(script, method),
               file=sys.stderr)
         return 1
 
     ret = 1
     try:
         with FileAvoidWrite(args.output_file) as output:
             ret = module.__dict__[method](output, *args.additional_arguments)
-            # We treat sets as a statement of success.  Everything else
-            # is an error (so scripts can conveniently |return 1| or
-            # similar).
-            if isinstance(ret, set) and ret:
-                ret |= set(iter_modules_in_path(buildconfig.topsrcdir,
-                                                buildconfig.topobjdir))
+            # The following values indicate a statement of success:
+            #  - a set() (see below)
+            #  - 0
+            #  - False
+            #  - None
+            #
+            # Everything else is an error (so scripts can conveniently |return
+            # 1| or similar). If a set is returned, the elements of the set
+            # indicate additional dependencies that will be listed in the deps
+            # file. Python module imports are automatically included as
+            # dependencies.
+            if isinstance(ret, set):
+                deps = ret
+                # The script succeeded, so reset |ret| to indicate that.
+                ret = None
+            else:
+                deps = set()
+
+            # Only write out the dependencies if the script was successful
+            if not ret:
+                # Add dependencies on any python modules that were imported by
+                # the script.
+                deps |= set(iter_modules_in_path(buildconfig.topsrcdir,
+                                                 buildconfig.topobjdir))
                 mk = Makefile()
-                mk.create_rule([args.output_file]).add_dependencies(ret)
+                mk.create_rule([args.output_file]).add_dependencies(deps)
                 with FileAvoidWrite(args.dep_file) as dep_file:
                     mk.dump(dep_file)
-                # The script succeeded, so reset |ret| to indicate that.
-                ret = None
         # Even when our file's contents haven't changed, we want to update
         # the file's mtime so make knows this target isn't still older than
         # whatever prerequisite caused it to be built this time around.
         try:
             os.utime(args.output_file, None)
         except:
             print('Error processing file "{0}"'.format(args.output_file),
                   file=sys.stderr)
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -3,17 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import
 
 import os
 import sys
 
 from collections import Iterable
-from types import StringTypes
+from types import StringTypes, ModuleType
 
 import mozpack.path as mozpath
 
 from mozbuild.util import ReadOnlyDict
 from mozbuild.shellutil import quote as shell_quote
 
 
 if sys.version_info.major == 2:
@@ -40,16 +40,22 @@ class BuildConfig(object):
     def from_config_status(cls, path):
         """Create an instance from a config.status file."""
         code_cache = cls._CODE_CACHE
         mtime = os.path.getmtime(path)
 
         # cache the compiled code as it can be reused
         # we cache it the first time, or if the file changed
         if not path in code_cache or code_cache[path][0] != mtime:
+            # Add config.status manually to sys.modules so it gets picked up by
+            # iter_modules_in_path() for automatic dependencies.
+            mod = ModuleType('config.status')
+            mod.__file__ = path
+            sys.modules['config.status'] = mod
+
             with open(path, 'rt') as fh:
                 source = fh.read()
                 code_cache[path] = (
                     mtime,
                     compile(source, path, 'exec', dont_inherit=1)
                 )
 
         g = {