mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 887121 - Make packager install and szip .so libraries in assets/ directly. r=glandium
This adds a Component type to the mozbuild.mozpack package manifest parser, and teaches the packager to accept components of the form [name destdir="dir"]. Then we update the Android package manifest and simplify the packager code. I would have liked to make the packager put mozglue.so and MOZ_CHILD_PROCESS_NAME in lib/$(ABI_DIR) directly, but this turned out to be awkward. Since MOZ_CHILD_PROCESS_NAME needs to have lib/ in its name to load successfully on Android, we would have to add notation in package manifests to install bin/lib/*plugin-container* to lib/$(ABI_DIR)/*plugin-container*.
This commit is contained in:
parent
0e66954343
commit
66582b795d
@ -30,8 +30,7 @@
|
||||
@BINPATH@/dictionaries/*
|
||||
@BINPATH@/hyphenation/*
|
||||
|
||||
[xpcom]
|
||||
@BINPATH@/dependentlibs.list
|
||||
[assets destdir="assets"]
|
||||
#ifndef MOZ_STATIC_JS
|
||||
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
@ -41,7 +40,6 @@
|
||||
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@omxplugin@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@
|
||||
@ -50,6 +48,34 @@
|
||||
@BINPATH@/@DLL_PREFIX@omxpluginsony@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@omxpluginfroyo@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
|
||||
|
||||
@BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
||||
#ifndef MOZ_FOLD_LIBS
|
||||
@BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
||||
#ifndef CROSS_COMPILE
|
||||
@BINPATH@/@DLL_PREFIX@freebl3.chk
|
||||
@BINPATH@/@DLL_PREFIX@softokn3.chk
|
||||
#endif
|
||||
#ifndef NSS_DISABLE_DBM
|
||||
@BINPATH@/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@
|
||||
#ifndef CROSS_COMPILE
|
||||
@BINPATH@/@DLL_PREFIX@nssdbm3.chk
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_FOLD_LIBS
|
||||
@BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
|
||||
#endif
|
||||
|
||||
[xpcom]
|
||||
@BINPATH@/dependentlibs.list
|
||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||
@BINPATH@/@MOZ_CHILD_PROCESS_NAME@
|
||||
|
||||
@BINPATH@/AndroidManifest.xml
|
||||
@ -72,9 +98,6 @@
|
||||
#endif
|
||||
@BINPATH@/application.ini
|
||||
@BINPATH@/platform.ini
|
||||
#ifndef MOZ_FOLD_LIBS
|
||||
@BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/blocklist.xml
|
||||
#ifdef XP_UNIX
|
||||
@BINPATH@/run-mozilla.sh
|
||||
@ -478,28 +501,9 @@
|
||||
|
||||
; [Personal Security Manager]
|
||||
;
|
||||
@BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
||||
@BINPATH@/components/pipboot.xpt
|
||||
@BINPATH@/components/pipnss.xpt
|
||||
@BINPATH@/components/pippki.xpt
|
||||
@BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
||||
#ifndef MOZ_FOLD_LIBS
|
||||
@BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
||||
#ifndef CROSS_COMPILE
|
||||
@BINPATH@/@DLL_PREFIX@freebl3.chk
|
||||
@BINPATH@/@DLL_PREFIX@softokn3.chk
|
||||
#endif
|
||||
#ifndef NSS_DISABLE_DBM
|
||||
@BINPATH@/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@
|
||||
#ifndef CROSS_COMPILE
|
||||
@BINPATH@/@DLL_PREFIX@nssdbm3.chk
|
||||
#endif
|
||||
#endif
|
||||
@BINPATH@/chrome/pippki@JAREXT@
|
||||
@BINPATH@/chrome/pippki.manifest
|
||||
|
||||
|
@ -17,6 +17,108 @@ import mozpack.path
|
||||
from collections import deque
|
||||
|
||||
|
||||
class Component(object):
|
||||
'''
|
||||
Class that represents a component in a package manifest.
|
||||
'''
|
||||
def __init__(self, name, destdir=''):
|
||||
if name.find(' ') > 0:
|
||||
errors.fatal('Malformed manifest: space in component name "%s"'
|
||||
% component)
|
||||
self._name = name
|
||||
self._destdir = destdir
|
||||
|
||||
def __repr__(self):
|
||||
s = self.name
|
||||
if self.destdir:
|
||||
s += ' destdir="%s"' % self.destdir
|
||||
return s
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def destdir(self):
|
||||
return self._destdir
|
||||
|
||||
@staticmethod
|
||||
def _triples(lst):
|
||||
'''
|
||||
Split [1, 2, 3, 4, 5, 6, 7] into [(1, 2, 3), (4, 5, 6)].
|
||||
'''
|
||||
return zip(*[iter(lst)] * 3)
|
||||
|
||||
KEY_VALUE_RE = re.compile(r'''
|
||||
\s* # optional whitespace.
|
||||
([a-zA-Z0-9_]+) # key.
|
||||
\s*=\s* # optional space around =.
|
||||
"([^"]*)" # value without surrounding quotes.
|
||||
(?:\s+|$)
|
||||
''', re.VERBOSE)
|
||||
|
||||
@staticmethod
|
||||
def _split_options(string):
|
||||
'''
|
||||
Split 'key1="value1" key2="value2"' into
|
||||
{'key1':'value1', 'key2':'value2'}.
|
||||
|
||||
Returned keys and values are all strings.
|
||||
|
||||
Throws ValueError if the input is malformed.
|
||||
'''
|
||||
options = {}
|
||||
splits = Component.KEY_VALUE_RE.split(string)
|
||||
if len(splits) % 3 != 1:
|
||||
# This should never happen -- we expect to always split
|
||||
# into ['', ('key', 'val', '')*].
|
||||
raise ValueError("Bad input")
|
||||
if splits[0]:
|
||||
raise ValueError('Unrecognized input ' + splits[0])
|
||||
for key, val, no_match in Component._triples(splits[1:]):
|
||||
if no_match:
|
||||
raise ValueError('Unrecognized input ' + no_match)
|
||||
options[key] = val
|
||||
return options
|
||||
|
||||
@staticmethod
|
||||
def _split_component_and_options(string):
|
||||
'''
|
||||
Split 'name key1="value1" key2="value2"' into
|
||||
('name', {'key1':'value1', 'key2':'value2'}).
|
||||
|
||||
Returned name, keys and values are all strings.
|
||||
|
||||
Raises ValueError if the input is malformed.
|
||||
'''
|
||||
splits = string.strip().split(None, 1)
|
||||
if not splits:
|
||||
raise ValueError('No component found')
|
||||
component = splits[0].strip()
|
||||
if not component:
|
||||
raise ValueError('No component found')
|
||||
if not re.match('[a-zA-Z0-9_\-]+$', component):
|
||||
raise ValueError('Bad component name ' + component)
|
||||
options = Component._split_options(splits[1]) if len(splits) > 1 else {}
|
||||
return component, options
|
||||
|
||||
@staticmethod
|
||||
def from_string(string):
|
||||
'''
|
||||
Create a component from a string.
|
||||
'''
|
||||
try:
|
||||
name, options = Component._split_component_and_options(string)
|
||||
except ValueError as e:
|
||||
errors.fatal('Malformed manifest: %s' % e)
|
||||
return
|
||||
destdir = options.pop('destdir', '')
|
||||
if options:
|
||||
errors.fatal('Malformed manifest: options %s not recognized'
|
||||
% options.keys())
|
||||
return Component(name, destdir=destdir)
|
||||
|
||||
|
||||
class PackageManifestParser(object):
|
||||
'''
|
||||
Class for parsing of a package manifest, after preprocessing.
|
||||
@ -29,14 +131,16 @@ class PackageManifestParser(object):
|
||||
; file comment
|
||||
|
||||
The parser takes input from the preprocessor line by line, and pushes
|
||||
parsed information to a sink object. The add and remove methods of the
|
||||
sink object are called with the current component and a path.
|
||||
parsed information to a sink object.
|
||||
|
||||
The add and remove methods of the sink object are called with the
|
||||
current Component instance and a path.
|
||||
'''
|
||||
def __init__(self, sink):
|
||||
'''
|
||||
Initialize the package manifest parser with the given sink.
|
||||
'''
|
||||
self._component = ''
|
||||
self._component = Component('')
|
||||
self._sink = sink
|
||||
|
||||
def handle_line(self, str):
|
||||
@ -49,10 +153,7 @@ class PackageManifestParser(object):
|
||||
if not str or str.startswith(';'):
|
||||
return
|
||||
if str.startswith('[') and str.endswith(']'):
|
||||
if str == '[]' or re.search(r'[\[\]\s]', str[1:-1]):
|
||||
errors.fatal('Malformed manifest')
|
||||
else:
|
||||
self._component = str[1:-1]
|
||||
self._component = Component.from_string(str[1:-1])
|
||||
elif str.startswith('-'):
|
||||
str = str[1:]
|
||||
self._sink.remove(self._component, str)
|
||||
@ -227,9 +328,9 @@ class SimpleManifestSink(object):
|
||||
return mozpack.path.relpath(path, 'bin')
|
||||
return path
|
||||
|
||||
def add(self, section, pattern):
|
||||
def add(self, component, pattern):
|
||||
'''
|
||||
Add files with the given pattern.
|
||||
Add files with the given pattern in the given component.
|
||||
'''
|
||||
assert not self._closed
|
||||
added = False
|
||||
@ -237,11 +338,15 @@ class SimpleManifestSink(object):
|
||||
added = True
|
||||
if is_manifest(p):
|
||||
self._manifests.add(p)
|
||||
self.packager.add(SimpleManifestSink.normalize_path(p), f)
|
||||
dest = mozpack.path.join(component.destdir, SimpleManifestSink.normalize_path(p))
|
||||
self.packager.add(dest, f)
|
||||
if not added:
|
||||
errors.error('Missing file(s): %s' % pattern)
|
||||
|
||||
def remove(self, section, pattern):
|
||||
def remove(self, component, pattern):
|
||||
'''
|
||||
Remove files with the given pattern in the given component.
|
||||
'''
|
||||
assert not self._closed
|
||||
errors.fatal('Removal is unsupported')
|
||||
|
||||
|
@ -7,9 +7,10 @@ import mozunit
|
||||
import os
|
||||
from mozpack.packager import (
|
||||
preprocess_manifest,
|
||||
CallDeque,
|
||||
Component,
|
||||
SimplePackager,
|
||||
SimpleManifestSink,
|
||||
CallDeque,
|
||||
)
|
||||
from mozpack.files import GeneratedFile
|
||||
from mozpack.chrome.manifest import (
|
||||
@ -30,6 +31,8 @@ bar/*
|
||||
foo/*
|
||||
-foo/bar
|
||||
chrome.manifest
|
||||
[zot destdir="destdir"]
|
||||
foo/zot
|
||||
; comment
|
||||
#ifdef baz
|
||||
[baz]
|
||||
@ -45,7 +48,8 @@ class TestPreprocessManifest(unittest.TestCase):
|
||||
((MANIFEST_PATH, 2), 'add', '', 'bar/*'),
|
||||
((MANIFEST_PATH, 4), 'add', 'foo', 'foo/*'),
|
||||
((MANIFEST_PATH, 5), 'remove', 'foo', 'foo/bar'),
|
||||
((MANIFEST_PATH, 6), 'add', 'foo', 'chrome.manifest')
|
||||
((MANIFEST_PATH, 6), 'add', 'foo', 'chrome.manifest'),
|
||||
((MANIFEST_PATH, 8), 'add', 'zot destdir="destdir"', 'foo/zot'),
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
@ -53,11 +57,11 @@ class TestPreprocessManifest(unittest.TestCase):
|
||||
def __init__(self):
|
||||
self.log = []
|
||||
|
||||
def add(self, section, path):
|
||||
self._log(errors.get_context(), 'add', section, path)
|
||||
def add(self, component, path):
|
||||
self._log(errors.get_context(), 'add', repr(component), path)
|
||||
|
||||
def remove(self, section, path):
|
||||
self._log(errors.get_context(), 'remove', section, path)
|
||||
def remove(self, component, path):
|
||||
self._log(errors.get_context(), 'remove', repr(component), path)
|
||||
|
||||
def _log(self, *args):
|
||||
self.log.append(args)
|
||||
@ -84,7 +88,7 @@ class TestPreprocessManifest(unittest.TestCase):
|
||||
preprocess_manifest(self.sink, 'manifest',
|
||||
{'baz': 1, 'SUFFIX': '.exe'})
|
||||
self.assertEqual(self.sink.log, self.EXPECTED_LOG +
|
||||
[((self.MANIFEST_PATH, 10), 'add', 'baz', 'baz.exe')])
|
||||
[((self.MANIFEST_PATH, 12), 'add', 'baz', 'baz.exe')])
|
||||
|
||||
|
||||
class MockFinder(object):
|
||||
@ -199,19 +203,25 @@ class TestSimpleManifestSink(unittest.TestCase):
|
||||
foobar = GeneratedFile('foobar')
|
||||
foobaz = GeneratedFile('foobaz')
|
||||
fooqux = GeneratedFile('fooqux')
|
||||
foozot = GeneratedFile('foozot')
|
||||
finder = MockFinder({
|
||||
'bin/foo/bar': foobar,
|
||||
'bin/foo/baz': foobaz,
|
||||
'bin/foo/qux': fooqux,
|
||||
'bin/foo/zot': foozot,
|
||||
'bin/foo/chrome.manifest': GeneratedFile('resource foo foo/'),
|
||||
'bin/chrome.manifest':
|
||||
GeneratedFile('manifest foo/chrome.manifest'),
|
||||
})
|
||||
parser = SimpleManifestSink(finder, formatter)
|
||||
parser.add('section0', 'bin/foo/b*')
|
||||
parser.add('section1', 'bin/foo/qux')
|
||||
parser.add('section1', 'bin/foo/chrome.manifest')
|
||||
self.assertRaises(ErrorMessage, parser.add, 'section1', 'bin/bar')
|
||||
component0 = Component('component0')
|
||||
component1 = Component('component1')
|
||||
component2 = Component('component2', destdir='destdir')
|
||||
parser.add(component0, 'bin/foo/b*')
|
||||
parser.add(component1, 'bin/foo/qux')
|
||||
parser.add(component1, 'bin/foo/chrome.manifest')
|
||||
parser.add(component2, 'bin/foo/zot')
|
||||
self.assertRaises(ErrorMessage, parser.add, 'component1', 'bin/bar')
|
||||
|
||||
self.assertEqual(formatter.log, [])
|
||||
parser.close()
|
||||
@ -221,12 +231,14 @@ class TestSimpleManifestSink(unittest.TestCase):
|
||||
(None, 'add', 'foo/bar', foobar),
|
||||
(None, 'add', 'foo/baz', foobaz),
|
||||
(None, 'add', 'foo/qux', fooqux),
|
||||
(None, 'add', 'destdir/foo/zot', foozot),
|
||||
])
|
||||
|
||||
self.assertEqual(finder.log, [
|
||||
'bin/foo/b*',
|
||||
'bin/foo/qux',
|
||||
'bin/foo/chrome.manifest',
|
||||
'bin/foo/zot',
|
||||
'bin/bar',
|
||||
'bin/chrome.manifest'
|
||||
])
|
||||
@ -258,5 +270,59 @@ class TestCallDeque(unittest.TestCase):
|
||||
d.execute()
|
||||
self.assertEqual(logger._log, ['foo', 'bar', 'baz', 'qux'])
|
||||
|
||||
|
||||
class TestComponent(unittest.TestCase):
|
||||
def do_split(self, string, name, options):
|
||||
n, o = Component._split_component_and_options(string)
|
||||
self.assertEqual(name, n)
|
||||
self.assertEqual(options, o)
|
||||
|
||||
def test_component_split_component_and_options(self):
|
||||
self.do_split('component', 'component', {})
|
||||
self.do_split('trailingspace ', 'trailingspace', {})
|
||||
self.do_split(' leadingspace', 'leadingspace', {})
|
||||
self.do_split(' trim ', 'trim', {})
|
||||
self.do_split(' trim key="value"', 'trim', {'key':'value'})
|
||||
self.do_split(' trim empty=""', 'trim', {'empty':''})
|
||||
self.do_split(' trim space=" "', 'trim', {'space':' '})
|
||||
self.do_split('component key="value" key2="second" ',
|
||||
'component', {'key':'value', 'key2':'second'})
|
||||
self.do_split( 'trim key=" value with spaces " key2="spaces again"',
|
||||
'trim', {'key':' value with spaces ', 'key2': 'spaces again'})
|
||||
|
||||
def do_split_error(self, string):
|
||||
self.assertRaises(ValueError, Component._split_component_and_options, string)
|
||||
|
||||
def test_component_split_component_and_options_errors(self):
|
||||
self.do_split_error('"component')
|
||||
self.do_split_error('comp"onent')
|
||||
self.do_split_error('component"')
|
||||
self.do_split_error('"component"')
|
||||
self.do_split_error('=component')
|
||||
self.do_split_error('comp=onent')
|
||||
self.do_split_error('component=')
|
||||
self.do_split_error('key="val"')
|
||||
self.do_split_error('component key=')
|
||||
self.do_split_error('component key="val')
|
||||
self.do_split_error('component key=val"')
|
||||
self.do_split_error('component key="val" x')
|
||||
self.do_split_error('component x key="val"')
|
||||
self.do_split_error('component key1="val" x key2="val"')
|
||||
|
||||
def do_from_string(self, string, name, destdir=''):
|
||||
component = Component.from_string(string)
|
||||
self.assertEqual(name, component.name)
|
||||
self.assertEqual(destdir, component.destdir)
|
||||
|
||||
def test_component_from_string(self):
|
||||
self.do_from_string('component', 'component')
|
||||
self.do_from_string('component-with-hyphen', 'component-with-hyphen')
|
||||
self.do_from_string('component destdir="foo/bar"', 'component', 'foo/bar')
|
||||
self.do_from_string('component destdir="bar spc"', 'component', 'bar spc')
|
||||
self.assertRaises(ErrorMessage, Component.from_string, '')
|
||||
self.assertRaises(ErrorMessage, Component.from_string, 'component novalue=')
|
||||
self.assertRaises(ErrorMessage, Component.from_string, 'component badoption=badvalue')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
||||
|
@ -345,17 +345,16 @@ ifdef MOZ_OMX_PLUGIN
|
||||
DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginsony.so libomxpluginfroyo.so libomxpluginjb-htc.so
|
||||
endif
|
||||
|
||||
SO_LIBRARIES := $(filter-out $(MOZ_CHILD_PROCESS_NAME),$(filter %.so,$(DIST_FILES)))
|
||||
# These libraries are moved into the assets/ directory of the APK.
|
||||
ASSET_SO_LIBRARIES := $(addprefix assets/,$(SO_LIBRARIES))
|
||||
SO_LIBRARIES := $(filter %.so,$(DIST_FILES))
|
||||
# These libraries are placed in the assets/ directory by packager.py.
|
||||
ASSET_SO_LIBRARIES := $(addprefix assets/,$(filter-out libmozglue.so $(MOZ_CHILD_PROCESS_NAME),$(SO_LIBRARIES)))
|
||||
|
||||
DIST_FILES := $(filter-out $(SO_LIBRARIES),$(DIST_FILES))
|
||||
NON_DIST_FILES += $(SO_LIBARIES)
|
||||
NON_DIST_FILES += libmozglue.so $(MOZ_CHILD_PROCESS_NAME) $(ASSET_SO_LIBRARIES)
|
||||
|
||||
ifdef MOZ_ENABLE_SZIP
|
||||
# These libraries are szipped (before being moved into the assets/
|
||||
# directory of the APK).
|
||||
SZIP_LIBRARIES := $(SO_LIBRARIES)
|
||||
# These libraries are szipped in-place in the assets/ directory.
|
||||
SZIP_LIBRARIES := $(ASSET_SO_LIBRARIES)
|
||||
endif
|
||||
|
||||
PKG_SUFFIX = .apk
|
||||
@ -364,10 +363,8 @@ INNER_MAKE_PACKAGE = \
|
||||
make -C $(GECKO_APP_AP_PATH) gecko.ap_ && \
|
||||
cp $(GECKO_APP_AP_PATH)/gecko.ap_ $(_ABS_DIST) && \
|
||||
( cd $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && \
|
||||
mkdir -p assets && \
|
||||
mkdir -p lib/$(ABI_DIR) && \
|
||||
mv libmozglue.so $(MOZ_CHILD_PROCESS_NAME) lib/$(ABI_DIR) && \
|
||||
mv $(SO_LIBRARIES) assets && \
|
||||
unzip -o $(_ABS_DIST)/gecko.ap_ && \
|
||||
rm $(_ABS_DIST)/gecko.ap_ && \
|
||||
$(ZIP) -0 $(_ABS_DIST)/gecko.ap_ $(ASSET_SO_LIBRARIES) && \
|
||||
@ -387,7 +384,6 @@ INNER_UNMAKE_PACKAGE = \
|
||||
$(UNZIP) $(UNPACKAGE) && \
|
||||
mv lib/$(ABI_DIR)/libmozglue.so . && \
|
||||
mv lib/$(ABI_DIR)/*plugin-container* $(MOZ_CHILD_PROCESS_NAME) && \
|
||||
mv $(ASSET_SO_LIBRARIES) . && \
|
||||
rm -rf lib/$(ABI_DIR) )
|
||||
endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user