blob: 81e545d11c79ed1713c3eeffe9abe1e762c8482f [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]))
Henrik Kjellanderec57e052017-10-17 21:36:01 +020038SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
sakal423f1062017-04-07 05:10:15 -070039DEFAULT_ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
sakala4a75382017-01-24 01:25:50 -080040NEEDED_SO_FILES = ['libjingle_peerconnection_so.so']
Henrik Kjellander03ec4f82017-09-27 16:07:40 +020041JAR_FILE = 'lib.java/sdk/android/libwebrtc.jar'
42MANIFEST_FILE = 'sdk/android/AndroidManifest.xml'
sakala4a75382017-01-24 01:25:50 -080043TARGETS = [
Henrik Kjellander03ec4f82017-09-27 16:07:40 +020044 'sdk/android:libwebrtc',
45 'sdk/android:libjingle_peerconnection_so',
sakala4a75382017-01-24 01:25:50 -080046]
47
sakal67e414c2017-09-05 00:16:15 -070048sys.path.append(os.path.join(SCRIPT_DIR, '..', 'libs'))
49from generate_licenses import LicenseBuilder
50
Henrik Kjellanderec57e052017-10-17 21:36:01 +020051sys.path.append(os.path.join(SRC_DIR, 'build'))
52import find_depot_tools
53
54
sakala4a75382017-01-24 01:25:50 -080055
56def _ParseArgs():
57 parser = argparse.ArgumentParser(description='libwebrtc.aar generator.')
korniltsev.anatoly0b510a92017-09-05 08:12:30 -070058 parser.add_argument('--build-dir',
59 help='Build dir. By default will create and use temporary dir.')
sakala4a75382017-01-24 01:25:50 -080060 parser.add_argument('--output', default='libwebrtc.aar',
61 help='Output file of the script.')
kjellander6b3fcfd2017-02-07 01:11:06 -080062 parser.add_argument('--arch', default=DEFAULT_ARCHS, nargs='*',
63 help='Architectures to build. Defaults to %(default)s.')
sakala4a75382017-01-24 01:25:50 -080064 parser.add_argument('--use-goma', action='store_true', default=False,
65 help='Use goma.')
66 parser.add_argument('--verbose', action='store_true', default=False,
67 help='Debug logging.')
kjellander6b3fcfd2017-02-07 01:11:06 -080068 parser.add_argument('--extra-gn-args', default=[], nargs='*',
Yura Yaroshevichbe7b88c2018-03-13 13:12:56 +030069 help="""Additional GN arguments to be used during Ninja generation.
Yura Yaroshevichf517f112018-05-24 16:48:02 +030070 These are passed to gn inside `--args` switch and
71 applied after any other arguments and will
72 override any values defined by the script.
73 Example of building debug aar file:
74 build_aar.py --extra-gn-args='is_debug=true'""")
75 parser.add_argument('--extra-ninja-switches', default=[], nargs='*',
76 help="""Additional Ninja switches to be used during compilation.
77 These are applied after any other Ninja switches.
78 Example of enabling verbose Ninja output:
79 build_aar.py --extra-ninja-switches='-v'""")
80 parser.add_argument('--extra-gn-switches', default=[], nargs='*',
81 help="""Additional GN switches to be used during compilation.
82 These are applied after any other GN switches.
83 Example of enabling verbose GN output:
84 build_aar.py --extra-gn-switches='-v'""")
sakala4a75382017-01-24 01:25:50 -080085 return parser.parse_args()
86
87
88def _RunGN(args):
Henrik Kjellanderec57e052017-10-17 21:36:01 +020089 cmd = [sys.executable,
90 os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py')]
sakala4a75382017-01-24 01:25:50 -080091 cmd.extend(args)
92 logging.debug('Running: %r', cmd)
93 subprocess.check_call(cmd)
94
95
96def _RunNinja(output_directory, args):
Henrik Kjellanderec57e052017-10-17 21:36:01 +020097 cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'),
98 '-C', output_directory]
sakala4a75382017-01-24 01:25:50 -080099 cmd.extend(args)
100 logging.debug('Running: %r', cmd)
101 subprocess.check_call(cmd)
102
103
104def _EncodeForGN(value):
105 """Encodes value as a GN literal."""
Artem Titov81f51972018-06-27 10:31:23 +0200106 if isinstance(value, str):
sakala4a75382017-01-24 01:25:50 -0800107 return '"' + value + '"'
Artem Titov81f51972018-06-27 10:31:23 +0200108 elif isinstance(value, bool):
sakala4a75382017-01-24 01:25:50 -0800109 return repr(value).lower()
110 else:
111 return repr(value)
112
113
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700114def _GetOutputDirectory(build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800115 """Returns the GN output directory for the target architecture."""
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700116 return os.path.join(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800117
118
119def _GetTargetCpu(arch):
120 """Returns target_cpu for the GN build with the given architecture."""
121 if arch in ['armeabi', 'armeabi-v7a']:
122 return 'arm'
sakal423f1062017-04-07 05:10:15 -0700123 elif arch == 'arm64-v8a':
124 return 'arm64'
sakala4a75382017-01-24 01:25:50 -0800125 elif arch == 'x86':
126 return 'x86'
sakal423f1062017-04-07 05:10:15 -0700127 elif arch == 'x86_64':
128 return 'x64'
sakala4a75382017-01-24 01:25:50 -0800129 else:
130 raise Exception('Unknown arch: ' + arch)
131
132
133def _GetArmVersion(arch):
134 """Returns arm_version for the GN build with the given architecture."""
135 if arch == 'armeabi':
136 return 6
137 elif arch == 'armeabi-v7a':
138 return 7
sakal423f1062017-04-07 05:10:15 -0700139 elif arch in ['arm64-v8a', 'x86', 'x86_64']:
sakala4a75382017-01-24 01:25:50 -0800140 return None
141 else:
142 raise Exception('Unknown arch: ' + arch)
143
144
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300145def Build(build_dir, arch, use_goma, extra_gn_args, extra_gn_switches,
146 extra_ninja_switches):
sakala4a75382017-01-24 01:25:50 -0800147 """Generates target architecture using GN and builds it using ninja."""
148 logging.info('Building: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700149 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800150 gn_args = {
151 'target_os': 'android',
152 'is_debug': False,
153 'is_component_build': False,
sakal67e414c2017-09-05 00:16:15 -0700154 'rtc_include_tests': False,
sakala4a75382017-01-24 01:25:50 -0800155 'target_cpu': _GetTargetCpu(arch),
156 'use_goma': use_goma
157 }
158 arm_version = _GetArmVersion(arch)
159 if arm_version:
160 gn_args['arm_version'] = arm_version
161 gn_args_str = '--args=' + ' '.join([
kjellander6b3fcfd2017-02-07 01:11:06 -0800162 k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800163
Artem Titov5d7a4c62018-07-23 13:58:25 +0200164 gn_args_list = ['gen', output_directory, gn_args_str]
165 gn_args_list.extend(extra_gn_switches)
166 _RunGN(gn_args_list)
sakala4a75382017-01-24 01:25:50 -0800167
sakal67e414c2017-09-05 00:16:15 -0700168 ninja_args = TARGETS[:]
sakala4a75382017-01-24 01:25:50 -0800169 if use_goma:
sakala53d4e72017-02-07 06:19:20 -0800170 ninja_args.extend(['-j', '200'])
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300171 ninja_args.extend(extra_ninja_switches)
sakala4a75382017-01-24 01:25:50 -0800172 _RunNinja(output_directory, ninja_args)
173
174
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700175def CollectCommon(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800176 """Collects architecture independent files into the .aar-archive."""
177 logging.info('Collecting common files.')
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700178 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800179 aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml')
180 aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
181
182
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700183def Collect(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800184 """Collects architecture specific files into the .aar-archive."""
185 logging.info('Collecting: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700186 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800187
188 abi_dir = os.path.join('jni', arch)
189 for so_file in NEEDED_SO_FILES:
190 aar_file.write(os.path.join(output_directory, so_file),
191 os.path.join(abi_dir, so_file))
192
193
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700194def GenerateLicenses(output_dir, build_dir, archs):
sakal67e414c2017-09-05 00:16:15 -0700195 builder = LicenseBuilder(
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700196 [_GetOutputDirectory(build_dir, arch) for arch in archs], TARGETS)
sakal67e414c2017-09-05 00:16:15 -0700197 builder.GenerateLicenseText(output_dir)
198
199
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200200def BuildAar(archs, output_file, use_goma=False, extra_gn_args=None,
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300201 ext_build_dir=None, extra_gn_switches=None,
202 extra_ninja_switches=None):
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200203 extra_gn_args = extra_gn_args or []
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300204 extra_gn_switches = extra_gn_switches or []
205 extra_ninja_switches = extra_ninja_switches or []
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200206 build_dir = ext_build_dir if ext_build_dir else tempfile.mkdtemp()
207
208 for arch in archs:
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300209 Build(build_dir, arch, use_goma, extra_gn_args, extra_gn_switches,
210 extra_ninja_switches)
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200211
212 with zipfile.ZipFile(output_file, 'w') as aar_file:
213 # Architecture doesn't matter here, arbitrarily using the first one.
214 CollectCommon(aar_file, build_dir, archs[0])
215 for arch in archs:
216 Collect(aar_file, build_dir, arch)
217
218 license_dir = os.path.dirname(os.path.realpath(output_file))
219 GenerateLicenses(license_dir, build_dir, archs)
220
221 if not ext_build_dir:
222 shutil.rmtree(build_dir, True)
223
224
sakala4a75382017-01-24 01:25:50 -0800225def main():
226 args = _ParseArgs()
sakala4a75382017-01-24 01:25:50 -0800227 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
228
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200229 BuildAar(args.arch, args.output, args.use_goma, args.extra_gn_args,
Yura Yaroshevichf517f112018-05-24 16:48:02 +0300230 args.build_dir, args.extra_gn_switches, args.extra_ninja_switches)
sakala4a75382017-01-24 01:25:50 -0800231
232
233if __name__ == '__main__':
234 sys.exit(main())