Bug 1257049 - Stop spawning a separate process for config.status from configure.py. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 19 Aug 2016 11:11:57 +0900
changeset 353902 ee9f4eeaebe897ec6d5e76ab7c4ace8d4782de18
parent 353831 30fa88c82366a358f412ca2cc3268142c8991f0d
child 353903 c3edbba2eb8aa5484eb41511bb0ce5269d3dfd11
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1257049
milestone51.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 1257049 - Stop spawning a separate process for config.status from configure.py. r=gps
configure.py
python/mozbuild/mozbuild/config_status.py
--- a/configure.py
+++ b/configure.py
@@ -5,16 +5,18 @@
 from __future__ import print_function, unicode_literals
 
 import codecs
 import json
 import os
 import subprocess
 import sys
 
+from collections import Iterable
+
 
 base_dir = os.path.abspath(os.path.dirname(__file__))
 sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
 from mozbuild.configure import ConfigureSandbox
 
 
 def main(argv):
     config = {}
@@ -74,21 +76,43 @@ def config_status(config):
         if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
             fh.write('''
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     from mozbuild.config_status import config_status
     config_status(**args)
 ''')
 
+    # Running config.status standalone uses byte literals for all the config,
+    # instead of the unicode literals we have in sanitized_config right now.
+    # Some values in sanitized_config also have more complex types, such as
+    # EnumString, which using when calling config_status would currently break
+    # the build, as well as making it inconsistent with re-running
+    # config.status. Fortunately, EnumString derives from unicode, so it's
+    # covered by converting unicode strings.
+    # Moreover, a lot of the build backend code is currently expecting byte
+    # strings and breaks in subtle ways with unicode strings.
+    def encode(v):
+        if isinstance(v, dict):
+            return {
+                encode(k): encode(val)
+                for k, val in v.iteritems()
+            }
+        if isinstance(v, str):
+            return v
+        if isinstance(v, unicode):
+            return v.encode(encoding)
+        if isinstance(v, Iterable):
+            return [encode(i) for i in v]
+        return v
+
     # Other things than us are going to run this file, so we need to give it
     # executable permissions.
     os.chmod('config.status', 0o755)
     if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
-        os.environ['WRITE_MOZINFO'] = '1'
-        # Until we have access to the virtualenv from this script, execute
-        # config.status externally, with the virtualenv python.
-        return subprocess.call([config['PYTHON'], 'config.status'])
+        os.environ[b'WRITE_MOZINFO'] = b'1'
+        from mozbuild.config_status import config_status
+        return config_status(args=[], **encode(sanitized_config))
     return 0
 
 
 if __name__ == '__main__':
     sys.exit(main(sys.argv))
--- a/python/mozbuild/mozbuild/config_status.py
+++ b/python/mozbuild/mozbuild/config_status.py
@@ -58,17 +58,17 @@ files by running:
    mach build-backend --backend=VisualStudio
 
 ===============================
 '''.strip()
 
 
 def config_status(topobjdir='.', topsrcdir='.', defines=None,
                   non_global_defines=None, substs=None, source=None,
-                  mozconfig=None):
+                  mozconfig=None, args=sys.argv[1:]):
     '''Main function, providing config.status functionality.
 
     Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
     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
@@ -102,17 +102,17 @@ def config_status(topobjdir='.', topsrcd
     parser.add_argument('-d', '--diff', action='store_true',
                         help='print diffs of changed files.')
     parser.add_argument('-b', '--backend', nargs='+', choices=sorted(backends),
                         default=default_backends,
                         help='what backend to build (default: %s).' %
                         ' '.join(default_backends))
     parser.add_argument('--dry-run', action='store_true',
                         help='do everything except writing files out.')
-    options = parser.parse_args()
+    options = parser.parse_args(args)
 
     # Without -n, the current directory is meant to be the top object directory
     if not options.not_topobjdir:
         topobjdir = os.path.abspath('.')
 
     env = ConfigEnvironment(topsrcdir, topobjdir, defines=defines,
             non_global_defines=non_global_defines, substs=substs,
             source=source, mozconfig=mozconfig)