mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1062221 - Change how DIRS and TEST_DIRS are handled. r=gps
Up to now, DIRS and TEST_DIRS were dumb values. This change makes them a list of ContextDerivedValues, and handles the fact that some types of paths are relative to the current source directory and others to the topsrcdir. This also makes us one step closer to fixing bug 991983.
This commit is contained in:
parent
0412683b7d
commit
2ff412e6fe
@ -9,7 +9,12 @@ CONFIGURE_SUBST_FILES += ['installer/Makefile']
|
||||
DIRS += [
|
||||
'../locales',
|
||||
'locales',
|
||||
'stumbler',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ANDROID_MLS_STUMBLER']:
|
||||
DIRS += ['stumbler']
|
||||
|
||||
DIRS += [
|
||||
'base',
|
||||
'chrome',
|
||||
'components',
|
||||
@ -21,9 +26,6 @@ DIRS += [
|
||||
'extensions',
|
||||
]
|
||||
|
||||
if not CONFIG['MOZ_ANDROID_MLS_STUMBLER']:
|
||||
DIRS.remove('stumbler')
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
DIRS += ['../../xulrunner/tools/redit']
|
||||
|
||||
|
@ -787,19 +787,21 @@ class RecursiveMakeBackend(CommonBackend):
|
||||
"""Process a data.DirectoryTraversal instance."""
|
||||
fh = backend_file.fh
|
||||
|
||||
def relativize(dirs):
|
||||
return [mozpath.normpath(mozpath.join(backend_file.relobjdir, d))
|
||||
for d in dirs]
|
||||
def relativize(base, dirs):
|
||||
return (mozpath.relpath(d.translated, base) for d in dirs)
|
||||
|
||||
if obj.dirs:
|
||||
fh.write('DIRS := %s\n' % ' '.join(obj.dirs))
|
||||
self._traversal.add(backend_file.relobjdir, dirs=relativize(obj.dirs))
|
||||
fh.write('DIRS := %s\n' % ' '.join(
|
||||
relativize(backend_file.objdir, obj.dirs)))
|
||||
self._traversal.add(backend_file.relobjdir,
|
||||
dirs=relativize(self.environment.topobjdir, obj.dirs))
|
||||
|
||||
if obj.test_dirs:
|
||||
fh.write('TEST_DIRS := %s\n' % ' '.join(obj.test_dirs))
|
||||
fh.write('TEST_DIRS := %s\n' % ' '.join(
|
||||
relativize(backend_file.objdir, obj.test_dirs)))
|
||||
if self.environment.substs.get('ENABLE_TESTS', False):
|
||||
self._traversal.add(backend_file.relobjdir,
|
||||
tests=relativize(obj.test_dirs))
|
||||
dirs=relativize(self.environment.topobjdir, obj.test_dirs))
|
||||
|
||||
# The directory needs to be registered whether subdirectories have been
|
||||
# registered or not.
|
||||
|
@ -25,13 +25,16 @@ from mozbuild.util import (
|
||||
HierarchicalStringListWithFlagsFactory,
|
||||
KeyedDefaultDict,
|
||||
List,
|
||||
memoize,
|
||||
memoized_property,
|
||||
ReadOnlyKeyedDefaultDict,
|
||||
StrictOrderingOnAppendList,
|
||||
StrictOrderingOnAppendListWithFlagsFactory,
|
||||
TypedList,
|
||||
)
|
||||
import mozpack.path as mozpath
|
||||
from types import StringTypes
|
||||
from UserString import UserString
|
||||
|
||||
import itertools
|
||||
|
||||
@ -227,6 +230,76 @@ class FinalTargetValue(ContextDerivedValue, unicode):
|
||||
return unicode.__new__(cls, value)
|
||||
|
||||
|
||||
class SourcePath(ContextDerivedValue, UserString):
|
||||
"""Stores and resolves a source path relative to a given context
|
||||
|
||||
This class is used as a backing type for some of the sandbox variables.
|
||||
It expresses paths relative to a context. Paths starting with a '/'
|
||||
are considered relative to the topsrcdir, and other paths relative
|
||||
to the current source directory for the associated context.
|
||||
"""
|
||||
def __new__(cls, context, value=None):
|
||||
if not isinstance(context, Context) and value is None:
|
||||
return unicode(context)
|
||||
return super(SourcePath, cls).__new__(cls)
|
||||
|
||||
def __init__(self, context, value=None):
|
||||
self.context = context
|
||||
self.value = value
|
||||
|
||||
@memoized_property
|
||||
def data(self):
|
||||
"""Serializes the path for UserString."""
|
||||
if self.value.startswith('/'):
|
||||
ret = None
|
||||
# If the path starts with a '/' and is actually relative to an
|
||||
# external source dir, use that as base instead of topsrcdir.
|
||||
if self.context.config.external_source_dir:
|
||||
ret = mozpath.join(self.context.config.external_source_dir,
|
||||
self.value[1:])
|
||||
if not ret or not os.path.exists(ret):
|
||||
ret = mozpath.join(self.context.config.topsrcdir,
|
||||
self.value[1:])
|
||||
else:
|
||||
ret = mozpath.join(self.context.srcdir, self.value)
|
||||
return mozpath.normpath(ret)
|
||||
|
||||
def __unicode__(self):
|
||||
# UserString doesn't implement a __unicode__ function at all, so add
|
||||
# ours.
|
||||
return self.data
|
||||
|
||||
@memoized_property
|
||||
def translated(self):
|
||||
"""Returns the corresponding path in the objdir.
|
||||
|
||||
Ideally, we wouldn't need this function, but the fact that both source
|
||||
path under topsrcdir and the external source dir end up mixed in the
|
||||
objdir (aka pseudo-rework), this is needed.
|
||||
"""
|
||||
if self.value.startswith('/'):
|
||||
ret = mozpath.join(self.context.config.topobjdir, self.value[1:])
|
||||
else:
|
||||
ret = mozpath.join(self.context.objdir, self.value)
|
||||
return mozpath.normpath(ret)
|
||||
|
||||
|
||||
@memoize
|
||||
def ContextDerivedTypedList(type, base_class=List):
|
||||
"""Specialized TypedList for use with ContextDerivedValue types.
|
||||
"""
|
||||
assert issubclass(type, ContextDerivedValue)
|
||||
class _TypedList(ContextDerivedValue, TypedList(type, base_class)):
|
||||
def __init__(self, context, iterable=[]):
|
||||
class _Type(type):
|
||||
def __new__(cls, obj):
|
||||
return type(context, obj)
|
||||
self.TYPE = _Type
|
||||
super(_TypedList, self).__init__(iterable)
|
||||
|
||||
return _TypedList
|
||||
|
||||
|
||||
# This defines the set of mutable global variables.
|
||||
#
|
||||
# Each variable is a tuple of:
|
||||
@ -346,7 +419,7 @@ VARIABLES = {
|
||||
should load lazily. This only has an effect when building with MSVC.
|
||||
""", None),
|
||||
|
||||
'DIRS': (List, list,
|
||||
'DIRS': (ContextDerivedTypedList(SourcePath), list,
|
||||
"""Child directories to descend into looking for build frontend files.
|
||||
|
||||
This works similarly to the ``DIRS`` variable in make files. Each str
|
||||
@ -637,7 +710,7 @@ VARIABLES = {
|
||||
``HOST_BIN_SUFFIX``, the name will remain unchanged.
|
||||
""", None),
|
||||
|
||||
'TEST_DIRS': (List, list,
|
||||
'TEST_DIRS': (ContextDerivedTypedList(SourcePath), list,
|
||||
"""Like DIRS but only for directories that contain test-only code.
|
||||
|
||||
If tests are not enabled, this variable will be ignored.
|
||||
|
@ -945,7 +945,7 @@ class BuildReader(object):
|
||||
if d in recurse_info:
|
||||
raise SandboxValidationError(
|
||||
'Directory (%s) registered multiple times in %s' % (
|
||||
d, var), context)
|
||||
mozpath.relpath(d, context.srcdir), var), context)
|
||||
|
||||
recurse_info[d] = {}
|
||||
if 'templates' in sandbox.metadata:
|
||||
@ -955,9 +955,8 @@ class BuildReader(object):
|
||||
sandbox.recompute_exports()
|
||||
recurse_info[d]['exports'] = dict(sandbox.metadata['exports'])
|
||||
|
||||
for relpath, child_metadata in recurse_info.items():
|
||||
child_path = sandbox.normalize_path(mozpath.join(relpath,
|
||||
'moz.build'), srcdir=curdir)
|
||||
for path, child_metadata in recurse_info.items():
|
||||
child_path = mozpath.join(path, 'moz.build')
|
||||
|
||||
# Ensure we don't break out of the topsrcdir. We don't do realpath
|
||||
# because it isn't necessary. If there are symlinks in the srcdir,
|
||||
|
@ -98,7 +98,13 @@ class TestEmitterBasic(unittest.TestCase):
|
||||
self.assertEqual(reldirs, ['', 'foo', 'foo/biz', 'bar'])
|
||||
|
||||
dirs = [o.dirs for o in objs]
|
||||
self.assertEqual(dirs, [['foo', 'bar'], ['biz'], [], []])
|
||||
self.assertEqual(dirs, [
|
||||
[
|
||||
mozpath.join(reader.config.topsrcdir, 'foo'),
|
||||
mozpath.join(reader.config.topsrcdir, 'bar')
|
||||
], [
|
||||
mozpath.join(reader.config.topsrcdir, 'foo', 'biz')
|
||||
], [], []])
|
||||
|
||||
def test_traversal_all_vars(self):
|
||||
reader = self.reader('traversal-all-vars')
|
||||
@ -115,8 +121,10 @@ class TestEmitterBasic(unittest.TestCase):
|
||||
reldir = o.relativedir
|
||||
|
||||
if reldir == '':
|
||||
self.assertEqual(o.dirs, ['regular'])
|
||||
self.assertEqual(o.test_dirs, ['test'])
|
||||
self.assertEqual(o.dirs, [
|
||||
mozpath.join(reader.config.topsrcdir, 'regular')])
|
||||
self.assertEqual(o.test_dirs, [
|
||||
mozpath.join(reader.config.topsrcdir, 'test')])
|
||||
|
||||
def test_config_file_substitution(self):
|
||||
reader = self.reader('config-file-substitution')
|
||||
|
@ -10,9 +10,42 @@ from mozunit import main
|
||||
|
||||
from mozbuild.frontend.context import (
|
||||
Context,
|
||||
VARIABLES,
|
||||
ContextDerivedValue,
|
||||
ContextDerivedTypedList,
|
||||
)
|
||||
|
||||
from mozbuild.util import (
|
||||
StrictOrderingOnAppendList,
|
||||
UnsortedError,
|
||||
)
|
||||
|
||||
|
||||
class Fuga(object):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
class Piyo(ContextDerivedValue):
|
||||
def __init__(self, context, value):
|
||||
if not isinstance(value, unicode):
|
||||
raise ValueError
|
||||
self.context = context
|
||||
self.value = value
|
||||
|
||||
def lower(self):
|
||||
return self.value.lower()
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
VARIABLES = {
|
||||
'HOGE': (unicode, unicode, None, None),
|
||||
'FUGA': (Fuga, unicode, None, None),
|
||||
'PIYO': (Piyo, unicode, None, None),
|
||||
'HOGERA': (ContextDerivedTypedList(Piyo, StrictOrderingOnAppendList),
|
||||
list, None, None),
|
||||
}
|
||||
|
||||
class TestContext(unittest.TestCase):
|
||||
def test_key_rejection(self):
|
||||
@ -39,35 +72,101 @@ class TestContext(unittest.TestCase):
|
||||
self.assertTrue(e[3])
|
||||
|
||||
def test_allowed_set(self):
|
||||
self.assertIn('DIRS', VARIABLES)
|
||||
self.assertIn('HOGE', VARIABLES)
|
||||
|
||||
ns = Context(allowed_variables=VARIABLES)
|
||||
|
||||
ns['DIRS'] = ['foo']
|
||||
self.assertEqual(ns['DIRS'], ['foo'])
|
||||
ns['HOGE'] = 'foo'
|
||||
self.assertEqual(ns['HOGE'], 'foo')
|
||||
|
||||
def test_value_checking(self):
|
||||
ns = Context(allowed_variables=VARIABLES)
|
||||
|
||||
# Setting to a non-allowed type should not work.
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
ns['DIRS'] = True
|
||||
ns['HOGE'] = True
|
||||
|
||||
e = ve.exception.args
|
||||
self.assertEqual(e[0], 'global_ns')
|
||||
self.assertEqual(e[1], 'set_type')
|
||||
self.assertEqual(e[2], 'DIRS')
|
||||
self.assertTrue(e[3])
|
||||
self.assertEqual(e[4], list)
|
||||
self.assertEqual(e[2], 'HOGE')
|
||||
self.assertEqual(e[3], True)
|
||||
self.assertEqual(e[4], unicode)
|
||||
|
||||
def test_key_checking(self):
|
||||
# Checking for existence of a key should not populate the key if it
|
||||
# doesn't exist.
|
||||
g = Context(allowed_variables=VARIABLES)
|
||||
|
||||
self.assertFalse('DIRS' in g)
|
||||
self.assertFalse('DIRS' in g)
|
||||
self.assertFalse('HOGE' in g)
|
||||
self.assertFalse('HOGE' in g)
|
||||
|
||||
def test_coercion(self):
|
||||
ns = Context(allowed_variables=VARIABLES)
|
||||
|
||||
# Setting to a type different from the allowed input type should not
|
||||
# work.
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
ns['FUGA'] = False
|
||||
|
||||
e = ve.exception.args
|
||||
self.assertEqual(e[0], 'global_ns')
|
||||
self.assertEqual(e[1], 'set_type')
|
||||
self.assertEqual(e[2], 'FUGA')
|
||||
self.assertEqual(e[3], False)
|
||||
self.assertEqual(e[4], unicode)
|
||||
|
||||
ns['FUGA'] = 'fuga'
|
||||
self.assertIsInstance(ns['FUGA'], Fuga)
|
||||
self.assertEqual(ns['FUGA'].value, 'fuga')
|
||||
|
||||
ns['FUGA'] = Fuga('hoge')
|
||||
self.assertIsInstance(ns['FUGA'], Fuga)
|
||||
self.assertEqual(ns['FUGA'].value, 'hoge')
|
||||
|
||||
def test_context_derived_coercion(self):
|
||||
ns = Context(allowed_variables=VARIABLES)
|
||||
|
||||
# Setting to a type different from the allowed input type should not
|
||||
# work.
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
ns['PIYO'] = False
|
||||
|
||||
e = ve.exception.args
|
||||
self.assertEqual(e[0], 'global_ns')
|
||||
self.assertEqual(e[1], 'set_type')
|
||||
self.assertEqual(e[2], 'PIYO')
|
||||
self.assertEqual(e[3], False)
|
||||
self.assertEqual(e[4], unicode)
|
||||
|
||||
ns['PIYO'] = 'piyo'
|
||||
self.assertIsInstance(ns['PIYO'], Piyo)
|
||||
self.assertEqual(ns['PIYO'].value, 'piyo')
|
||||
self.assertEqual(ns['PIYO'].context, ns)
|
||||
|
||||
ns['PIYO'] = Piyo(ns, 'fuga')
|
||||
self.assertIsInstance(ns['PIYO'], Piyo)
|
||||
self.assertEqual(ns['PIYO'].value, 'fuga')
|
||||
self.assertEqual(ns['PIYO'].context, ns)
|
||||
|
||||
def test_context_derived_typed_list(self):
|
||||
ns = Context(allowed_variables=VARIABLES)
|
||||
|
||||
# Setting to a type that's rejected by coercion should not work.
|
||||
with self.assertRaises(ValueError):
|
||||
ns['HOGERA'] = [False]
|
||||
|
||||
ns['HOGERA'] += ['a', 'b', 'c']
|
||||
|
||||
self.assertIsInstance(ns['HOGERA'],
|
||||
ContextDerivedTypedList(Piyo, StrictOrderingOnAppendList))
|
||||
for n in range(0, 3):
|
||||
self.assertIsInstance(ns['HOGERA'][n], Piyo)
|
||||
self.assertEqual(ns['HOGERA'][n].value, ['a', 'b', 'c'][n])
|
||||
self.assertEqual(ns['HOGERA'][n].context, ns)
|
||||
|
||||
with self.assertRaises(UnsortedError):
|
||||
ns['HOGERA'] += ['f', 'e', 'd']
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -38,7 +38,9 @@ test_data_path = mozpath.join(test_data_path, 'data')
|
||||
|
||||
class TestSandbox(unittest.TestCase):
|
||||
def sandbox(self):
|
||||
return Sandbox(Context(VARIABLES))
|
||||
return Sandbox(Context({
|
||||
'DIRS': (list, list, None, None),
|
||||
}))
|
||||
|
||||
def test_exec_source_success(self):
|
||||
sandbox = self.sandbox()
|
||||
@ -217,7 +219,10 @@ class TestMozbuildSandbox(unittest.TestCase):
|
||||
|
||||
sandbox.exec_file('moz.build')
|
||||
|
||||
self.assertEqual(sandbox['DIRS'], ['foo', 'bar'])
|
||||
self.assertEqual(sandbox['DIRS'], [
|
||||
sandbox.normalize_path('foo'),
|
||||
sandbox.normalize_path('bar'),
|
||||
])
|
||||
self.assertEqual(sandbox._context.main_path,
|
||||
sandbox.normalize_path('moz.build'))
|
||||
self.assertEqual(len(sandbox._context.all_paths), 2)
|
||||
@ -263,11 +268,11 @@ class TestMozbuildSandbox(unittest.TestCase):
|
||||
# child directory.
|
||||
sandbox = self.sandbox(data_path='include-relative-from-child')
|
||||
sandbox.exec_file('child/child.build')
|
||||
self.assertEqual(sandbox['DIRS'], ['foo'])
|
||||
self.assertEqual(sandbox['DIRS'], [sandbox.normalize_path('child/foo')])
|
||||
|
||||
sandbox = self.sandbox(data_path='include-relative-from-child')
|
||||
sandbox.exec_file('child/child2.build')
|
||||
self.assertEqual(sandbox['DIRS'], ['foo'])
|
||||
self.assertEqual(sandbox['DIRS'], [sandbox.normalize_path('child/foo')])
|
||||
|
||||
def test_include_topsrcdir_relative(self):
|
||||
# An absolute path for include() is relative to topsrcdir.
|
||||
@ -275,7 +280,7 @@ class TestMozbuildSandbox(unittest.TestCase):
|
||||
sandbox = self.sandbox(data_path='include-topsrcdir-relative')
|
||||
sandbox.exec_file('moz.build')
|
||||
|
||||
self.assertEqual(sandbox['DIRS'], ['foo'])
|
||||
self.assertEqual(sandbox['DIRS'], [sandbox.normalize_path('foo')])
|
||||
|
||||
def test_error(self):
|
||||
sandbox = self.sandbox()
|
||||
@ -346,7 +351,7 @@ SOURCES += ['hoge.cpp']
|
||||
|
||||
self.assertEqual(sandbox2._context, {
|
||||
'SOURCES': ['qux.cpp', 'bar.cpp', 'foo.cpp', 'hoge.cpp'],
|
||||
'DIRS': ['foo'],
|
||||
'DIRS': [sandbox.normalize_path('foo')],
|
||||
})
|
||||
|
||||
source = '''
|
||||
@ -387,7 +392,7 @@ TemplateGlobalUPPERVariable()
|
||||
sandbox2.exec_source(source, sandbox.normalize_path('foo.mozbuild'))
|
||||
self.assertEqual(sandbox2._context, {
|
||||
'SOURCES': [],
|
||||
'DIRS': ['foo'],
|
||||
'DIRS': [sandbox.normalize_path('foo')],
|
||||
})
|
||||
|
||||
# However, the result of the template is mixed with the global
|
||||
|
Loading…
Reference in New Issue
Block a user