blob: cc56abda14bf03ea7cf1b388b4350c17c308ab7f [file] [log] [blame]
sakala4a75382017-01-24 01:25:50 -08001#!/usr/bin/env python
2
3# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS. All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
10
11"""Script to generate libwebrtc.aar for distribution.
12
13The script has to be run from the root src folder.
Henrik Kjellander90fd7d82017-05-09 08:30:10 +020014./tools_webrtc/android/build_aar.py
sakala4a75382017-01-24 01:25:50 -080015
16.aar-file is just a zip-archive containing the files of the library. The file
17structure generated by this script looks like this:
18 - AndroidManifest.xml
19 - classes.jar
20 - libs/
21 - armeabi-v7a/
22 - libjingle_peerconnection_so.so
23 - x86/
24 - libjingle_peerconnection_so.so
25"""
26
27import argparse
28import logging
29import os
30import shutil
31import subprocess
32import sys
33import tempfile
34import zipfile
35
36
sakal67e414c2017-09-05 00:16:15 -070037SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
sakal423f1062017-04-07 05:10:15 -070038DEFAULT_ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
sakala4a75382017-01-24 01:25:50 -080039NEEDED_SO_FILES = ['libjingle_peerconnection_so.so']
40JAR_FILE = 'lib.java/webrtc/sdk/android/libwebrtc.jar'
41MANIFEST_FILE = 'webrtc/sdk/android/AndroidManifest.xml'
42TARGETS = [
43 'webrtc/sdk/android:libwebrtc',
44 'webrtc/sdk/android:libjingle_peerconnection_so',
45]
46
sakal67e414c2017-09-05 00:16:15 -070047sys.path.append(os.path.join(SCRIPT_DIR, '..', 'libs'))
48from generate_licenses import LicenseBuilder
49
sakala4a75382017-01-24 01:25:50 -080050
51def _ParseArgs():
52 parser = argparse.ArgumentParser(description='libwebrtc.aar generator.')
korniltsev.anatoly0b510a92017-09-05 08:12:30 -070053 parser.add_argument('--build-dir',
54 help='Build dir. By default will create and use temporary dir.')
sakala4a75382017-01-24 01:25:50 -080055 parser.add_argument('--output', default='libwebrtc.aar',
56 help='Output file of the script.')
kjellander6b3fcfd2017-02-07 01:11:06 -080057 parser.add_argument('--arch', default=DEFAULT_ARCHS, nargs='*',
58 help='Architectures to build. Defaults to %(default)s.')
sakala4a75382017-01-24 01:25:50 -080059 parser.add_argument('--use-goma', action='store_true', default=False,
60 help='Use goma.')
61 parser.add_argument('--verbose', action='store_true', default=False,
62 help='Debug logging.')
kjellander6b3fcfd2017-02-07 01:11:06 -080063 parser.add_argument('--extra-gn-args', default=[], nargs='*',
64 help='Additional GN args to be used during Ninja generation.')
sakala4a75382017-01-24 01:25:50 -080065 return parser.parse_args()
66
67
68def _RunGN(args):
69 cmd = ['gn']
70 cmd.extend(args)
71 logging.debug('Running: %r', cmd)
72 subprocess.check_call(cmd)
73
74
75def _RunNinja(output_directory, args):
76 cmd = ['ninja', '-C', output_directory]
77 cmd.extend(args)
78 logging.debug('Running: %r', cmd)
79 subprocess.check_call(cmd)
80
81
82def _EncodeForGN(value):
83 """Encodes value as a GN literal."""
84 if type(value) is str:
85 return '"' + value + '"'
86 elif type(value) is bool:
87 return repr(value).lower()
88 else:
89 return repr(value)
90
91
korniltsev.anatoly0b510a92017-09-05 08:12:30 -070092def _GetOutputDirectory(build_dir, arch):
sakala4a75382017-01-24 01:25:50 -080093 """Returns the GN output directory for the target architecture."""
korniltsev.anatoly0b510a92017-09-05 08:12:30 -070094 return os.path.join(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -080095
96
97def _GetTargetCpu(arch):
98 """Returns target_cpu for the GN build with the given architecture."""
99 if arch in ['armeabi', 'armeabi-v7a']:
100 return 'arm'
sakal423f1062017-04-07 05:10:15 -0700101 elif arch == 'arm64-v8a':
102 return 'arm64'
sakala4a75382017-01-24 01:25:50 -0800103 elif arch == 'x86':
104 return 'x86'
sakal423f1062017-04-07 05:10:15 -0700105 elif arch == 'x86_64':
106 return 'x64'
sakala4a75382017-01-24 01:25:50 -0800107 else:
108 raise Exception('Unknown arch: ' + arch)
109
110
111def _GetArmVersion(arch):
112 """Returns arm_version for the GN build with the given architecture."""
113 if arch == 'armeabi':
114 return 6
115 elif arch == 'armeabi-v7a':
116 return 7
sakal423f1062017-04-07 05:10:15 -0700117 elif arch in ['arm64-v8a', 'x86', 'x86_64']:
sakala4a75382017-01-24 01:25:50 -0800118 return None
119 else:
120 raise Exception('Unknown arch: ' + arch)
121
122
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700123def Build(build_dir, arch, use_goma, extra_gn_args):
sakala4a75382017-01-24 01:25:50 -0800124 """Generates target architecture using GN and builds it using ninja."""
125 logging.info('Building: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700126 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800127 gn_args = {
128 'target_os': 'android',
129 'is_debug': False,
130 'is_component_build': False,
sakal67e414c2017-09-05 00:16:15 -0700131 'rtc_include_tests': False,
sakala4a75382017-01-24 01:25:50 -0800132 'target_cpu': _GetTargetCpu(arch),
133 'use_goma': use_goma
134 }
135 arm_version = _GetArmVersion(arch)
136 if arm_version:
137 gn_args['arm_version'] = arm_version
138 gn_args_str = '--args=' + ' '.join([
kjellander6b3fcfd2017-02-07 01:11:06 -0800139 k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800140
141 _RunGN(['gen', output_directory, gn_args_str])
142
sakal67e414c2017-09-05 00:16:15 -0700143 ninja_args = TARGETS[:]
sakala4a75382017-01-24 01:25:50 -0800144 if use_goma:
sakala53d4e72017-02-07 06:19:20 -0800145 ninja_args.extend(['-j', '200'])
sakala4a75382017-01-24 01:25:50 -0800146 _RunNinja(output_directory, ninja_args)
147
148
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700149def CollectCommon(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800150 """Collects architecture independent files into the .aar-archive."""
151 logging.info('Collecting common files.')
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700152 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800153 aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml')
154 aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
155
156
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700157def Collect(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800158 """Collects architecture specific files into the .aar-archive."""
159 logging.info('Collecting: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700160 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800161
162 abi_dir = os.path.join('jni', arch)
163 for so_file in NEEDED_SO_FILES:
164 aar_file.write(os.path.join(output_directory, so_file),
165 os.path.join(abi_dir, so_file))
166
167
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700168def GenerateLicenses(output_dir, build_dir, archs):
sakal67e414c2017-09-05 00:16:15 -0700169 builder = LicenseBuilder(
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700170 [_GetOutputDirectory(build_dir, arch) for arch in archs], TARGETS)
sakal67e414c2017-09-05 00:16:15 -0700171 builder.GenerateLicenseText(output_dir)
172
173
sakala4a75382017-01-24 01:25:50 -0800174def main():
175 args = _ParseArgs()
sakala4a75382017-01-24 01:25:50 -0800176 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
177
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700178 build_dir = args.build_dir if args.build_dir else tempfile.mkdtemp()
sakala4a75382017-01-24 01:25:50 -0800179
180 for arch in args.arch:
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700181 Build(build_dir, arch, args.use_goma, args.extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800182
183 with zipfile.ZipFile(args.output, 'w') as aar_file:
184 # Architecture doesn't matter here, arbitrarily using the first one.
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700185 CollectCommon(aar_file, build_dir, args.arch[0])
sakala4a75382017-01-24 01:25:50 -0800186 for arch in args.arch:
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700187 Collect(aar_file, build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800188
sakal67e414c2017-09-05 00:16:15 -0700189 license_dir = os.path.dirname(os.path.realpath(args.output))
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700190 GenerateLicenses(license_dir, build_dir, args.arch)
sakal67e414c2017-09-05 00:16:15 -0700191
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700192 if not args.build_dir:
193 shutil.rmtree(build_dir, True)
sakala4a75382017-01-24 01:25:50 -0800194
195
196if __name__ == '__main__':
197 sys.exit(main())