blob: eee679b58c0b0aa00677258027d8fac315488405 [file] [log] [blame]
# 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/.
'''
Script to produce an Android ARchive (.aar) containing the compiled
Gecko library binaries. The AAR file is intended for use by local
developers using Gradle.
'''
from __future__ import absolute_import, print_function
import argparse
import hashlib
import os
import shutil
import sys
import zipfile
from mozbuild import util
from mozpack.copier import Jarrer
from mozpack.files import (
File,
FileFinder,
JarFinder,
)
from mozpack.mozjar import JarReader
MAVEN_POM_TEMPLATE = r'''
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>{groupId}</groupId>
<artifactId>{artifactId}</artifactId>
<version>{version}</version>
<packaging>{packaging}</packaging>
<dependencies>
{dependencies}
</dependencies>
</project>
'''.lstrip()
MAVEN_POM_DEPENDENCY_TEMPLATE = r'''
<dependency>
<groupId>{groupId}</groupId>
<artifactId>{artifactId}</artifactId>
<version>{version}</version>
<type>{packaging}</type>
</dependency>
'''.lstrip()
IVY_XML_TEMPLATE = r'''
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0">
<info organisation="{organisation}" module="{module}" revision="{revision}" status="integration" publication="{publication}"/>
<configurations/>
<publications>
<artifact name="{name}" type="{type}" ext="{ext}"/>
</publications>
<dependencies>
{dependencies}
</dependencies>
</ivy-module>
'''.lstrip()
IVY_XML_DEPENDENCY_TEMPLATE = r'''
<dependency org="{organisation}" name="{name}" rev="{revision}" />
'''.lstrip()
def _zipdir(path, output_file):
zip = zipfile.ZipFile(output_file, "w")
for root, dirs, files in os.walk(path, topdown=True):
archive_root = root.replace(path, '')
for file in files:
zip.write(os.path.join(root, file), os.path.join(archive_root, file))
def _generate_geckoview_classes_jar(distdir, base_path):
base_folder = FileFinder(base_path, ignore=['gecko-R.jar'])
# Unzip all jar files into $(DISTDIR)/geckoview_aar_classes.
geckoview_aar_classes_path = os.path.join(distdir, 'geckoview_aar_classes')
shutil.rmtree(geckoview_aar_classes_path, ignore_errors=True)
util.ensureParentDir(geckoview_aar_classes_path)
for p, f in base_folder.find('*.jar'):
with zipfile.ZipFile(f.path) as zf:
zf.extractall(geckoview_aar_classes_path)
# Rezip them into a single classes.jar file.
classes_jar_path = os.path.join(distdir, 'classes.jar')
_zipdir(geckoview_aar_classes_path, classes_jar_path)
return File(classes_jar_path)
def package_geckolibs_aar(topsrcdir, distdir, appname, output_file):
jarrer = Jarrer(optimize=False)
srcdir = os.path.join(topsrcdir, 'mobile', 'android', 'geckoview_library', 'geckolibs')
jarrer.add('AndroidManifest.xml', File(os.path.join(srcdir, 'AndroidManifest.xml')))
jarrer.add('classes.jar', File(os.path.join(srcdir, 'classes.jar')))
jni = FileFinder(os.path.join(distdir, appname, 'lib'))
for p, f in jni.find('**/*.so'):
jarrer.add(os.path.join('jni', p), f)
# Include the buildinfo JSON as an asset, to give future consumers at least
# a hope of determining where this AAR came from.
json = FileFinder(distdir, ignore=['*.mozinfo.json'])
for p, f in json.find('*.json'):
jarrer.add(os.path.join('assets', p), f)
# This neatly ignores omni.ja.
assets = FileFinder(os.path.join(distdir, appname, 'assets'))
for p, f in assets.find('**/*.so'):
jarrer.add(os.path.join('assets', p), f)
jarrer.copy(output_file)
return 0
def package_geckoview_aar(topsrcdir, distdir, appname, output_file):
jarrer = Jarrer(optimize=False)
app_path = os.path.join(distdir, appname)
assets = FileFinder(os.path.join(app_path, 'assets'), ignore=['*.so'])
for p, f in assets.find('omni.ja'):
jarrer.add(os.path.join('assets', p), f)
# The folder that contains Fennec's JAR files and resources.
base_path = os.path.join(distdir, '..', 'mobile', 'android', 'base')
# The resource set is packaged during Fennec's build.
resjar = JarReader(os.path.join(base_path, 'geckoview_resources.zip'))
for p, f in JarFinder(base_path, resjar).find('*'):
jarrer.add(os.path.join('res', p), f)
# Package the contents of all Fennec JAR files into classes.jar.
classes_jar_file = _generate_geckoview_classes_jar(distdir, base_path)
jarrer.add('classes.jar', classes_jar_file)
# Add R.txt.
jarrer.add('R.txt', File(os.path.join(base_path, 'R.txt')))
# Finally add AndroidManifest.xml.
srcdir = os.path.join(topsrcdir, 'mobile', 'android', 'geckoview_library', 'geckoview')
jarrer.add('AndroidManifest.xml', File(os.path.join(srcdir, 'AndroidManifest.xml')))
jarrer.copy(output_file)
return 0
def main(args):
parser = argparse.ArgumentParser()
parser.add_argument(dest='dir',
metavar='DIR',
help='Path to write Android ARchives and metadata to.')
parser.add_argument('--verbose', '-v', default=False, action='store_true',
help='be verbose')
parser.add_argument('--revision',
help='Revision identifier to write.')
parser.add_argument('--topsrcdir',
help='Top source directory.')
parser.add_argument('--distdir',
help='Distribution directory (usually $OBJDIR/dist).')
parser.add_argument('--appname',
help='Application name (usually $MOZ_APP_NAME, like "fennec").')
args = parser.parse_args(args)
# An Ivy 'publication' date must be given in the form yyyyMMddHHmmss, and Mozilla buildids are in this format.
if len(args.revision) != 14:
raise ValueError('Revision must be in yyyyMMddHHmmss format: %s' % args.revision)
paths_to_hash = []
groupId='org.mozilla'
packaging_type='aar'
gecklibs_aar = os.path.join(args.dir, 'geckolibs-{revision}.aar').format(revision=args.revision)
paths_to_hash.append(gecklibs_aar)
geckoview_aar = os.path.join(args.dir, 'geckoview-{revision}.aar').format(revision=args.revision)
paths_to_hash.append(geckoview_aar)
package_geckolibs_aar(args.topsrcdir, args.distdir, args.appname, gecklibs_aar)
package_geckoview_aar(args.topsrcdir, args.distdir, args.appname, geckoview_aar)
geckolibs_pom_path = os.path.join(args.dir, 'geckolibs-{revision}.pom').format(revision=args.revision)
paths_to_hash.append(geckolibs_pom_path)
geckolibs_pom = MAVEN_POM_TEMPLATE.format(
groupId=groupId,
artifactId='geckolibs',
version=args.revision,
packaging=packaging_type,
dependencies=''
)
with open(geckolibs_pom_path, 'wt') as f:
f.write(geckolibs_pom)
geckoview_pom_path = os.path.join(args.dir, 'geckoview-{revision}.pom').format(revision=args.revision)
paths_to_hash.append(geckoview_pom_path)
geckoview_pom = MAVEN_POM_TEMPLATE.format(
groupId=groupId,
artifactId='geckoview',
version=args.revision,
packaging=packaging_type,
dependencies=MAVEN_POM_DEPENDENCY_TEMPLATE.format(
groupId=groupId,
artifactId='geckolibs',
version=args.revision,
packaging=packaging_type
)
)
with open(geckoview_pom_path, 'wt') as f:
f.write(geckoview_pom)
geckolibs_ivy_path = os.path.join(args.dir, 'ivy-geckolibs-{revision}.xml').format(revision=args.revision)
paths_to_hash.append(geckolibs_ivy_path)
with open(geckolibs_ivy_path, 'wt') as f:
f.write(IVY_XML_TEMPLATE.format(
organisation=groupId,
module='geckolibs',
revision=args.revision,
publication=args.revision, # A white lie.
name='geckolibs',
type=packaging_type,
ext=packaging_type,
dependencies=''
))
geckoview_ivy_path = os.path.join(args.dir, 'ivy-geckoview-{revision}.xml').format(revision=args.revision)
paths_to_hash.append(geckoview_ivy_path)
with open(geckoview_ivy_path, 'wt') as f:
f.write(IVY_XML_TEMPLATE.format(
organisation=groupId,
module='geckoview',
revision=args.revision,
publication=args.revision, # A white lie.
name='geckoview',
type=packaging_type,
ext=packaging_type,
dependencies=IVY_XML_DEPENDENCY_TEMPLATE.format(
organisation=groupId,
name='geckolibs',
revision=args.revision)
))
for p in paths_to_hash:
sha = "%s.sha1" % p
with open(sha, 'wt') as f:
f.write(util.hash_file(p, hasher=hashlib.sha1()))
if args.verbose:
print(p)
print(sha)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))