mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 10:22:05 +00:00

Instead, we now run js/src/old-configure from the top-level configure after having run old-configure and extracted a few variables to inherit from it. Because we're now running from the top-level, $_objdir is always the top-level objdir, which simplifies some things. The topobjdir in js/src/config.status, however, needs to stay in js/src because of the build frontend expecting it there. When running js/src/old-configure, we used to need some special treatment for a large number of variables for historic reasons, where we'd take values from the assigned values before running old-configure for some, or from AC_SUBSTs after running old-configure. Now that both old-configure and js/src/old-configure get the same assignments from old-configure.vars, we don't need anything special for the former. And only a few remaining variables still need manual work for the latter. One notable difference, though, is that the new code doesn't try to avoid running js subconfigure, which added complexity, and was actually error-prone. Differential Revision: https://phabricator.services.mozilla.com/D92725
214 lines
7.5 KiB
Python
214 lines
7.5 KiB
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/.
|
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
import codecs
|
|
import errno
|
|
import io
|
|
import itertools
|
|
import logging
|
|
import os
|
|
import sys
|
|
import textwrap
|
|
|
|
|
|
try:
|
|
from collections.abc import Iterable
|
|
except ImportError:
|
|
from collections import Iterable
|
|
|
|
|
|
base_dir = os.path.abspath(os.path.dirname(__file__))
|
|
sys.path.insert(0, os.path.join(base_dir, 'python', 'mozboot'))
|
|
sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
|
|
sys.path.insert(0, os.path.join(base_dir, 'third_party', 'python', 'six'))
|
|
from mozbuild.configure import (
|
|
ConfigureSandbox,
|
|
TRACE,
|
|
)
|
|
from mozbuild.pythonutil import iter_modules_in_path
|
|
from mozbuild.backend.configenvironment import PartialConfigEnvironment
|
|
from mozbuild.util import (
|
|
write_indented_repr,
|
|
)
|
|
import mozpack.path as mozpath
|
|
import six
|
|
|
|
|
|
def main(argv):
|
|
config = {}
|
|
|
|
sandbox = ConfigureSandbox(config, os.environ, argv)
|
|
|
|
clobber_file = 'CLOBBER'
|
|
if not os.path.exists(clobber_file):
|
|
# Simply touch the file.
|
|
with open(clobber_file, 'a'):
|
|
pass
|
|
|
|
if os.environ.get('MOZ_CONFIGURE_TRACE'):
|
|
sandbox._logger.setLevel(TRACE)
|
|
|
|
sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
|
|
|
|
if sandbox._help:
|
|
return 0
|
|
|
|
logging.getLogger('moz.configure').info('Creating config.status')
|
|
|
|
old_js_configure_substs = config.pop('OLD_JS_CONFIGURE_SUBSTS', None)
|
|
old_js_configure_defines = config.pop('OLD_JS_CONFIGURE_DEFINES', None)
|
|
if old_js_configure_substs or old_js_configure_defines:
|
|
js_config = config.copy()
|
|
pwd = os.getcwd()
|
|
try:
|
|
try:
|
|
os.makedirs('js/src')
|
|
except OSError as e:
|
|
if e.errno != errno.EEXIST:
|
|
raise
|
|
|
|
os.chdir('js/src')
|
|
js_config['OLD_CONFIGURE_SUBSTS'] = old_js_configure_substs
|
|
js_config['OLD_CONFIGURE_DEFINES'] = old_js_configure_defines
|
|
# The build system frontend expects $objdir/js/src/config.status
|
|
# to have $objdir/js/src as topobjdir.
|
|
# We want forward slashes on all platforms.
|
|
js_config['TOPOBJDIR'] += '/js/src'
|
|
config_status(js_config, execute=False)
|
|
finally:
|
|
os.chdir(pwd)
|
|
|
|
return config_status(config)
|
|
|
|
|
|
def check_unicode(obj):
|
|
'''Recursively check that all strings in the object are unicode strings.'''
|
|
if isinstance(obj, dict):
|
|
result = True
|
|
for k, v in six.iteritems(obj):
|
|
if not check_unicode(k):
|
|
print("%s key is not unicode." % k, file=sys.stderr)
|
|
result = False
|
|
elif not check_unicode(v):
|
|
print("%s value is not unicode." % k, file=sys.stderr)
|
|
result = False
|
|
return result
|
|
if isinstance(obj, bytes):
|
|
return False
|
|
if isinstance(obj, six.text_type):
|
|
return True
|
|
if isinstance(obj, Iterable):
|
|
return all(check_unicode(o) for o in obj)
|
|
return True
|
|
|
|
|
|
def config_status(config, execute=True):
|
|
# Sanitize config data to feed config.status
|
|
# Ideally, all the backend and frontend code would handle the booleans, but
|
|
# there are so many things involved, that it's easier to keep config.status
|
|
# untouched for now.
|
|
def sanitize_config(v):
|
|
if v is True:
|
|
return '1'
|
|
if v is False:
|
|
return ''
|
|
# Serialize types that look like lists and tuples as lists.
|
|
if not isinstance(v, (bytes, six.text_type, dict)) and isinstance(v, Iterable):
|
|
return list(v)
|
|
return v
|
|
|
|
sanitized_config = {}
|
|
sanitized_config['substs'] = {
|
|
k: sanitize_config(v) for k, v in six.iteritems(config)
|
|
if k not in ('DEFINES', 'TOPSRCDIR', 'TOPOBJDIR', 'CONFIG_STATUS_DEPS',
|
|
'OLD_CONFIGURE_SUBSTS', 'OLD_CONFIGURE_DEFINES')
|
|
}
|
|
for k, v in config['OLD_CONFIGURE_SUBSTS']:
|
|
sanitized_config['substs'][k] = sanitize_config(v)
|
|
sanitized_config['defines'] = {
|
|
k: sanitize_config(v) for k, v in six.iteritems(config['DEFINES'])
|
|
}
|
|
for k, v in config['OLD_CONFIGURE_DEFINES']:
|
|
sanitized_config['defines'][k] = sanitize_config(v)
|
|
sanitized_config['topsrcdir'] = config['TOPSRCDIR']
|
|
sanitized_config['topobjdir'] = config['TOPOBJDIR']
|
|
sanitized_config['mozconfig'] = config.get('MOZCONFIG')
|
|
|
|
if not check_unicode(sanitized_config):
|
|
print("Configuration should be all unicode.", file=sys.stderr)
|
|
print("Please file a bug for the above.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# 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, for which they are normalized to plain strings via
|
|
# indented_repr. Likewise for non-dict non-string iterables being
|
|
# converted to lists.
|
|
def normalize(obj):
|
|
if isinstance(obj, dict):
|
|
return {
|
|
k: normalize(v)
|
|
for k, v in six.iteritems(obj)
|
|
}
|
|
if isinstance(obj, six.text_type):
|
|
return six.text_type(obj)
|
|
if isinstance(obj, Iterable):
|
|
return [normalize(o) for o in obj]
|
|
return obj
|
|
|
|
sanitized_config = normalize(sanitized_config)
|
|
|
|
# Create config.status. Eventually, we'll want to just do the work it does
|
|
# here, when we're able to skip configure tests/use cached results/not rely
|
|
# on autoconf.
|
|
with codecs.open('config.status', 'w', 'utf-8') as fh:
|
|
fh.write(textwrap.dedent('''\
|
|
#!%(python)s
|
|
# coding=utf-8
|
|
from __future__ import unicode_literals
|
|
''') % {'python': config['PYTHON3']})
|
|
for k, v in sorted(six.iteritems(sanitized_config)):
|
|
fh.write('%s = ' % k)
|
|
write_indented_repr(fh, v)
|
|
fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
|
|
"'substs', 'mozconfig']")
|
|
|
|
if execute:
|
|
fh.write(textwrap.dedent('''
|
|
if __name__ == '__main__':
|
|
from mozbuild.util import patch_main
|
|
patch_main()
|
|
from mozbuild.config_status import config_status
|
|
args = dict([(name, globals()[name]) for name in __all__])
|
|
config_status(**args)
|
|
'''))
|
|
|
|
partial_config = PartialConfigEnvironment(config['TOPOBJDIR'])
|
|
partial_config.write_vars(sanitized_config)
|
|
|
|
# Write out a file so the build backend knows to re-run configure when
|
|
# relevant Python changes.
|
|
with io.open('config_status_deps.in', 'w', encoding='utf-8',
|
|
newline='\n') as fh:
|
|
for f in sorted(
|
|
itertools.chain(config['CONFIG_STATUS_DEPS'],
|
|
iter_modules_in_path(config['TOPOBJDIR'],
|
|
config['TOPSRCDIR']))):
|
|
fh.write('%s\n' % mozpath.normpath(f))
|
|
|
|
# Other things than us are going to run this file, so we need to give it
|
|
# executable permissions.
|
|
os.chmod('config.status', 0o755)
|
|
if execute:
|
|
from mozbuild.config_status import config_status
|
|
return config_status(args=[], **sanitized_config)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv))
|