Bug 969164 - Use per-directory config in sandboxes when reading moz.builds. r=gps

This commit is contained in:
Mike Hommey 2014-02-11 10:37:47 +09:00
parent 1f82304637
commit 3ce0ef9179
9 changed files with 41 additions and 43 deletions

View File

@ -169,24 +169,6 @@ class BuildBackend(LoggingMixin):
This exists so child classes don't need to implement __init__.
"""
def get_environment(self, obj):
"""Obtain the ConfigEnvironment for a specific object.
This is used to support external source directories which operate in
their own topobjdir and have their own ConfigEnvironment.
This is somewhat hacky and should be considered for rewrite if external
project integration is rewritten.
"""
environment = self._environments.get(obj.topobjdir, None)
if not environment:
config_status = mozpath.join(obj.topobjdir, 'config.status')
environment = ConfigEnvironment.from_config_status(config_status)
self._environments[obj.topobjdir] = environment
return environment
def consume(self, objs):
"""Consume a stream of TreeMetadata instances.
@ -310,7 +292,7 @@ class BuildBackend(LoggingMixin):
in the current environment.'''
pp = Preprocessor()
srcdir = mozpath.dirname(obj.input_path)
pp.context.update(self.environment.substs)
pp.context.update(obj.config.substs)
pp.context.update(
top_srcdir=obj.topsrcdir,
srcdir=srcdir,

View File

@ -170,8 +170,11 @@ class CommonBackend(BuildBackend):
self._idl_manager = XPIDLManager(self.environment)
self._test_manager = TestManager(self.environment)
self._webidls = WebIDLCollection()
self._configs = set()
def consume_object(self, obj):
self._configs.add(obj.config)
if isinstance(obj, TestManifest):
for test in obj.tests:
self._test_manager.add(test, flavor=obj.flavor,
@ -231,6 +234,9 @@ class CommonBackend(BuildBackend):
self._handle_webidl_collection(self._webidls)
for config in self._configs:
self.backend_input_files.add(config.source)
# Write out a machine-readable file describing every test.
path = mozpath.join(self.environment.topobjdir, 'all-tests.json')
with self._write_file(path) as fh:
@ -257,17 +263,17 @@ class CommonBackend(BuildBackend):
name = m.group('name')
value = m.group('value')
if name:
if name in self.environment.defines:
if name in obj.config.defines:
if cmd == 'define' and value:
l = l[:m.start('value')] \
+ str(self.environment.defines[name]) \
+ str(obj.config.defines[name]) \
+ l[m.end('value'):]
elif cmd == 'undef':
l = l[:m.start('cmd')] \
+ 'define' \
+ l[m.end('cmd'):m.end('name')] \
+ ' ' \
+ str(self.environment.defines[name]) \
+ str(obj.config.defines[name]) \
+ l[m.end('name'):]
elif cmd == 'undef':
l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]

View File

@ -99,8 +99,11 @@ class ConfigEnvironment(object):
"""
def __init__(self, topsrcdir, topobjdir, defines=[], non_global_defines=[],
substs=[]):
substs=[], source=None):
if not source:
source = mozpath.join(topobjdir, 'config.status')
self.source = source
self.defines = ReadOnlyDict(defines)
self.substs = dict(substs)
self.topsrcdir = mozpath.normsep(topsrcdir)
@ -154,4 +157,4 @@ class ConfigEnvironment(object):
config = BuildConfig.from_config_status(path)
return ConfigEnvironment(config.topsrcdir, config.topobjdir,
config.defines, config.non_global_defines, config.substs)
config.defines, config.non_global_defines, config.substs, path)

View File

@ -330,7 +330,7 @@ class RecursiveMakeBackend(CommonBackend):
if obj.objdir not in self._backend_files:
self._backend_files[obj.objdir] = \
BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj))
BackendMakeFile(obj.srcdir, obj.objdir, obj.config)
backend_file = self._backend_files[obj.objdir]
CommonBackend.consume_object(self, obj)
@ -705,6 +705,7 @@ class RecursiveMakeBackend(CommonBackend):
obj.input_path = makefile_in
obj.topsrcdir = bf.environment.topsrcdir
obj.topobjdir = bf.environment.topobjdir
obj.config = bf.environment
self._create_makefile(obj, stub=stub)
# Write out a master list of all IPDL source files.
@ -966,6 +967,7 @@ class RecursiveMakeBackend(CommonBackend):
'makefiles', 'xpidl', 'Makefile.in')
obj.topsrcdir = self.environment.topsrcdir
obj.topobjdir = self.environment.topobjdir
obj.config = self.environment
self._create_makefile(obj, extra=dict(
xpidl_rules='\n'.join(rules),
xpidl_modules=' '.join(xpt_modules),
@ -1091,6 +1093,7 @@ class RecursiveMakeBackend(CommonBackend):
'output_path',
'topsrcdir',
'topobjdir',
'config',
)
def _create_makefile(self, obj, stub=False, extra=None):

View File

@ -26,7 +26,7 @@ log_manager = LoggingManager()
def config_status(topobjdir='.', topsrcdir='.',
defines=[], non_global_defines=[], substs=[]):
defines=[], non_global_defines=[], substs=[], source=None):
'''Main function, providing config.status functionality.
Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
@ -73,7 +73,7 @@ def config_status(topobjdir='.', topsrcdir='.',
topobjdir = os.path.abspath('.')
env = ConfigEnvironment(topsrcdir, topobjdir, defines=defines,
non_global_defines=non_global_defines, substs=substs)
non_global_defines=non_global_defines, substs=substs, source=source)
# mozinfo.json only needs written if configure changes and configure always
# passes this environment variable.

View File

@ -81,6 +81,8 @@ class SandboxDerived(TreeMetadata):
self.srcdir = sandbox['SRCDIR']
self.objdir = sandbox['OBJDIR']
self.config = sandbox.config
class DirectoryTraversal(SandboxDerived):
"""Describes how directory traversal for building should work.

View File

@ -120,6 +120,7 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()):
for f in data[build_file]['included_files']]
# Emit a sandbox for each target.
sandbox = GypSandbox(mozpath.abspath(build_file), included_files)
sandbox.config = config
with sandbox.allow_all_writes() as d:
topsrcdir = d['TOPSRCDIR'] = config.topsrcdir

View File

@ -620,7 +620,7 @@ class BuildReader(object):
read, a new Sandbox is created and emitted.
"""
path = mozpath.join(self.topsrcdir, 'moz.build')
return self.read_mozbuild(path, read_tiers=True,
return self.read_mozbuild(path, self.config, read_tiers=True,
filesystem_absolute=True, metadata={'tier': None})
def walk_topsrcdir(self):
@ -648,12 +648,12 @@ class BuildReader(object):
for path, f in finder.find('**/moz.build'):
path = os.path.join(self.topsrcdir, path)
for s in self.read_mozbuild(path, descend=False,
for s in self.read_mozbuild(path, self.config, descend=False,
filesystem_absolute=True, read_tiers=True):
yield s
def read_mozbuild(self, path, read_tiers=False, filesystem_absolute=False,
descend=True, metadata={}):
def read_mozbuild(self, path, config, read_tiers=False,
filesystem_absolute=False, descend=True, metadata={}):
"""Read and process a mozbuild file, descending into children.
This starts with a single mozbuild file, executes it, and descends into
@ -681,9 +681,9 @@ class BuildReader(object):
"""
self._execution_stack.append(path)
try:
for s in self._read_mozbuild(path, read_tiers=read_tiers,
filesystem_absolute=filesystem_absolute, descend=descend,
metadata=metadata):
for s in self._read_mozbuild(path, config, read_tiers=read_tiers,
filesystem_absolute=filesystem_absolute,
descend=descend, metadata=metadata):
yield s
except BuildReaderError as bre:
@ -709,8 +709,8 @@ class BuildReader(object):
raise BuildReaderError(list(self._execution_stack),
sys.exc_info()[2], other_error=e)
def _read_mozbuild(self, path, read_tiers, filesystem_absolute, descend,
metadata):
def _read_mozbuild(self, path, config, read_tiers, filesystem_absolute,
descend, metadata):
path = mozpath.normpath(path)
log(self._log, logging.DEBUG, 'read_mozbuild', {'path': path},
'Reading file: {path}')
@ -723,7 +723,7 @@ class BuildReader(object):
self._read_files.add(path)
time_start = time.time()
sandbox = MozbuildSandbox(self.config, path, metadata=metadata)
sandbox = MozbuildSandbox(config, path, metadata=metadata)
sandbox.exec_file(path, filesystem_absolute=filesystem_absolute)
sandbox.execution_time = time.time() - time_start
@ -747,7 +747,7 @@ class BuildReader(object):
# We first collect directories populated in variables.
dir_vars = ['DIRS', 'PARALLEL_DIRS', 'TOOL_DIRS']
if self.config.substs.get('ENABLE_TESTS', False) == '1':
if sandbox.config.substs.get('ENABLE_TESTS', False) == '1':
dir_vars.extend(['TEST_DIRS', 'TEST_TOOL_DIRS'])
dirs = [(v, sandbox[v]) for v in dir_vars if v in sandbox]
@ -775,7 +775,7 @@ class BuildReader(object):
raise SandboxValidationError('Cannot find %s referenced '
'from %s' % (source, path))
non_unified_sources.add(source)
for gyp_sandbox in read_from_gyp(self.config,
for gyp_sandbox in read_from_gyp(sandbox.config,
mozpath.join(curdir, gyp_dir.input),
mozpath.join(sandbox['OBJDIR'],
target_dir),
@ -847,7 +847,7 @@ class BuildReader(object):
# that's not our problem. We're not a hosted application: we don't
# need to worry about security too much.
child_path = mozpath.normpath(child_path)
if not is_read_allowed(child_path, self.config):
if not is_read_allowed(child_path, sandbox.config):
raise SandboxValidationError(
'Attempting to process file outside of allowed paths: %s' %
child_path)
@ -855,8 +855,9 @@ class BuildReader(object):
if not descend:
continue
for res in self.read_mozbuild(child_path, read_tiers=False,
filesystem_absolute=True, metadata=child_metadata):
for res in self.read_mozbuild(child_path, sandbox.config,
read_tiers=False, filesystem_absolute=True,
metadata=child_metadata):
yield res
self._execution_stack.pop()

View File

@ -57,7 +57,7 @@ class TestBuildReader(unittest.TestCase):
path = mozpath.join(reader.topsrcdir, 'moz.build')
self.assertTrue(os.path.exists(path))
sandboxes = list(reader.read_mozbuild(path,
sandboxes = list(reader.read_mozbuild(path, reader.config,
filesystem_absolute=True, descend=False))
self.assertEqual(len(sandboxes), 1)