blob: 0ddca2fd5ecf0b4584607d44eabe9b1b232f4153 [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='*',
69 help='Additional GN args to be used during Ninja generation.')
sakala4a75382017-01-24 01:25:50 -080070 return parser.parse_args()
71
72
73def _RunGN(args):
Henrik Kjellanderec57e052017-10-17 21:36:01 +020074 cmd = [sys.executable,
75 os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py')]
sakala4a75382017-01-24 01:25:50 -080076 cmd.extend(args)
77 logging.debug('Running: %r', cmd)
78 subprocess.check_call(cmd)
79
80
81def _RunNinja(output_directory, args):
Henrik Kjellanderec57e052017-10-17 21:36:01 +020082 cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'),
83 '-C', output_directory]
sakala4a75382017-01-24 01:25:50 -080084 cmd.extend(args)
85 logging.debug('Running: %r', cmd)
86 subprocess.check_call(cmd)
87
88
89def _EncodeForGN(value):
90 """Encodes value as a GN literal."""
91 if type(value) is str:
92 return '"' + value + '"'
93 elif type(value) is bool:
94 return repr(value).lower()
95 else:
96 return repr(value)
97
98
korniltsev.anatoly0b510a92017-09-05 08:12:30 -070099def _GetOutputDirectory(build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800100 """Returns the GN output directory for the target architecture."""
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700101 return os.path.join(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800102
103
104def _GetTargetCpu(arch):
105 """Returns target_cpu for the GN build with the given architecture."""
106 if arch in ['armeabi', 'armeabi-v7a']:
107 return 'arm'
sakal423f1062017-04-07 05:10:15 -0700108 elif arch == 'arm64-v8a':
109 return 'arm64'
sakala4a75382017-01-24 01:25:50 -0800110 elif arch == 'x86':
111 return 'x86'
sakal423f1062017-04-07 05:10:15 -0700112 elif arch == 'x86_64':
113 return 'x64'
sakala4a75382017-01-24 01:25:50 -0800114 else:
115 raise Exception('Unknown arch: ' + arch)
116
117
118def _GetArmVersion(arch):
119 """Returns arm_version for the GN build with the given architecture."""
120 if arch == 'armeabi':
121 return 6
122 elif arch == 'armeabi-v7a':
123 return 7
sakal423f1062017-04-07 05:10:15 -0700124 elif arch in ['arm64-v8a', 'x86', 'x86_64']:
sakala4a75382017-01-24 01:25:50 -0800125 return None
126 else:
127 raise Exception('Unknown arch: ' + arch)
128
129
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700130def Build(build_dir, arch, use_goma, extra_gn_args):
sakala4a75382017-01-24 01:25:50 -0800131 """Generates target architecture using GN and builds it using ninja."""
132 logging.info('Building: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700133 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800134 gn_args = {
135 'target_os': 'android',
136 'is_debug': False,
137 'is_component_build': False,
sakal67e414c2017-09-05 00:16:15 -0700138 'rtc_include_tests': False,
sakala4a75382017-01-24 01:25:50 -0800139 'target_cpu': _GetTargetCpu(arch),
140 'use_goma': use_goma
141 }
142 arm_version = _GetArmVersion(arch)
143 if arm_version:
144 gn_args['arm_version'] = arm_version
145 gn_args_str = '--args=' + ' '.join([
kjellander6b3fcfd2017-02-07 01:11:06 -0800146 k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800147
148 _RunGN(['gen', output_directory, gn_args_str])
149
sakal67e414c2017-09-05 00:16:15 -0700150 ninja_args = TARGETS[:]
sakala4a75382017-01-24 01:25:50 -0800151 if use_goma:
sakala53d4e72017-02-07 06:19:20 -0800152 ninja_args.extend(['-j', '200'])
sakala4a75382017-01-24 01:25:50 -0800153 _RunNinja(output_directory, ninja_args)
154
155
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700156def CollectCommon(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800157 """Collects architecture independent files into the .aar-archive."""
158 logging.info('Collecting common files.')
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700159 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800160 aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml')
161 aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
162
163
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700164def Collect(aar_file, build_dir, arch):
sakala4a75382017-01-24 01:25:50 -0800165 """Collects architecture specific files into the .aar-archive."""
166 logging.info('Collecting: %s', arch)
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700167 output_directory = _GetOutputDirectory(build_dir, arch)
sakala4a75382017-01-24 01:25:50 -0800168
169 abi_dir = os.path.join('jni', arch)
170 for so_file in NEEDED_SO_FILES:
171 aar_file.write(os.path.join(output_directory, so_file),
172 os.path.join(abi_dir, so_file))
173
174
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700175def GenerateLicenses(output_dir, build_dir, archs):
sakal67e414c2017-09-05 00:16:15 -0700176 builder = LicenseBuilder(
korniltsev.anatoly0b510a92017-09-05 08:12:30 -0700177 [_GetOutputDirectory(build_dir, arch) for arch in archs], TARGETS)
sakal67e414c2017-09-05 00:16:15 -0700178 builder.GenerateLicenseText(output_dir)
179
180
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200181def BuildAar(archs, output_file, use_goma=False, extra_gn_args=None,
182 ext_build_dir=None):
183 extra_gn_args = extra_gn_args or []
184 build_dir = ext_build_dir if ext_build_dir else tempfile.mkdtemp()
185
186 for arch in archs:
187 Build(build_dir, arch, use_goma, extra_gn_args)
188
189 with zipfile.ZipFile(output_file, 'w') as aar_file:
190 # Architecture doesn't matter here, arbitrarily using the first one.
191 CollectCommon(aar_file, build_dir, archs[0])
192 for arch in archs:
193 Collect(aar_file, build_dir, arch)
194
195 license_dir = os.path.dirname(os.path.realpath(output_file))
196 GenerateLicenses(license_dir, build_dir, archs)
197
198 if not ext_build_dir:
199 shutil.rmtree(build_dir, True)
200
201
sakala4a75382017-01-24 01:25:50 -0800202def main():
203 args = _ParseArgs()
sakala4a75382017-01-24 01:25:50 -0800204 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
205
Sami Kalliomäkidbb15a72017-10-05 16:15:02 +0200206 BuildAar(args.arch, args.output, args.use_goma, args.extra_gn_args,
207 args.build_dir)
sakala4a75382017-01-24 01:25:50 -0800208
209
210if __name__ == '__main__':
211 sys.exit(main())