blob: d0cee97618fb307387db585336afe48c2aeae34a [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.
mbonadei26764612017-01-25 07:42:08 -080014./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
37DEFAULT_ARCHS = ['armeabi-v7a', 'x86']
38NEEDED_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'
95 elif arch == 'x86':
96 return 'x86'
97 else:
98 raise Exception('Unknown arch: ' + arch)
99
100
101def _GetArmVersion(arch):
102 """Returns arm_version for the GN build with the given architecture."""
103 if arch == 'armeabi':
104 return 6
105 elif arch == 'armeabi-v7a':
106 return 7
107 elif arch == 'x86':
108 return None
109 else:
110 raise Exception('Unknown arch: ' + arch)
111
112
kjellander6b3fcfd2017-02-07 01:11:06 -0800113def Build(tmp_dir, arch, use_goma, extra_gn_args):
sakala4a75382017-01-24 01:25:50 -0800114 """Generates target architecture using GN and builds it using ninja."""
115 logging.info('Building: %s', arch)
116 output_directory = _GetOutputDirectory(tmp_dir, arch)
117 gn_args = {
118 'target_os': 'android',
119 'is_debug': False,
120 'is_component_build': False,
121 'target_cpu': _GetTargetCpu(arch),
122 'use_goma': use_goma
123 }
124 arm_version = _GetArmVersion(arch)
125 if arm_version:
126 gn_args['arm_version'] = arm_version
127 gn_args_str = '--args=' + ' '.join([
kjellander6b3fcfd2017-02-07 01:11:06 -0800128 k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800129
130 _RunGN(['gen', output_directory, gn_args_str])
131
132 ninja_args = TARGETS
133 if use_goma:
134 ninja_args.extend(['-j', '1024'])
135 _RunNinja(output_directory, ninja_args)
136
137
138def CollectCommon(aar_file, tmp_dir, arch):
139 """Collects architecture independent files into the .aar-archive."""
140 logging.info('Collecting common files.')
141 output_directory = _GetOutputDirectory(tmp_dir, arch)
142 aar_file.write(MANIFEST_FILE, 'AndroidManifest.xml')
143 aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
144
145
146def Collect(aar_file, tmp_dir, arch):
147 """Collects architecture specific files into the .aar-archive."""
148 logging.info('Collecting: %s', arch)
149 output_directory = _GetOutputDirectory(tmp_dir, arch)
150
151 abi_dir = os.path.join('jni', arch)
152 for so_file in NEEDED_SO_FILES:
153 aar_file.write(os.path.join(output_directory, so_file),
154 os.path.join(abi_dir, so_file))
155
156
157def main():
158 args = _ParseArgs()
sakala4a75382017-01-24 01:25:50 -0800159 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
160
161 tmp_dir = tempfile.mkdtemp()
162
163 for arch in args.arch:
kjellander6b3fcfd2017-02-07 01:11:06 -0800164 Build(tmp_dir, arch, args.use_goma, args.extra_gn_args)
sakala4a75382017-01-24 01:25:50 -0800165
166 with zipfile.ZipFile(args.output, 'w') as aar_file:
167 # Architecture doesn't matter here, arbitrarily using the first one.
168 CollectCommon(aar_file, tmp_dir, args.arch[0])
169 for arch in args.arch:
170 Collect(aar_file, tmp_dir, arch)
171
172 shutil.rmtree(tmp_dir, True)
173
174
175if __name__ == '__main__':
176 sys.exit(main())