OLD | NEW |
---|---|
(Empty) | |
1 #!/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 """WebRTC iOS FAT libraries build script. | |
12 Each architecture is compiled separately before being merged together. | |
13 By default, the library is created in out_ios_libs/. (Change with -o.) | |
14 The headers will be copied to out_ios_libs/include. | |
15 """ | |
16 | |
17 import argparse | |
18 import distutils.dir_util | |
19 import logging | |
20 import os | |
21 import shutil | |
22 import subprocess | |
23 import sys | |
24 | |
25 | |
26 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
27 WEBRTC_BASE_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..')) | |
28 SDK_OUTPUT_DIR = os.path.join(WEBRTC_BASE_DIR, 'out_ios_libs') | |
29 SDK_LIB_NAME = 'librtc_sdk_objc.a' | |
30 SDK_FRAMEWORK_NAME = 'WebRTC.framework' | |
31 | |
32 BUILD_FLAVOR = 'release' | |
33 ENABLED_ARCHITECTURES = ['arm', 'arm64', 'x64'] | |
34 IOS_DEPLOYMENT_TARGET = '8.0' | |
35 LIBVPX_BUILD_VP9 = False | |
36 CUSTOM_GN_OPTS = [] # example: ['some_option=foo bar', 'other_option=true'] | |
37 | |
38 | |
39 def _ParseArgs(): | |
40 parser = argparse.ArgumentParser(description=__doc__) | |
41 parser.add_argument('-b', '--build_type', default='framework', | |
42 choices=['framework', 'static_only'], | |
43 help='The build type. Can be "framework" or "static_only". ' | |
44 'Defaults to "framework".') | |
45 parser.add_argument('-c', '--clean', action='store_true', default=False, | |
46 help='Removes the previously generated build output, if any.') | |
47 parser.add_argument('-o', '--output-dir', default=SDK_OUTPUT_DIR, | |
48 help='Specifies a directory to output the build artifacts to. ' | |
49 'If specified together with -c, deletes the dir.') | |
50 parser.add_argument('-r', '--revision', type=int, default=0, | |
51 help='Specifies a revision number to embed if building the framework.') | |
52 parser.add_argument('-e', '--bitcode', action='store_true', default=False, | |
53 help='Compile with bitcode.') | |
54 return parser.parse_args() | |
55 | |
56 | |
57 def _CleanArtifacts(output_dir): | |
58 if os.path.isdir(output_dir): | |
59 logging.info('Deleting %s', output_dir) | |
60 shutil.rmtree(output_dir, True) | |
kjellander_webrtc
2017/01/31 21:39:54
I'm not sure we want to ignore errors here. Since
oprypin_webrtc
2017/02/06 08:39:14
Done.
| |
61 | |
62 | |
63 def BuildWebRTC(output_dir, target_arch, flavor, build_type, | |
64 ios_deployment_target, libvpx_build_vp9, use_bitcode, | |
65 custom_gn_options=[]): | |
kjellander_webrtc
2017/01/31 21:39:53
empty lists as a default parameters in Python are
oprypin_webrtc
2017/02/06 08:39:14
Done.
| |
66 output_dir = os.path.join(output_dir, target_arch + '_libs') | |
67 gn_args = ['target_os="ios"', 'ios_enable_code_signing=false', | |
68 'use_xcode_clang=true', 'is_component_build=false'] | |
69 | |
70 # Add flavor option. | |
kjellander_webrtc
2017/01/31 21:39:54
I know you're just preserving the behavior of the
oprypin_webrtc
2017/02/06 08:39:14
I made the change to use a flag but I feel like th
kjellander_webrtc
2017/02/06 08:58:24
Fair enough.
| |
71 if flavor == 'debug': | |
72 gn_args.append('is_debug=true') | |
73 elif flavor == 'release': | |
74 gn_args.append('is_debug=false') | |
75 else: | |
76 raise ValueError('Unexpected flavor type: %s' % flavor) | |
77 | |
78 # Add the specified architecture. | |
kjellander_webrtc
2017/01/31 21:39:53
I know these comments were there in the bash scrip
oprypin_webrtc
2017/02/06 08:39:14
Done.
| |
79 gn_args.append('target_cpu="%s"' % target_arch) | |
80 | |
81 # Add deployment target. | |
82 gn_args.append('ios_deployment_target="%s"' % ios_deployment_target) | |
83 | |
84 # Add vp9 option. | |
85 gn_args.append('rtc_libvpx_build_vp9=' + | |
86 ('true' if libvpx_build_vp9 else 'false')) | |
87 | |
88 # Add bitcode option. | |
89 gn_args.append('enable_ios_bitcode=' + | |
90 ('true' if use_bitcode else 'false')) | |
91 | |
92 # Add custom options. | |
93 gn_args.extend(custom_gn_options) | |
94 | |
95 # Generate static or dynamic. | |
96 if build_type == 'static_only': | |
97 gn_target_name = 'rtc_sdk_objc' | |
98 elif build_type == 'framework': | |
99 gn_target_name = 'rtc_sdk_framework_objc' | |
100 gn_args.append('enable_dsyms=true') | |
101 gn_args.append('enable_stripping=true') | |
102 else: | |
103 raise ValueError('Build type "%s" is not supported.' % build_type) | |
104 | |
105 logging.info('Building WebRTC with args: %s', ' '.join(gn_args)) | |
106 cmd = ['gn', 'gen', output_dir, | |
107 '--args=' + ' '.join(gn_args)] | |
108 subprocess.check_call(cmd) | |
kjellander_webrtc
2017/01/31 21:39:54
For debugging purposes, I find it useful to wrap s
oprypin_webrtc
2017/02/06 08:39:14
Done.
| |
109 logging.info('Building target: %s', gn_target_name) | |
110 cmd = ['ninja', '-C', output_dir, gn_target_name] | |
111 subprocess.check_call(cmd) | |
112 | |
113 # Strip debug symbols to reduce size. | |
114 if build_type == 'static_only': | |
115 gn_target_path = os.path.join(output_dir, 'obj', 'webrtc', 'sdk', | |
116 'lib%s.a' % gn_target_name) | |
117 cmd = ['strip', '-S', gn_target_path, '-o', | |
118 os.path.join(output_dir, 'lib%s.a' % gn_target_name)] | |
119 subprocess.check_call(cmd) | |
120 | |
121 | |
122 def main(): | |
123 args = _ParseArgs() | |
124 | |
125 logging.basicConfig(level=logging.INFO) | |
126 | |
127 if args.clean: | |
128 _CleanArtifacts(args.output_dir) | |
129 return 0 | |
130 | |
131 # Build all architectures. | |
132 for arch in ENABLED_ARCHITECTURES: | |
133 BuildWebRTC(args.output_dir, arch, BUILD_FLAVOR, args.build_type, | |
134 IOS_DEPLOYMENT_TARGET, LIBVPX_BUILD_VP9, args.bitcode, | |
135 CUSTOM_GN_OPTS) | |
136 | |
137 # Ignoring x86 except for static libraries for now because of a GN build issue | |
138 # where the generated dynamic framework has the wrong architectures. | |
139 | |
140 # Create FAT archive. | |
141 if args.build_type == 'static_only': | |
142 BuildWebRTC(args.output_dir, 'x86', BUILD_FLAVOR, args.build_type, | |
143 IOS_DEPLOYMENT_TARGET, LIBVPX_BUILD_VP9, args.bitcode, | |
144 CUSTOM_GN_OPTS) | |
145 | |
146 arm_lib_path = os.path.join(args.output_dir, 'arm_libs', SDK_LIB_NAME) | |
147 arm64_lib_path = os.path.join(args.output_dir, 'arm64_libs', SDK_LIB_NAME) | |
148 x64_lib_path = os.path.join(args.output_dir, 'x64_libs', SDK_LIB_NAME) | |
149 x86_lib_path = os.path.join(args.output_dir, 'x86_libs', SDK_LIB_NAME) | |
150 | |
151 # Combine the slices. | |
152 cmd = ['lipo', arm_lib_path, arm64_lib_path, x64_lib_path, x86_lib_path, | |
153 '-create', '-output', os.path.join(args.output_dir, SDK_LIB_NAME)] | |
154 subprocess.check_call(cmd) | |
155 | |
156 elif args.build_type == 'framework': | |
157 arm_lib_path = os.path.join(args.output_dir, 'arm_libs') | |
158 arm64_lib_path = os.path.join(args.output_dir, 'arm64_libs') | |
159 x64_lib_path = os.path.join(args.output_dir, 'x64_libs') | |
160 | |
161 # Combine the slices. | |
162 dylib_path = os.path.join(SDK_FRAMEWORK_NAME, 'WebRTC') | |
163 # Use distutils instead of shutil to support merging folders. | |
164 distutils.dir_util.copy_tree( | |
165 os.path.join(arm64_lib_path, SDK_FRAMEWORK_NAME), args.output_dir) | |
166 try: | |
167 os.remove(os.path.join(args.output_dir, dylib_path)) | |
kjellander_webrtc
2017/01/31 21:39:54
Use shutil.rmtree instead and check with os.path.i
oprypin_webrtc
2017/02/06 08:39:14
Not sure what you mean here. Seems like we are del
kjellander_webrtc
2017/02/06 08:58:24
Ah, I thought it was a dir. Still nicer to check i
oprypin_webrtc
2017/02/06 09:19:50
Just applying the EAFP principle. Aside from how i
kjellander_webrtc
2017/02/06 11:33:02
You're right. This is fine.
| |
168 except OSError: | |
169 pass | |
170 logging.info('Merging framework slices.') | |
171 cmd = ['lipo', os.path.join(arm_lib_path, dylib_path), | |
172 os.path.join(arm64_lib_path, dylib_path), | |
173 os.path.join(x64_lib_path, dylib_path), | |
174 '-create', '-output', os.path.join(args.output_dir, dylib_path)] | |
175 subprocess.check_call(cmd) | |
176 | |
177 # Remove stray mobileprovision if it exists until chromium roll lands. | |
178 # See https://codereview.chromium.org/2397433002. | |
kjellander_webrtc
2017/01/31 21:39:54
This was rolled in long time ago. Can you make a s
oprypin_webrtc
2017/02/06 08:39:14
https://codereview.webrtc.org/2676233002/
kjellander_webrtc
2017/02/06 08:58:24
Acknowledged.
| |
179 provision_file = os.path.join(args.output_dir, SDK_FRAMEWORK_NAME, | |
180 'embedded.mobileprovision') | |
181 try: | |
182 os.remove(provision_file) | |
183 except OSError: | |
184 pass | |
185 | |
186 # Merge the dSYM slices. | |
187 dsym_path = 'WebRTC.dSYM/Contents/Resources/DWARF/WebRTC' | |
kjellander_webrtc
2017/01/31 21:39:53
since we use os.path.join everywhere else, we shou
oprypin_webrtc
2017/02/06 08:39:14
Done.
| |
188 distutils.dir_util.copy_tree(os.path.join(arm64_lib_path, 'WebRTC.dSYM'), | |
189 args.output_dir) | |
190 os.remove(os.path.join(args.output_dir, dsym_path)) | |
191 logging.info('Merging dSYM slices.') | |
192 cmd = ['lipo', os.path.join(arm_lib_path, dsym_path), | |
193 os.path.join(arm64_lib_path, dsym_path), | |
194 os.path.join(x64_lib_path, dsym_path), | |
195 '-create', '-output', os.path.join(args.output_dir, dsym_path)] | |
196 subprocess.check_call(cmd) | |
197 | |
198 # Modify the version number. | |
199 # Format should be <Branch cut MXX>.<Hotfix #>.<Rev #>. | |
200 # e.g. 55.0.14986 means branch cut 55, no hotfixes, and revision 14986. | |
201 infoplist_path = os.path.join(args.output_dir, SDK_FRAMEWORK_NAME, | |
202 'Info.plist') | |
203 cmd = ['PlistBuddy', '-c', | |
204 'Print :CFBundleShortVersionString', infoplist_path] | |
205 major_minor = subprocess.check_output(cmd).strip() | |
206 version_number = '%s.%s' % (major_minor, args.revision) | |
207 logging.info('Substituting revision number: %s', version_number) | |
208 cmd = ['PlistBuddy', '-c', | |
209 'Set :CFBundleVersion ' + version_number, infoplist_path] | |
210 subprocess.check_call(cmd) | |
211 subprocess.check_call(['plutil', '-convert', 'binary1', infoplist_path]) | |
212 | |
213 logging.info('Done.') | |
214 return 0 | |
215 | |
216 | |
217 if __name__ == '__main__': | |
218 sys.exit(main()) | |
OLD | NEW |