1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2017 The Chromium Authors 4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 6*8975f5c5SAndroid Build Coastguard Worker 7*8975f5c5SAndroid Build Coastguard Worker"""Creates an Android .aar file.""" 8*8975f5c5SAndroid Build Coastguard Worker 9*8975f5c5SAndroid Build Coastguard Workerimport argparse 10*8975f5c5SAndroid Build Coastguard Workerimport os 11*8975f5c5SAndroid Build Coastguard Workerimport posixpath 12*8975f5c5SAndroid Build Coastguard Workerimport shutil 13*8975f5c5SAndroid Build Coastguard Workerimport sys 14*8975f5c5SAndroid Build Coastguard Workerimport tempfile 15*8975f5c5SAndroid Build Coastguard Workerimport zipfile 16*8975f5c5SAndroid Build Coastguard Worker 17*8975f5c5SAndroid Build Coastguard Workerimport filter_zip 18*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils 19*8975f5c5SAndroid Build Coastguard Workerimport action_helpers # build_utils adds //build to sys.path. 20*8975f5c5SAndroid Build Coastguard Workerimport zip_helpers 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Worker_ANDROID_BUILD_DIR = os.path.dirname(os.path.dirname(__file__)) 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard Workerdef _MergeRTxt(r_paths, include_globs): 27*8975f5c5SAndroid Build Coastguard Worker """Merging the given R.txt files and returns them as a string.""" 28*8975f5c5SAndroid Build Coastguard Worker all_lines = set() 29*8975f5c5SAndroid Build Coastguard Worker for r_path in r_paths: 30*8975f5c5SAndroid Build Coastguard Worker if include_globs and not build_utils.MatchesGlob(r_path, include_globs): 31*8975f5c5SAndroid Build Coastguard Worker continue 32*8975f5c5SAndroid Build Coastguard Worker with open(r_path) as f: 33*8975f5c5SAndroid Build Coastguard Worker all_lines.update(f.readlines()) 34*8975f5c5SAndroid Build Coastguard Worker return ''.join(sorted(all_lines)) 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Workerdef _MergeProguardConfigs(proguard_configs): 38*8975f5c5SAndroid Build Coastguard Worker """Merging the given proguard config files and returns them as a string.""" 39*8975f5c5SAndroid Build Coastguard Worker ret = [] 40*8975f5c5SAndroid Build Coastguard Worker for config in proguard_configs: 41*8975f5c5SAndroid Build Coastguard Worker ret.append('# FROM: {}'.format(config)) 42*8975f5c5SAndroid Build Coastguard Worker with open(config) as f: 43*8975f5c5SAndroid Build Coastguard Worker ret.append(f.read()) 44*8975f5c5SAndroid Build Coastguard Worker return '\n'.join(ret) 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Worker 47*8975f5c5SAndroid Build Coastguard Workerdef _AddResources(aar_zip, resource_zips, include_globs): 48*8975f5c5SAndroid Build Coastguard Worker """Adds all resource zips to the given aar_zip. 49*8975f5c5SAndroid Build Coastguard Worker 50*8975f5c5SAndroid Build Coastguard Worker Ensures all res/values/* files have unique names by prefixing them. 51*8975f5c5SAndroid Build Coastguard Worker """ 52*8975f5c5SAndroid Build Coastguard Worker for i, path in enumerate(resource_zips): 53*8975f5c5SAndroid Build Coastguard Worker if include_globs and not build_utils.MatchesGlob(path, include_globs): 54*8975f5c5SAndroid Build Coastguard Worker continue 55*8975f5c5SAndroid Build Coastguard Worker with zipfile.ZipFile(path) as res_zip: 56*8975f5c5SAndroid Build Coastguard Worker for info in res_zip.infolist(): 57*8975f5c5SAndroid Build Coastguard Worker data = res_zip.read(info) 58*8975f5c5SAndroid Build Coastguard Worker dirname, basename = posixpath.split(info.filename) 59*8975f5c5SAndroid Build Coastguard Worker if 'values' in dirname: 60*8975f5c5SAndroid Build Coastguard Worker root, ext = os.path.splitext(basename) 61*8975f5c5SAndroid Build Coastguard Worker basename = '{}_{}{}'.format(root, i, ext) 62*8975f5c5SAndroid Build Coastguard Worker info.filename = posixpath.join(dirname, basename) 63*8975f5c5SAndroid Build Coastguard Worker info.filename = posixpath.join('res', info.filename) 64*8975f5c5SAndroid Build Coastguard Worker aar_zip.writestr(info, data) 65*8975f5c5SAndroid Build Coastguard Worker 66*8975f5c5SAndroid Build Coastguard Worker 67*8975f5c5SAndroid Build Coastguard Workerdef main(args): 68*8975f5c5SAndroid Build Coastguard Worker args = build_utils.ExpandFileArgs(args) 69*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 70*8975f5c5SAndroid Build Coastguard Worker action_helpers.add_depfile_arg(parser) 71*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--output', required=True, help='Path to output aar.') 72*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--jars', required=True, help='GN list of jar inputs.') 73*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--dependencies-res-zips', required=True, 74*8975f5c5SAndroid Build Coastguard Worker help='GN list of resource zips') 75*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--r-text-files', required=True, 76*8975f5c5SAndroid Build Coastguard Worker help='GN list of R.txt files to merge') 77*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--proguard-configs', required=True, 78*8975f5c5SAndroid Build Coastguard Worker help='GN list of ProGuard flag files to merge.') 79*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 80*8975f5c5SAndroid Build Coastguard Worker '--android-manifest', 81*8975f5c5SAndroid Build Coastguard Worker help='Path to AndroidManifest.xml to include.', 82*8975f5c5SAndroid Build Coastguard Worker default=os.path.join(_ANDROID_BUILD_DIR, 'AndroidManifest.xml')) 83*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--native-libraries', default='', 84*8975f5c5SAndroid Build Coastguard Worker help='GN list of native libraries. If non-empty then ' 85*8975f5c5SAndroid Build Coastguard Worker 'ABI must be specified.') 86*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--abi', 87*8975f5c5SAndroid Build Coastguard Worker help='ABI (e.g. armeabi-v7a) for native libraries.') 88*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 89*8975f5c5SAndroid Build Coastguard Worker '--jar-excluded-globs', 90*8975f5c5SAndroid Build Coastguard Worker help='GN-list of globs for paths to exclude in jar.') 91*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 92*8975f5c5SAndroid Build Coastguard Worker '--jar-included-globs', 93*8975f5c5SAndroid Build Coastguard Worker help='GN-list of globs for paths to include in jar.') 94*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 95*8975f5c5SAndroid Build Coastguard Worker '--resource-included-globs', 96*8975f5c5SAndroid Build Coastguard Worker help='GN-list of globs for paths to include in R.txt and resources zips.') 97*8975f5c5SAndroid Build Coastguard Worker 98*8975f5c5SAndroid Build Coastguard Worker options = parser.parse_args(args) 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard Worker if options.native_libraries and not options.abi: 101*8975f5c5SAndroid Build Coastguard Worker parser.error('You must provide --abi if you have native libs') 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker options.jars = action_helpers.parse_gn_list(options.jars) 104*8975f5c5SAndroid Build Coastguard Worker options.dependencies_res_zips = action_helpers.parse_gn_list( 105*8975f5c5SAndroid Build Coastguard Worker options.dependencies_res_zips) 106*8975f5c5SAndroid Build Coastguard Worker options.r_text_files = action_helpers.parse_gn_list(options.r_text_files) 107*8975f5c5SAndroid Build Coastguard Worker options.proguard_configs = action_helpers.parse_gn_list( 108*8975f5c5SAndroid Build Coastguard Worker options.proguard_configs) 109*8975f5c5SAndroid Build Coastguard Worker options.native_libraries = action_helpers.parse_gn_list( 110*8975f5c5SAndroid Build Coastguard Worker options.native_libraries) 111*8975f5c5SAndroid Build Coastguard Worker options.jar_excluded_globs = action_helpers.parse_gn_list( 112*8975f5c5SAndroid Build Coastguard Worker options.jar_excluded_globs) 113*8975f5c5SAndroid Build Coastguard Worker options.jar_included_globs = action_helpers.parse_gn_list( 114*8975f5c5SAndroid Build Coastguard Worker options.jar_included_globs) 115*8975f5c5SAndroid Build Coastguard Worker options.resource_included_globs = action_helpers.parse_gn_list( 116*8975f5c5SAndroid Build Coastguard Worker options.resource_included_globs) 117*8975f5c5SAndroid Build Coastguard Worker 118*8975f5c5SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile(delete=False) as staging_file: 119*8975f5c5SAndroid Build Coastguard Worker try: 120*8975f5c5SAndroid Build Coastguard Worker with zipfile.ZipFile(staging_file.name, 'w') as z: 121*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 122*8975f5c5SAndroid Build Coastguard Worker 'AndroidManifest.xml', 123*8975f5c5SAndroid Build Coastguard Worker src_path=options.android_manifest) 124*8975f5c5SAndroid Build Coastguard Worker 125*8975f5c5SAndroid Build Coastguard Worker path_transform = filter_zip.CreatePathTransform( 126*8975f5c5SAndroid Build Coastguard Worker options.jar_excluded_globs, options.jar_included_globs) 127*8975f5c5SAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as jar_file: 128*8975f5c5SAndroid Build Coastguard Worker zip_helpers.merge_zips(jar_file.name, 129*8975f5c5SAndroid Build Coastguard Worker options.jars, 130*8975f5c5SAndroid Build Coastguard Worker path_transform=path_transform) 131*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 132*8975f5c5SAndroid Build Coastguard Worker 'classes.jar', 133*8975f5c5SAndroid Build Coastguard Worker src_path=jar_file.name) 134*8975f5c5SAndroid Build Coastguard Worker 135*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 136*8975f5c5SAndroid Build Coastguard Worker 'R.txt', 137*8975f5c5SAndroid Build Coastguard Worker data=_MergeRTxt( 138*8975f5c5SAndroid Build Coastguard Worker options.r_text_files, 139*8975f5c5SAndroid Build Coastguard Worker options.resource_included_globs)) 140*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 'public.txt', data='') 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker if options.proguard_configs: 143*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 144*8975f5c5SAndroid Build Coastguard Worker 'proguard.txt', 145*8975f5c5SAndroid Build Coastguard Worker data=_MergeProguardConfigs( 146*8975f5c5SAndroid Build Coastguard Worker options.proguard_configs)) 147*8975f5c5SAndroid Build Coastguard Worker 148*8975f5c5SAndroid Build Coastguard Worker _AddResources(z, options.dependencies_res_zips, 149*8975f5c5SAndroid Build Coastguard Worker options.resource_included_globs) 150*8975f5c5SAndroid Build Coastguard Worker 151*8975f5c5SAndroid Build Coastguard Worker for native_library in options.native_libraries: 152*8975f5c5SAndroid Build Coastguard Worker libname = os.path.basename(native_library) 153*8975f5c5SAndroid Build Coastguard Worker zip_helpers.add_to_zip_hermetic(z, 154*8975f5c5SAndroid Build Coastguard Worker os.path.join('jni', options.abi, 155*8975f5c5SAndroid Build Coastguard Worker libname), 156*8975f5c5SAndroid Build Coastguard Worker src_path=native_library) 157*8975f5c5SAndroid Build Coastguard Worker except: 158*8975f5c5SAndroid Build Coastguard Worker os.unlink(staging_file.name) 159*8975f5c5SAndroid Build Coastguard Worker raise 160*8975f5c5SAndroid Build Coastguard Worker shutil.move(staging_file.name, options.output) 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker if options.depfile: 163*8975f5c5SAndroid Build Coastguard Worker all_inputs = (options.jars + options.dependencies_res_zips + 164*8975f5c5SAndroid Build Coastguard Worker options.r_text_files + options.proguard_configs) 165*8975f5c5SAndroid Build Coastguard Worker action_helpers.write_depfile(options.depfile, options.output, all_inputs) 166*8975f5c5SAndroid Build Coastguard Worker 167*8975f5c5SAndroid Build Coastguard Worker 168*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 169*8975f5c5SAndroid Build Coastguard Worker main(sys.argv[1:]) 170