blob: 54272e979e446c25de831aa36f24624ed335976f [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
sakal423f1062017-04-07 05:10:15 -070037DEFAULT_ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
sakala4a75382017-01-24 01:25:50 -080038NEEDED_SO_FILES = ['libjingle_peerconnection_so.so']
39JAR_FILE = 'lib.java/webrtc/sdk/android/libwebrtc.jar'
40MANIFEST_FILE = 'webrtc/sdk/android/AndroidManifest.xml'
41TARGETS = [
42 'webrtc/sdk/android:libwebrtc',
43 'webrtc/sdk/android:libjingle_peerconnection_so',
44]
45
46
47def _ParseArgs():
48 parser = argparse.ArgumentParser(description='libwebrtc.aar generator.')
49 parser.add_argument('--output', default='libwebrtc.aar',
50 help='Output file of the script.')
kjellander6b3fcfd2017-02-07 01:11:06 -080051 parser.add_argument('--arch', default=DEFAULT_ARCHS, nargs='*',
52 help='Architectures to build. Defaults to %(default)s.')
sakala4a75382017-01-24 01:25:50 -080053 parser.add_argument('--use-goma', action='store_true', default=False,
54 help='Use goma.')
55 parser.add_argument('--verbose', action='store_true', default=False,
56 help='Debug logging.')
kjellander6b3fcfd2017-02-07 01:11:06 -080057 parser.add_argument('--extra-gn-args', default=[], nargs='*',
58 help='Additional GN args to be used during Ninja generation.')
sakala4a75382017-01-24 01:25:50 -080059 return parser.parse_args()
60
61
62def _RunGN(args):
63 cmd = ['gn']
64 cmd.extend(args)
65 logging.debug('Running: %r', cmd)
66 subprocess.check_call(cmd)
67
68
69def _RunNinja(output_directory, args):
70 cmd = ['ninja', '-C', output_directory]
71 cmd.extend(args)
72 logging.debug('Running: %r', cmd)
73 subprocess.check_call(cmd)
74
75
76def _EncodeForGN(value):
77 """Encodes value as a GN literal."""
78 if type(value) is str:
79 return '"' + value + '"'
80 elif type(value) is bool:
81 return repr(value).lower()
82 else:
83 return repr(value)
84
85
86def _GetOutputDirectory(tmp_dir, arch):
87 """Returns the GN output directory for the target architecture."""
88 return os.path.join(tmp_dir, arch)
89
90
91def _GetTargetCpu(arch):
92 """Returns target_cpu for the GN build with the given architecture."""
93 if arch in ['armeabi', 'armeabi-v7a']:
94 return 'arm'
sakal423f1062017-04-07 05:10:15 -070095 elif arch == 'arm64-v8a':
96 return 'arm64'
sakala4a75382017-01-24 01:25:50 -080097 elif arch == 'x86':
98 return 'x86'
sakal423f1062017-04-07 05:10:15 -070099 elif arch == 'x86_64':
100 return 'x64'
sakala4a75382017-01-24 01:25:50 -0800101 else:
102 raise Exception('Unknown arch: ' + arch)
103
104
105def _GetArmVersion(arch):
106 """Returns arm_version for the GN build with the given architecture."""
107 if arch == 'armeabi':
108 return 6
109 elif arch == 'armeabi-v7a':
110 return 7
sakal423f1062017-04-07 05:10:15 -0700111 elif arch in ['arm64-v8a', 'x86', 'x86_64']:
sakala4a75382017-01-24 01:25:50 -0800112 return None
113 else:
114 raise Exception('Unknown arch: ' + arch)
115
116
kjellander6b3fcfd2017-02-07 01:11:06 -0800117def Build(tmp_dir, arch, use_goma, extra_gn_args):
sakala4a75382017-01-24 01:25:50 -0800118 """Generates target architecture using GN and builds it using ninja."""
119 logging.info('Building: %s', arch)
120 output_directory = _GetOutputDirectory(tmp_dir, arch)
121 gn_args = {
122 'target_os': 'android',
123 'is_debug': False,
124 'is_component_build': False,
125 'target_cpu': _GetTargetCpu(arch),
126 'use_goma': use_goma
127 }
128 arm_version = _GetArmVersion(arch)
129 if arm_version:
130 gn_args['arm_version'] = arm_version
131 gn_args_str = '--args=' + ' '.join([
kjellander6b3fcfd2017-02-07 01:11:06 -0800132 k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800133
134 _RunGN(['gen', output_directory, gn_args_str])
135
136 ninja_args = TARGETS
137 if use_goma:
sakala53d4e72017-02-07 06:19:20 -0800138 ninja_args.extend(['-j', '200'])
sakala4a75382017-01-24 01:25:50 -0800139 _RunNinja(output_directory, ninja_args)
140
141
142def CollectCommon(aar_file, tmp_dir, arch):
143 """Collects architecture independent files into the .aar-archive."""
144 logging.info('Collecting common files.')
145 output_directory = _GetOutputDirectory(tmp_dir, arch)
146 aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml')
147 aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
148
149
150def Collect(aar_file, tmp_dir, arch):
151 """Collects architecture specific files into the .aar-archive."""
152 logging.info('Collecting: %s', arch)
153 output_directory = _GetOutputDirectory(tmp_dir, arch)
154
155 abi_dir = os.path.join('jni', arch)
156 for so_file in NEEDED_SO_FILES:
157 aar_file.write(os.path.join(output_directory, so_file),
158 os.path.join(abi_dir, so_file))
159
160
161def main():
162 args = _ParseArgs()
sakala4a75382017-01-24 01:25:50 -0800163 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
164
165 tmp_dir = tempfile.mkdtemp()
166
167 for arch in args.arch:
kjellander6b3fcfd2017-02-07 01:11:06 -0800168 Build(tmp_dir, arch, args.use_goma, args.extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800169
170 with zipfile.ZipFile(args.output, 'w') as aar_file:
171 # Architecture doesn't matter here, arbitrarily using the first one.
172 CollectCommon(aar_file, tmp_dir, args.arch[0])
173 for arch in args.arch:
174 Collect(aar_file, tmp_dir, arch)
175
176 shutil.rmtree(tmp_dir, True)
177
178
179if __name__ == '__main__':
180 sys.exit(main())