Chromium Code Reviews| Index: webrtc/build/android/build_aar.py |
| diff --git a/webrtc/build/android/build_aar.py b/webrtc/build/android/build_aar.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..bd2efb4ca0a397ea25dc351381f1877c143c7db9 |
| --- /dev/null |
| +++ b/webrtc/build/android/build_aar.py |
| @@ -0,0 +1,177 @@ |
| +#!/usr/bin/env python |
| + |
| +# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| +# |
| +# Use of this source code is governed by a BSD-style license |
| +# that can be found in the LICENSE file in the root of the source |
| +# tree. An additional intellectual property rights grant can be found |
| +# in the file PATENTS. All contributing project authors may |
| +# be found in the AUTHORS file in the root of the source tree. |
| + |
| +"""Script to generate libwebrtc.aar for distribution. |
| + |
| +The script has to be run from the root src folder. |
| +./webrtc/build/android/build_aar.py |
| + |
| +.aar-file is just a zip-archive containing the files of the library. The file |
| +structure generated by this script looks like this: |
| + - AndroidManifest.xml |
| + - classes.jar |
| + - libs/ |
| + - armeabi-v7a/ |
| + - libjingle_peerconnection_so.so |
| + - x86/ |
| + - libjingle_peerconnection_so.so |
| +""" |
| + |
| +import argparse |
| +import logging |
| +import os |
| +import shutil |
| +import subprocess |
| +import sys |
| +import tempfile |
| +import zipfile |
| + |
| + |
| +DEFAULT_ARCHS = ['armeabi-v7a', 'x86'] |
|
kjellander_webrtc
2017/01/24 08:59:13
Should we not build more configs by default? Isn't
sakal
2017/01/24 09:04:38
I believe arm64 processors are able to run armeabi
|
| +NEEDED_SO_FILES = ['libjingle_peerconnection_so.so'] |
| +JAR_FILE = 'lib.java/webrtc/sdk/android/libwebrtc.jar' |
| +MANIFEST_FILE = 'webrtc/sdk/android/AndroidManifest.xml' |
| +TARGETS = [ |
| + 'webrtc/sdk/android:libwebrtc', |
| + 'webrtc/sdk/android:libjingle_peerconnection_so', |
| +] |
| + |
| + |
| +def _ParseArgs(): |
| + parser = argparse.ArgumentParser(description='libwebrtc.aar generator.') |
| + parser.add_argument('--output', default='libwebrtc.aar', |
| + help='Output file of the script.') |
| + parser.add_argument('--arch', action='append', default=[], |
| + help='Architectures to build. Defaults to ' + str(DEFAULT_ARCHS)) |
| + parser.add_argument('--use-goma', action='store_true', default=False, |
| + help='Use goma.') |
| + parser.add_argument('--verbose', action='store_true', default=False, |
| + help='Debug logging.') |
| + return parser.parse_args() |
| + |
| + |
| +def _RunGN(args): |
| + cmd = ['gn'] |
| + cmd.extend(args) |
| + logging.debug('Running: %r', cmd) |
| + subprocess.check_call(cmd) |
| + |
| + |
| +def _RunNinja(output_directory, args): |
| + cmd = ['ninja', '-C', output_directory] |
| + cmd.extend(args) |
| + logging.debug('Running: %r', cmd) |
| + subprocess.check_call(cmd) |
| + |
| + |
| +def _EncodeForGN(value): |
| + """Encodes value as a GN literal.""" |
| + if type(value) is str: |
| + return '"' + value + '"' |
| + elif type(value) is bool: |
| + return repr(value).lower() |
| + else: |
| + return repr(value) |
| + |
| + |
| +def _GetOutputDirectory(tmp_dir, arch): |
| + """Returns the GN output directory for the target architecture.""" |
| + return os.path.join(tmp_dir, arch) |
| + |
| + |
| +def _GetTargetCpu(arch): |
| + """Returns target_cpu for the GN build with the given architecture.""" |
| + if arch in ['armeabi', 'armeabi-v7a']: |
| + return 'arm' |
| + elif arch == 'x86': |
| + return 'x86' |
| + else: |
| + raise Exception('Unknown arch: ' + arch) |
| + |
| + |
| +def _GetArmVersion(arch): |
| + """Returns arm_version for the GN build with the given architecture.""" |
| + if arch == 'armeabi': |
| + return 6 |
| + elif arch == 'armeabi-v7a': |
| + return 7 |
| + elif arch == 'x86': |
| + return None |
| + else: |
| + raise Exception('Unknown arch: ' + arch) |
| + |
| + |
| +def Build(tmp_dir, arch, use_goma): |
| + """Generates target architecture using GN and builds it using ninja.""" |
| + logging.info('Building: %s', arch) |
| + output_directory = _GetOutputDirectory(tmp_dir, arch) |
| + gn_args = { |
| + 'target_os': 'android', |
| + 'is_debug': False, |
| + 'is_component_build': False, |
| + 'target_cpu': _GetTargetCpu(arch), |
| + 'use_goma': use_goma |
| + } |
| + arm_version = _GetArmVersion(arch) |
| + if arm_version: |
| + gn_args['arm_version'] = arm_version |
| + gn_args_str = '--args=' + ' '.join([ |
| + k + '=' + _EncodeForGN(v) for k, v in gn_args.items()]) |
| + |
| + _RunGN(['gen', output_directory, gn_args_str]) |
| + |
| + ninja_args = TARGETS |
| + if use_goma: |
| + ninja_args.extend(['-j', '1024']) |
| + _RunNinja(output_directory, ninja_args) |
| + |
| + |
| +def CollectCommon(aar_file, tmp_dir, arch): |
| + """Collects architecture independent files into the .aar-archive.""" |
| + logging.info('Collecting common files.') |
| + output_directory = _GetOutputDirectory(tmp_dir, arch) |
| + aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml') |
| + aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar') |
| + |
| + |
| +def Collect(aar_file, tmp_dir, arch): |
| + """Collects architecture specific files into the .aar-archive.""" |
| + logging.info('Collecting: %s', arch) |
| + output_directory = _GetOutputDirectory(tmp_dir, arch) |
| + |
| + abi_dir = os.path.join('jni', arch) |
| + for so_file in NEEDED_SO_FILES: |
| + aar_file.write(os.path.join(output_directory, so_file), |
| + os.path.join(abi_dir, so_file)) |
| + |
| + |
| +def main(): |
| + args = _ParseArgs() |
| + if not args.arch: |
| + args.arch = DEFAULT_ARCHS |
| + |
| + logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) |
| + |
| + tmp_dir = tempfile.mkdtemp() |
| + |
| + for arch in args.arch: |
| + Build(tmp_dir, arch, args.use_goma) |
| + |
| + with zipfile.ZipFile(args.output, 'w') as aar_file: |
| + # Architecture doesn't matter here, arbitrarily using the first one. |
| + CollectCommon(aar_file, tmp_dir, args.arch[0]) |
| + for arch in args.arch: |
| + Collect(aar_file, tmp_dir, arch) |
| + |
| + shutil.rmtree(tmp_dir, True) |
| + |
| + |
| +if __name__ == '__main__': |
| + sys.exit(main()) |