blob: 7f0de1d687ef615fa008f7aaed5ca8f43bc79e97 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Creates an Android .aar file."""
import argparse
import os
import posixpath
import shutil
import sys
import tempfile
import zipfile
import filter_zip
from util import build_utils
_ANDROID_BUILD_DIR = os.path.dirname(os.path.dirname(__file__))
def _MergeRTxt(r_paths, include_globs):
"""Merging the given R.txt files and returns them as a string."""
all_lines = set()
for r_path in r_paths:
if include_globs and not build_utils.MatchesGlob(r_path, include_globs):
continue
with open(r_path) as f:
all_lines.update(f.readlines())
return ''.join(sorted(all_lines))
def _MergeProguardConfigs(proguard_configs):
"""Merging the given proguard config files and returns them as a string."""
ret = []
for config in proguard_configs:
ret.append('# FROM: {}'.format(config))
with open(config) as f:
ret.append(f.read())
return '\n'.join(ret)
def _AddResources(aar_zip, resource_zips, include_globs):
"""Adds all resource zips to the given aar_zip.
Ensures all res/values/* files have unique names by prefixing them.
"""
for i, path in enumerate(resource_zips):
if include_globs and not build_utils.MatchesGlob(path, include_globs):
continue
with zipfile.ZipFile(path) as res_zip:
for info in res_zip.infolist():
data = res_zip.read(info)
dirname, basename = posixpath.split(info.filename)
if 'values' in dirname:
root, ext = os.path.splitext(basename)
basename = '{}_{}{}'.format(root, i, ext)
info.filename = posixpath.join(dirname, basename)
info.filename = posixpath.join('res', info.filename)
aar_zip.writestr(info, data)
def main(args):
args = build_utils.ExpandFileArgs(args)
parser = argparse.ArgumentParser()
build_utils.AddDepfileOption(parser)
parser.add_argument('--output', required=True, help='Path to output aar.')
parser.add_argument('--jars', required=True, help='GN list of jar inputs.')
parser.add_argument('--dependencies-res-zips', required=True,
help='GN list of resource zips')
parser.add_argument('--r-text-files', required=True,
help='GN list of R.txt files to merge')
parser.add_argument('--proguard-configs', required=True,
help='GN list of ProGuard flag files to merge.')
parser.add_argument(
'--android-manifest',
help='Path to AndroidManifest.xml to include.',
default=os.path.join(_ANDROID_BUILD_DIR, 'AndroidManifest.xml'))
parser.add_argument('--native-libraries', default='',
help='GN list of native libraries. If non-empty then '
'ABI must be specified.')
parser.add_argument('--abi',
help='ABI (e.g. armeabi-v7a) for native libraries.')
parser.add_argument(
'--jar-excluded-globs',
help='GN-list of globs for paths to exclude in jar.')
parser.add_argument(
'--jar-included-globs',
help='GN-list of globs for paths to include in jar.')
parser.add_argument(
'--resource-included-globs',
help='GN-list of globs for paths to include in R.txt and resources zips.')
options = parser.parse_args(args)
if options.native_libraries and not options.abi:
parser.error('You must provide --abi if you have native libs')
options.jars = build_utils.ParseGnList(options.jars)
options.dependencies_res_zips = build_utils.ParseGnList(
options.dependencies_res_zips)
options.r_text_files = build_utils.ParseGnList(options.r_text_files)
options.proguard_configs = build_utils.ParseGnList(options.proguard_configs)
options.native_libraries = build_utils.ParseGnList(options.native_libraries)
options.jar_excluded_globs = build_utils.ParseGnList(
options.jar_excluded_globs)
options.jar_included_globs = build_utils.ParseGnList(
options.jar_included_globs)
options.resource_included_globs = build_utils.ParseGnList(
options.resource_included_globs)
with tempfile.NamedTemporaryFile(delete=False) as staging_file:
try:
with zipfile.ZipFile(staging_file.name, 'w') as z:
build_utils.AddToZipHermetic(
z, 'AndroidManifest.xml', src_path=options.android_manifest)
path_transform = filter_zip.CreatePathTransform(
options.jar_excluded_globs, options.jar_included_globs, [])
with tempfile.NamedTemporaryFile() as jar_file:
build_utils.MergeZips(
jar_file.name, options.jars, path_transform=path_transform)
build_utils.AddToZipHermetic(z, 'classes.jar', src_path=jar_file.name)
build_utils.AddToZipHermetic(
z,
'R.txt',
data=_MergeRTxt(options.r_text_files,
options.resource_included_globs))
build_utils.AddToZipHermetic(z, 'public.txt', data='')
if options.proguard_configs:
build_utils.AddToZipHermetic(
z, 'proguard.txt',
data=_MergeProguardConfigs(options.proguard_configs))
_AddResources(z, options.dependencies_res_zips,
options.resource_included_globs)
for native_library in options.native_libraries:
libname = os.path.basename(native_library)
build_utils.AddToZipHermetic(
z, os.path.join('jni', options.abi, libname),
src_path=native_library)
except:
os.unlink(staging_file.name)
raise
shutil.move(staging_file.name, options.output)
if options.depfile:
all_inputs = (options.jars + options.dependencies_res_zips +
options.r_text_files + options.proguard_configs)
build_utils.WriteDepfile(options.depfile, options.output, all_inputs)
if __name__ == '__main__':
main(sys.argv[1:])