1*d9f75844SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*d9f75844SAndroid Build Coastguard Worker 3*d9f75844SAndroid Build Coastguard Worker# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 4*d9f75844SAndroid Build Coastguard Worker# 5*d9f75844SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license 6*d9f75844SAndroid Build Coastguard Worker# that can be found in the LICENSE file in the root of the source 7*d9f75844SAndroid Build Coastguard Worker# tree. An additional intellectual property rights grant can be found 8*d9f75844SAndroid Build Coastguard Worker# in the file PATENTS. All contributing project authors may 9*d9f75844SAndroid Build Coastguard Worker# be found in the AUTHORS file in the root of the source tree. 10*d9f75844SAndroid Build Coastguard Worker"""Script to generate libwebrtc.aar for distribution. 11*d9f75844SAndroid Build Coastguard Worker 12*d9f75844SAndroid Build Coastguard WorkerThe script has to be run from the root src folder. 13*d9f75844SAndroid Build Coastguard Worker./tools_webrtc/android/build_aar.py 14*d9f75844SAndroid Build Coastguard Worker 15*d9f75844SAndroid Build Coastguard Worker.aar-file is just a zip-archive containing the files of the library. The file 16*d9f75844SAndroid Build Coastguard Workerstructure generated by this script looks like this: 17*d9f75844SAndroid Build Coastguard Worker - AndroidManifest.xml 18*d9f75844SAndroid Build Coastguard Worker - classes.jar 19*d9f75844SAndroid Build Coastguard Worker - libs/ 20*d9f75844SAndroid Build Coastguard Worker - armeabi-v7a/ 21*d9f75844SAndroid Build Coastguard Worker - libjingle_peerconnection_so.so 22*d9f75844SAndroid Build Coastguard Worker - x86/ 23*d9f75844SAndroid Build Coastguard Worker - libjingle_peerconnection_so.so 24*d9f75844SAndroid Build Coastguard Worker""" 25*d9f75844SAndroid Build Coastguard Worker 26*d9f75844SAndroid Build Coastguard Workerimport argparse 27*d9f75844SAndroid Build Coastguard Workerimport logging 28*d9f75844SAndroid Build Coastguard Workerimport os 29*d9f75844SAndroid Build Coastguard Workerimport shutil 30*d9f75844SAndroid Build Coastguard Workerimport subprocess 31*d9f75844SAndroid Build Coastguard Workerimport sys 32*d9f75844SAndroid Build Coastguard Workerimport tempfile 33*d9f75844SAndroid Build Coastguard Workerimport zipfile 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard WorkerSCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0])) 36*d9f75844SAndroid Build Coastguard WorkerSRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir)) 37*d9f75844SAndroid Build Coastguard WorkerDEFAULT_ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'] 38*d9f75844SAndroid Build Coastguard WorkerNEEDED_SO_FILES = ['libjingle_peerconnection_so.so'] 39*d9f75844SAndroid Build Coastguard WorkerJAR_FILE = 'lib.java/sdk/android/libwebrtc.jar' 40*d9f75844SAndroid Build Coastguard WorkerMANIFEST_FILE = 'sdk/android/AndroidManifest.xml' 41*d9f75844SAndroid Build Coastguard WorkerTARGETS = [ 42*d9f75844SAndroid Build Coastguard Worker 'sdk/android:libwebrtc', 43*d9f75844SAndroid Build Coastguard Worker 'sdk/android:libjingle_peerconnection_so', 44*d9f75844SAndroid Build Coastguard Worker] 45*d9f75844SAndroid Build Coastguard Worker 46*d9f75844SAndroid Build Coastguard Workersys.path.append(os.path.join(SCRIPT_DIR, '..', 'libs')) 47*d9f75844SAndroid Build Coastguard Workerfrom generate_licenses import LicenseBuilder 48*d9f75844SAndroid Build Coastguard Worker 49*d9f75844SAndroid Build Coastguard Workersys.path.append(os.path.join(SRC_DIR, 'build')) 50*d9f75844SAndroid Build Coastguard Workerimport find_depot_tools 51*d9f75844SAndroid Build Coastguard Worker 52*d9f75844SAndroid Build Coastguard Worker 53*d9f75844SAndroid Build Coastguard Workerdef _ParseArgs(): 54*d9f75844SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description='libwebrtc.aar generator.') 55*d9f75844SAndroid Build Coastguard Worker parser.add_argument( 56*d9f75844SAndroid Build Coastguard Worker '--build-dir', 57*d9f75844SAndroid Build Coastguard Worker type=os.path.abspath, 58*d9f75844SAndroid Build Coastguard Worker help='Build dir. By default will create and use temporary dir.') 59*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--output', 60*d9f75844SAndroid Build Coastguard Worker default='libwebrtc.aar', 61*d9f75844SAndroid Build Coastguard Worker type=os.path.abspath, 62*d9f75844SAndroid Build Coastguard Worker help='Output file of the script.') 63*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--arch', 64*d9f75844SAndroid Build Coastguard Worker default=DEFAULT_ARCHS, 65*d9f75844SAndroid Build Coastguard Worker nargs='*', 66*d9f75844SAndroid Build Coastguard Worker help='Architectures to build. Defaults to %(default)s.') 67*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--use-goma', 68*d9f75844SAndroid Build Coastguard Worker action='store_true', 69*d9f75844SAndroid Build Coastguard Worker default=False, 70*d9f75844SAndroid Build Coastguard Worker help='Use goma.') 71*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--use-remoteexec', 72*d9f75844SAndroid Build Coastguard Worker action='store_true', 73*d9f75844SAndroid Build Coastguard Worker default=False, 74*d9f75844SAndroid Build Coastguard Worker help='Use RBE.') 75*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--use-unstripped-libs', 76*d9f75844SAndroid Build Coastguard Worker action='store_true', 77*d9f75844SAndroid Build Coastguard Worker default=False, 78*d9f75844SAndroid Build Coastguard Worker help='Use unstripped .so files within libwebrtc.aar') 79*d9f75844SAndroid Build Coastguard Worker parser.add_argument('--verbose', 80*d9f75844SAndroid Build Coastguard Worker action='store_true', 81*d9f75844SAndroid Build Coastguard Worker default=False, 82*d9f75844SAndroid Build Coastguard Worker help='Debug logging.') 83*d9f75844SAndroid Build Coastguard Worker parser.add_argument( 84*d9f75844SAndroid Build Coastguard Worker '--extra-gn-args', 85*d9f75844SAndroid Build Coastguard Worker default=[], 86*d9f75844SAndroid Build Coastguard Worker nargs='*', 87*d9f75844SAndroid Build Coastguard Worker help="""Additional GN arguments to be used during Ninja generation. 88*d9f75844SAndroid Build Coastguard Worker These are passed to gn inside `--args` switch and 89*d9f75844SAndroid Build Coastguard Worker applied after any other arguments and will 90*d9f75844SAndroid Build Coastguard Worker override any values defined by the script. 91*d9f75844SAndroid Build Coastguard Worker Example of building debug aar file: 92*d9f75844SAndroid Build Coastguard Worker build_aar.py --extra-gn-args='is_debug=true'""") 93*d9f75844SAndroid Build Coastguard Worker parser.add_argument( 94*d9f75844SAndroid Build Coastguard Worker '--extra-ninja-switches', 95*d9f75844SAndroid Build Coastguard Worker default=[], 96*d9f75844SAndroid Build Coastguard Worker nargs='*', 97*d9f75844SAndroid Build Coastguard Worker help="""Additional Ninja switches to be used during compilation. 98*d9f75844SAndroid Build Coastguard Worker These are applied after any other Ninja switches. 99*d9f75844SAndroid Build Coastguard Worker Example of enabling verbose Ninja output: 100*d9f75844SAndroid Build Coastguard Worker build_aar.py --extra-ninja-switches='-v'""") 101*d9f75844SAndroid Build Coastguard Worker parser.add_argument( 102*d9f75844SAndroid Build Coastguard Worker '--extra-gn-switches', 103*d9f75844SAndroid Build Coastguard Worker default=[], 104*d9f75844SAndroid Build Coastguard Worker nargs='*', 105*d9f75844SAndroid Build Coastguard Worker help="""Additional GN switches to be used during compilation. 106*d9f75844SAndroid Build Coastguard Worker These are applied after any other GN switches. 107*d9f75844SAndroid Build Coastguard Worker Example of enabling verbose GN output: 108*d9f75844SAndroid Build Coastguard Worker build_aar.py --extra-gn-switches='-v'""") 109*d9f75844SAndroid Build Coastguard Worker return parser.parse_args() 110*d9f75844SAndroid Build Coastguard Worker 111*d9f75844SAndroid Build Coastguard Worker 112*d9f75844SAndroid Build Coastguard Workerdef _RunGN(args): 113*d9f75844SAndroid Build Coastguard Worker cmd = [ 114*d9f75844SAndroid Build Coastguard Worker sys.executable, 115*d9f75844SAndroid Build Coastguard Worker os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py') 116*d9f75844SAndroid Build Coastguard Worker ] 117*d9f75844SAndroid Build Coastguard Worker cmd.extend(args) 118*d9f75844SAndroid Build Coastguard Worker logging.debug('Running: %r', cmd) 119*d9f75844SAndroid Build Coastguard Worker subprocess.check_call(cmd) 120*d9f75844SAndroid Build Coastguard Worker 121*d9f75844SAndroid Build Coastguard Worker 122*d9f75844SAndroid Build Coastguard Workerdef _RunNinja(output_directory, args): 123*d9f75844SAndroid Build Coastguard Worker cmd = [ 124*d9f75844SAndroid Build Coastguard Worker os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'), '-C', 125*d9f75844SAndroid Build Coastguard Worker output_directory 126*d9f75844SAndroid Build Coastguard Worker ] 127*d9f75844SAndroid Build Coastguard Worker cmd.extend(args) 128*d9f75844SAndroid Build Coastguard Worker logging.debug('Running: %r', cmd) 129*d9f75844SAndroid Build Coastguard Worker subprocess.check_call(cmd) 130*d9f75844SAndroid Build Coastguard Worker 131*d9f75844SAndroid Build Coastguard Worker 132*d9f75844SAndroid Build Coastguard Workerdef _EncodeForGN(value): 133*d9f75844SAndroid Build Coastguard Worker """Encodes value as a GN literal.""" 134*d9f75844SAndroid Build Coastguard Worker if isinstance(value, str): 135*d9f75844SAndroid Build Coastguard Worker return '"' + value + '"' 136*d9f75844SAndroid Build Coastguard Worker if isinstance(value, bool): 137*d9f75844SAndroid Build Coastguard Worker return repr(value).lower() 138*d9f75844SAndroid Build Coastguard Worker return repr(value) 139*d9f75844SAndroid Build Coastguard Worker 140*d9f75844SAndroid Build Coastguard Worker 141*d9f75844SAndroid Build Coastguard Workerdef _GetOutputDirectory(build_dir, arch): 142*d9f75844SAndroid Build Coastguard Worker """Returns the GN output directory for the target architecture.""" 143*d9f75844SAndroid Build Coastguard Worker return os.path.join(build_dir, arch) 144*d9f75844SAndroid Build Coastguard Worker 145*d9f75844SAndroid Build Coastguard Worker 146*d9f75844SAndroid Build Coastguard Workerdef _GetTargetCpu(arch): 147*d9f75844SAndroid Build Coastguard Worker """Returns target_cpu for the GN build with the given architecture.""" 148*d9f75844SAndroid Build Coastguard Worker if arch in ['armeabi', 'armeabi-v7a']: 149*d9f75844SAndroid Build Coastguard Worker return 'arm' 150*d9f75844SAndroid Build Coastguard Worker if arch == 'arm64-v8a': 151*d9f75844SAndroid Build Coastguard Worker return 'arm64' 152*d9f75844SAndroid Build Coastguard Worker if arch == 'x86': 153*d9f75844SAndroid Build Coastguard Worker return 'x86' 154*d9f75844SAndroid Build Coastguard Worker if arch == 'x86_64': 155*d9f75844SAndroid Build Coastguard Worker return 'x64' 156*d9f75844SAndroid Build Coastguard Worker raise Exception('Unknown arch: ' + arch) 157*d9f75844SAndroid Build Coastguard Worker 158*d9f75844SAndroid Build Coastguard Worker 159*d9f75844SAndroid Build Coastguard Workerdef _GetArmVersion(arch): 160*d9f75844SAndroid Build Coastguard Worker """Returns arm_version for the GN build with the given architecture.""" 161*d9f75844SAndroid Build Coastguard Worker if arch == 'armeabi': 162*d9f75844SAndroid Build Coastguard Worker return 6 163*d9f75844SAndroid Build Coastguard Worker if arch == 'armeabi-v7a': 164*d9f75844SAndroid Build Coastguard Worker return 7 165*d9f75844SAndroid Build Coastguard Worker if arch in ['arm64-v8a', 'x86', 'x86_64']: 166*d9f75844SAndroid Build Coastguard Worker return None 167*d9f75844SAndroid Build Coastguard Worker raise Exception('Unknown arch: ' + arch) 168*d9f75844SAndroid Build Coastguard Worker 169*d9f75844SAndroid Build Coastguard Worker 170*d9f75844SAndroid Build Coastguard Workerdef Build(build_dir, arch, use_goma, use_remoteexec, extra_gn_args, 171*d9f75844SAndroid Build Coastguard Worker extra_gn_switches, extra_ninja_switches): 172*d9f75844SAndroid Build Coastguard Worker """Generates target architecture using GN and builds it using ninja.""" 173*d9f75844SAndroid Build Coastguard Worker logging.info('Building: %s', arch) 174*d9f75844SAndroid Build Coastguard Worker output_directory = _GetOutputDirectory(build_dir, arch) 175*d9f75844SAndroid Build Coastguard Worker gn_args = { 176*d9f75844SAndroid Build Coastguard Worker 'target_os': 'android', 177*d9f75844SAndroid Build Coastguard Worker 'is_debug': False, 178*d9f75844SAndroid Build Coastguard Worker 'is_component_build': False, 179*d9f75844SAndroid Build Coastguard Worker 'rtc_include_tests': False, 180*d9f75844SAndroid Build Coastguard Worker 'target_cpu': _GetTargetCpu(arch), 181*d9f75844SAndroid Build Coastguard Worker 'use_goma': use_goma, 182*d9f75844SAndroid Build Coastguard Worker 'use_remoteexec': use_remoteexec, 183*d9f75844SAndroid Build Coastguard Worker } 184*d9f75844SAndroid Build Coastguard Worker arm_version = _GetArmVersion(arch) 185*d9f75844SAndroid Build Coastguard Worker if arm_version: 186*d9f75844SAndroid Build Coastguard Worker gn_args['arm_version'] = arm_version 187*d9f75844SAndroid Build Coastguard Worker gn_args_str = '--args=' + ' '.join( 188*d9f75844SAndroid Build Coastguard Worker [k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args) 189*d9f75844SAndroid Build Coastguard Worker 190*d9f75844SAndroid Build Coastguard Worker gn_args_list = ['gen', output_directory, gn_args_str] 191*d9f75844SAndroid Build Coastguard Worker gn_args_list.extend(extra_gn_switches) 192*d9f75844SAndroid Build Coastguard Worker _RunGN(gn_args_list) 193*d9f75844SAndroid Build Coastguard Worker 194*d9f75844SAndroid Build Coastguard Worker ninja_args = TARGETS[:] 195*d9f75844SAndroid Build Coastguard Worker if use_goma or use_remoteexec: 196*d9f75844SAndroid Build Coastguard Worker ninja_args.extend(['-j', '200']) 197*d9f75844SAndroid Build Coastguard Worker ninja_args.extend(extra_ninja_switches) 198*d9f75844SAndroid Build Coastguard Worker _RunNinja(output_directory, ninja_args) 199*d9f75844SAndroid Build Coastguard Worker 200*d9f75844SAndroid Build Coastguard Worker 201*d9f75844SAndroid Build Coastguard Workerdef CollectCommon(aar_file, build_dir, arch): 202*d9f75844SAndroid Build Coastguard Worker """Collects architecture independent files into the .aar-archive.""" 203*d9f75844SAndroid Build Coastguard Worker logging.info('Collecting common files.') 204*d9f75844SAndroid Build Coastguard Worker output_directory = _GetOutputDirectory(build_dir, arch) 205*d9f75844SAndroid Build Coastguard Worker aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml') 206*d9f75844SAndroid Build Coastguard Worker aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar') 207*d9f75844SAndroid Build Coastguard Worker 208*d9f75844SAndroid Build Coastguard Worker 209*d9f75844SAndroid Build Coastguard Workerdef Collect(aar_file, build_dir, arch, unstripped): 210*d9f75844SAndroid Build Coastguard Worker """Collects architecture specific files into the .aar-archive.""" 211*d9f75844SAndroid Build Coastguard Worker logging.info('Collecting: %s', arch) 212*d9f75844SAndroid Build Coastguard Worker output_directory = _GetOutputDirectory(build_dir, arch) 213*d9f75844SAndroid Build Coastguard Worker 214*d9f75844SAndroid Build Coastguard Worker abi_dir = os.path.join('jni', arch) 215*d9f75844SAndroid Build Coastguard Worker for so_file in NEEDED_SO_FILES: 216*d9f75844SAndroid Build Coastguard Worker source_so_file = os.path.join("lib.unstripped", 217*d9f75844SAndroid Build Coastguard Worker so_file) if unstripped else so_file 218*d9f75844SAndroid Build Coastguard Worker aar_file.write(os.path.join(output_directory, source_so_file), 219*d9f75844SAndroid Build Coastguard Worker os.path.join(abi_dir, so_file)) 220*d9f75844SAndroid Build Coastguard Worker 221*d9f75844SAndroid Build Coastguard Worker 222*d9f75844SAndroid Build Coastguard Workerdef GenerateLicenses(output_dir, build_dir, archs): 223*d9f75844SAndroid Build Coastguard Worker builder = LicenseBuilder( 224*d9f75844SAndroid Build Coastguard Worker [_GetOutputDirectory(build_dir, arch) for arch in archs], TARGETS) 225*d9f75844SAndroid Build Coastguard Worker builder.GenerateLicenseText(output_dir) 226*d9f75844SAndroid Build Coastguard Worker 227*d9f75844SAndroid Build Coastguard Worker 228*d9f75844SAndroid Build Coastguard Workerdef BuildAar(archs, 229*d9f75844SAndroid Build Coastguard Worker output_file, 230*d9f75844SAndroid Build Coastguard Worker use_goma=False, 231*d9f75844SAndroid Build Coastguard Worker use_remoteexec=False, 232*d9f75844SAndroid Build Coastguard Worker extra_gn_args=None, 233*d9f75844SAndroid Build Coastguard Worker ext_build_dir=None, 234*d9f75844SAndroid Build Coastguard Worker extra_gn_switches=None, 235*d9f75844SAndroid Build Coastguard Worker extra_ninja_switches=None, 236*d9f75844SAndroid Build Coastguard Worker unstripped=False): 237*d9f75844SAndroid Build Coastguard Worker extra_gn_args = extra_gn_args or [] 238*d9f75844SAndroid Build Coastguard Worker extra_gn_switches = extra_gn_switches or [] 239*d9f75844SAndroid Build Coastguard Worker extra_ninja_switches = extra_ninja_switches or [] 240*d9f75844SAndroid Build Coastguard Worker build_dir = ext_build_dir if ext_build_dir else tempfile.mkdtemp() 241*d9f75844SAndroid Build Coastguard Worker 242*d9f75844SAndroid Build Coastguard Worker for arch in archs: 243*d9f75844SAndroid Build Coastguard Worker Build(build_dir, arch, use_goma, use_remoteexec, extra_gn_args, 244*d9f75844SAndroid Build Coastguard Worker extra_gn_switches, extra_ninja_switches) 245*d9f75844SAndroid Build Coastguard Worker 246*d9f75844SAndroid Build Coastguard Worker with zipfile.ZipFile(output_file, 'w') as aar_file: 247*d9f75844SAndroid Build Coastguard Worker # Architecture doesn't matter here, arbitrarily using the first one. 248*d9f75844SAndroid Build Coastguard Worker CollectCommon(aar_file, build_dir, archs[0]) 249*d9f75844SAndroid Build Coastguard Worker for arch in archs: 250*d9f75844SAndroid Build Coastguard Worker Collect(aar_file, build_dir, arch, unstripped) 251*d9f75844SAndroid Build Coastguard Worker 252*d9f75844SAndroid Build Coastguard Worker license_dir = os.path.dirname(os.path.realpath(output_file)) 253*d9f75844SAndroid Build Coastguard Worker GenerateLicenses(license_dir, build_dir, archs) 254*d9f75844SAndroid Build Coastguard Worker 255*d9f75844SAndroid Build Coastguard Worker if not ext_build_dir: 256*d9f75844SAndroid Build Coastguard Worker shutil.rmtree(build_dir, True) 257*d9f75844SAndroid Build Coastguard Worker 258*d9f75844SAndroid Build Coastguard Worker 259*d9f75844SAndroid Build Coastguard Workerdef main(): 260*d9f75844SAndroid Build Coastguard Worker args = _ParseArgs() 261*d9f75844SAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) 262*d9f75844SAndroid Build Coastguard Worker 263*d9f75844SAndroid Build Coastguard Worker BuildAar(args.arch, args.output, args.use_goma, args.use_remoteexec, 264*d9f75844SAndroid Build Coastguard Worker args.extra_gn_args, args.build_dir, args.extra_gn_switches, 265*d9f75844SAndroid Build Coastguard Worker args.extra_ninja_switches, args.use_unstripped_libs) 266*d9f75844SAndroid Build Coastguard Worker 267*d9f75844SAndroid Build Coastguard Worker 268*d9f75844SAndroid Build Coastguard Workerif __name__ == '__main__': 269*d9f75844SAndroid Build Coastguard Worker sys.exit(main()) 270