Bug 1160563 - Part 1: Make ANDROID_RES_DIRS a moz.build variable. r=gps

This patch does a few things.  First, it adds an AbsolutePath data
type, sibling to SourcePath and ObjDirPath.  (Existing Path consumers
that accept an open set of Path subtypes, and that only use full_path,
should function fine with the new AbsolutePath subtype.)

Second, it moves ANDROID_RES_DIRS to a moz.build list of Paths
(ordered).  We test, but don't use in tree, the new AbsolutePath.

--HG--
extra : commitid : DMLy1ogTJ0Y
extra : rebase_source : cb9ac47e8bf7c893a0284adc7a42eccb78ccae3d
This commit is contained in:
Nick Alexander 2015-08-12 11:03:44 -07:00
parent 5a2d80488e
commit 549c28f40f
9 changed files with 98 additions and 13 deletions

View File

@ -579,7 +579,7 @@ gbjar.extra_jars += [
]
if CONFIG['MOZ_CRASHREPORTER']:
gbjar.sources += [ 'CrashReporter.java' ]
ANDROID_RES_DIRS += [ SRCDIR + '/crashreporter/res' ]
ANDROID_RES_DIRS += [ 'crashreporter/res' ]
if CONFIG['MOZ_ANDROID_SHARE_OVERLAY']:
gbjar.sources += [
@ -754,9 +754,9 @@ if CONFIG['MOZ_INSTALL_TRACKING']:
# Putting branding earlier allows branders to override default resources.
ANDROID_RES_DIRS += [
TOPSRCDIR + '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
SRCDIR + '/resources',
OBJDIR + '/res',
'/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
'resources',
'!res',
]
ANDROID_GENERATED_RESFILES += [

View File

@ -26,6 +26,7 @@ import mozpack.path as mozpath
from .common import CommonBackend
from ..frontend.data import (
AndroidResDirs,
AndroidEclipseProjectData,
BrandingFiles,
ConfigFileSubstitution,
@ -598,6 +599,10 @@ class RecursiveMakeBackend(CommonBackend):
for f in obj.files:
backend_file.write('DIST_FILES += %s\n' % f)
elif isinstance(obj, AndroidResDirs):
for p in obj.paths:
backend_file.write('ANDROID_RES_DIRS += %s\n' % p.full_path)
else:
return
obj.ack()

View File

@ -330,8 +330,13 @@ class PathMeta(type):
assert isinstance(context, Context)
if isinstance(value, Path):
context = value.context
if not issubclass(cls, (SourcePath, ObjDirPath)):
cls = ObjDirPath if value.startswith('!') else SourcePath
if not issubclass(cls, (SourcePath, ObjDirPath, AbsolutePath)):
if value.startswith('!'):
cls = ObjDirPath
elif value.startswith('%'):
cls = AbsolutePath
else:
cls = SourcePath
return super(PathMeta, cls).__call__(context, value)
class Path(ContextDerivedValue, unicode):
@ -343,6 +348,7 @@ class Path(ContextDerivedValue, unicode):
- 'srcdir/relative/paths'
- '!/topobjdir/relative/paths'
- '!objdir/relative/paths'
- '%/filesystem/absolute/paths'
"""
__metaclass__ = PathMeta
@ -398,6 +404,8 @@ class SourcePath(Path):
def __init__(self, context, value):
if value.startswith('!'):
raise ValueError('Object directory paths are not allowed')
if value.startswith('%'):
raise ValueError('Filesystem absolute paths are not allowed')
super(SourcePath, self).__init__(context, value)
if value.startswith('/'):
@ -429,7 +437,7 @@ class ObjDirPath(Path):
"""Like Path, but limited to paths in the object directory."""
def __init__(self, context, value=None):
if not value.startswith('!'):
raise ValueError('Source paths are not allowed')
raise ValueError('Object directory paths must start with ! prefix')
super(ObjDirPath, self).__init__(context, value)
if value.startswith('!/'):
@ -439,6 +447,18 @@ class ObjDirPath(Path):
self.full_path = mozpath.normpath(path)
class AbsolutePath(Path):
"""Like Path, but allows arbitrary paths outside the source and object directories."""
def __init__(self, context, value=None):
if not value.startswith('%'):
raise ValueError('Absolute paths must start with % prefix')
if not os.path.isabs(value[1:]):
raise ValueError('Path \'%s\' is not absolute' % value[1:])
super(AbsolutePath, self).__init__(context, value)
self.full_path = mozpath.normpath(value[1:])
@memoize
def ContextDerivedTypedList(klass, base_class=List):
"""Specialized TypedList for use with ContextDerivedValue types.
@ -671,12 +691,12 @@ VARIABLES = {
file.
""", 'export'),
'ANDROID_RES_DIRS': (List, list,
'ANDROID_RES_DIRS': (ContextDerivedTypedListWithItems(Path, List), list,
"""Android resource directories.
This variable contains a list of directories, each relative to
the srcdir, containing static files to package into a 'res'
directory and merge into an APK file.
This variable contains a list of directories containing static
files to package into a 'res' directory and merge into an APK
file.
""", 'export'),
'ANDROID_ECLIPSE_PROJECT_TARGETS': (dict, dict,

View File

@ -963,3 +963,15 @@ class AndroidEclipseProjectData(object):
cpe.ignore_warnings = ignore_warnings
self._classpathentries.append(cpe)
return cpe
class AndroidResDirs(ContextDerived):
"""Represents Android resource directories."""
__slots__ = (
'paths',
)
def __init__(self, context, paths):
ContextDerived.__init__(self, context)
self.paths = paths

View File

@ -24,6 +24,7 @@ import reftest
import mozinfo
from .data import (
AndroidResDirs,
BrandingFiles,
ConfigFileSubstitution,
ContextWrapped,
@ -77,7 +78,7 @@ from .reader import SandboxValidationError
from .context import (
Context,
ObjDirPath,
AbsolutePath,
SourcePath,
ObjDirPath,
Path,
@ -555,7 +556,6 @@ class TreeMetadataEmitter(LoggingMixin):
passthru = VariablePassthru(context)
varlist = [
'ANDROID_GENERATED_RESFILES',
'ANDROID_RES_DIRS',
'DISABLE_STL_WRAPPING',
'EXTRA_COMPONENTS',
'EXTRA_DSO_LDOPTS',
@ -700,6 +700,15 @@ class TreeMetadataEmitter(LoggingMixin):
for name, data in context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items():
yield ContextWrapped(context, data)
paths = context.get('ANDROID_RES_DIRS')
if paths:
for p in paths:
if isinstance(p, SourcePath) and not os.path.isdir(p.full_path):
raise SandboxValidationError('Directory listed in '
'ANDROID_RES_DIRS is not a directory: \'%s\'' %
p.full_path, context)
yield AndroidResDirs(context, paths)
if passthru.variables:
yield passthru

View File

@ -0,0 +1,9 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
ANDROID_RES_DIRS += [
'/dir1',
'!/dir2',
'%/dir3',
]

View File

@ -8,6 +8,7 @@ import unittest
from mozunit import main
from mozbuild.frontend.context import (
AbsolutePath,
Context,
ContextDerivedTypedList,
ContextDerivedTypedListWithItems,
@ -454,6 +455,18 @@ class TestPaths(unittest.TestCase):
path = Path(path)
self.assertIsInstance(path, ObjDirPath)
def test_absolute_path(self):
config = self.config
ctxt = Context(config=config)
ctxt.push_source(mozpath.join(config.topsrcdir, 'foo', 'moz.build'))
path = AbsolutePath(ctxt, '%/qux')
self.assertEqual(path, '%/qux')
self.assertEqual(path.full_path, '/qux')
with self.assertRaises(ValueError):
path = AbsolutePath(ctxt, '%qux')
def test_path_with_mixed_contexts(self):
config = self.config
ctxt1 = Context(config=config)

View File

@ -10,6 +10,7 @@ import unittest
from mozunit import main
from mozbuild.frontend.data import (
AndroidResDirs,
BrandingFiles,
ConfigFileSubstitution,
Defines,
@ -874,5 +875,21 @@ class TestEmitterBasic(unittest.TestCase):
reader = self.reader('dist-files-missing')
self.read_topsrcdir(reader)
def test_android_res_dirs(self):
"""Test that ANDROID_RES_DIRS works properly."""
reader = self.reader('android-res-dirs')
objs = self.read_topsrcdir(reader)
self.assertEqual(len(objs), 1)
self.assertIsInstance(objs[0], AndroidResDirs)
# Android resource directories are ordered.
expected = [
mozpath.join(reader.config.topsrcdir, 'dir1'),
mozpath.join(reader.config.topobjdir, 'dir2'),
'/dir3',
]
self.assertEquals([p.full_path for p in objs[0].paths], expected)
if __name__ == '__main__':
main()