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 os.environ['PATH'] = '/usr/libexec' + os.pathsep + os.environ['PATH'] | |
27 | |
28 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
29 WEBRTC_BASE_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..')) | |
30 SDK_OUTPUT_DIR = os.path.join(WEBRTC_BASE_DIR, 'out_ios_libs') | |
31 SDK_LIB_NAME = 'librtc_sdk_objc.a' | |
32 SDK_FRAMEWORK_NAME = 'WebRTC.framework' | |
33 | |
34 ENABLED_ARCHITECTURES = ['arm', 'arm64', 'x64'] | |
35 IOS_DEPLOYMENT_TARGET = '8.0' | |
36 LIBVPX_BUILD_VP9 = False | |
37 CUSTOM_GN_OPTS = [] # example: ['some_option=foo bar', 'other_option=true'] | |
38 | |
39 | |
40 def _ParseArgs(): | |
41 parser = argparse.ArgumentParser(description=__doc__) | |
42 parser.add_argument('-b', '--build_type', default='framework', | |
43 choices=['framework', 'static_only'], | |
44 help='The build type. Can be "framework" or "static_only". ' | |
45 'Defaults to "framework".') | |
46 parser.add_argument('--build_config', default='release', | |
47 choices=['debug', 'release'], | |
48 help='The build config. Can be "debug" or "release". ' | |
49 'Defaults to "release".') | |
50 parser.add_argument('-c', '--clean', action='store_true', default=False, | |
51 help='Removes the previously generated build output, if any.') | |
52 parser.add_argument('-o', '--output-dir', default=SDK_OUTPUT_DIR, | |
53 help='Specifies a directory to output the build artifacts to. ' | |
54 'If specified together with -c, deletes the dir.') | |
55 parser.add_argument('-r', '--revision', type=int, default=0, | |
56 help='Specifies a revision number to embed if building the framework.') | |
57 parser.add_argument('-e', '--bitcode', action='store_true', default=False, | |
58 help='Compile with bitcode.') | |
59 return parser.parse_args() | |
60 | |
61 | |
62 def _RunCommand(cmd): | |
63 logging.debug('Running: %r', cmd) | |
64 subprocess.check_call(cmd) | |
65 | |
66 | |
67 def _CleanArtifacts(output_dir): | |
68 if os.path.isdir(output_dir): | |
69 logging.info('Deleting %s', output_dir) | |
70 shutil.rmtree(output_dir) | |
71 | |
72 | |
73 def BuildWebRTC(output_dir, target_arch, flavor, build_type, | |
74 ios_deployment_target, libvpx_build_vp9, use_bitcode, | |
75 custom_gn_options=()): | |
76 output_dir = os.path.join(output_dir, target_arch + '_libs') | |
77 gn_args = ['target_os="ios"', 'ios_enable_code_signing=false', | |
78 'use_xcode_clang=true', 'is_component_build=false'] | |
79 | |
80 # Add flavor option. | |
81 if flavor == 'debug': | |
82 gn_args.append('is_debug=true') | |
83 elif flavor == 'release': | |
84 gn_args.append('is_debug=false') | |
85 else: | |
86 raise ValueError('Unexpected flavor type: %s' % flavor) | |
87 | |
88 gn_args.append('target_cpu="%s"' % target_arch) | |
89 | |
90 gn_args.append('ios_deployment_target="%s"' % ios_deployment_target) | |
91 | |
92 gn_args.append('rtc_libvpx_build_vp9=' + | |
93 ('true' if libvpx_build_vp9 else 'false')) | |
94 | |
95 gn_args.append('enable_ios_bitcode=' + | |
96 ('true' if use_bitcode else 'false')) | |
97 | |
98 gn_args.extend(custom_gn_options) | |
99 | |
100 # Generate static or dynamic. | |
101 if build_type == 'static_only': | |
102 gn_target_name = 'rtc_sdk_objc' | |
103 elif build_type == 'framework': | |
104 gn_target_name = 'rtc_sdk_framework_objc' | |
105 gn_args.append('enable_dsyms=true') | |
106 gn_args.append('enable_stripping=true') | |
107 else: | |
108 raise ValueError('Build type "%s" is not supported.' % build_type) | |
109 | |
110 logging.info('Building WebRTC with args: %s', ' '.join(gn_args)) | |
111 cmd = ['gn', 'gen', output_dir, | |
112 '--args=' + ' '.join(gn_args)] | |
113 _RunCommand(cmd) | |
114 logging.info('Building target: %s', gn_target_name) | |
115 cmd = ['ninja', '-C', output_dir, gn_target_name] | |
116 _RunCommand(cmd) | |
117 | |
118 # Strip debug symbols to reduce size. | |
119 if build_type == 'static_only': | |
120 gn_target_path = os.path.join(output_dir, 'obj', 'webrtc', 'sdk', | |
121 'lib%s.a' % gn_target_name) | |
122 cmd = ['strip', '-S', gn_target_path, '-o', | |
123 os.path.join(output_dir, 'lib%s.a' % gn_target_name)] | |
124 _RunCommand(cmd) | |
125 | |
126 | |
127 def main(): | |
128 args = _ParseArgs() | |
129 | |
130 logging.basicConfig(level=logging.INFO) | |
kjellander_webrtc
2017/02/06 08:58:24
Since we have several debug logging statements now
oprypin_webrtc
2017/02/06 09:19:50
Done.
| |
131 | |
132 if args.clean: | |
133 _CleanArtifacts(args.output_dir) | |
134 return 0 | |
135 | |
136 # Build all architectures. | |
137 for arch in ENABLED_ARCHITECTURES: | |
138 BuildWebRTC(args.output_dir, arch, args.build_config, args.build_type, | |
139 IOS_DEPLOYMENT_TARGET, LIBVPX_BUILD_VP9, args.bitcode, | |
140 CUSTOM_GN_OPTS) | |
141 | |
142 # Ignoring x86 except for static libraries for now because of a GN build issue | |
143 # where the generated dynamic framework has the wrong architectures. | |
144 | |
145 # Create FAT archive. | |
146 if args.build_type == 'static_only': | |
147 BuildWebRTC(args.output_dir, 'x86', args.build_config, args.build_type, | |
148 IOS_DEPLOYMENT_TARGET, LIBVPX_BUILD_VP9, args.bitcode, | |
149 CUSTOM_GN_OPTS) | |
150 | |
151 arm_lib_path = os.path.join(args.output_dir, 'arm_libs', SDK_LIB_NAME) | |
152 arm64_lib_path = os.path.join(args.output_dir, 'arm64_libs', SDK_LIB_NAME) | |
153 x64_lib_path = os.path.join(args.output_dir, 'x64_libs', SDK_LIB_NAME) | |
154 x86_lib_path = os.path.join(args.output_dir, 'x86_libs', SDK_LIB_NAME) | |
155 | |
156 # Combine the slices. | |
157 cmd = ['lipo', arm_lib_path, arm64_lib_path, x64_lib_path, x86_lib_path, | |
158 '-create', '-output', os.path.join(args.output_dir, SDK_LIB_NAME)] | |
159 _RunCommand(cmd) | |
160 | |
161 elif args.build_type == 'framework': | |
162 arm_lib_path = os.path.join(args.output_dir, 'arm_libs') | |
163 arm64_lib_path = os.path.join(args.output_dir, 'arm64_libs') | |
164 x64_lib_path = os.path.join(args.output_dir, 'x64_libs') | |
165 | |
166 # Combine the slices. | |
167 dylib_path = os.path.join(SDK_FRAMEWORK_NAME, 'WebRTC') | |
168 # Use distutils instead of shutil to support merging folders. | |
169 distutils.dir_util.copy_tree( | |
170 os.path.join(arm64_lib_path, SDK_FRAMEWORK_NAME), | |
171 os.path.join(args.output_dir, SDK_FRAMEWORK_NAME)) | |
172 try: | |
173 os.remove(os.path.join(args.output_dir, dylib_path)) | |
174 except OSError: | |
175 pass | |
176 logging.info('Merging framework slices.') | |
177 cmd = ['lipo', os.path.join(arm_lib_path, dylib_path), | |
178 os.path.join(arm64_lib_path, dylib_path), | |
179 os.path.join(x64_lib_path, dylib_path), | |
180 '-create', '-output', os.path.join(args.output_dir, dylib_path)] | |
181 _RunCommand(cmd) | |
182 | |
183 # Remove stray mobileprovision if it exists until chromium roll lands. | |
184 # See https://codereview.chromium.org/2397433002. | |
185 provision_file = os.path.join(args.output_dir, SDK_FRAMEWORK_NAME, | |
186 'embedded.mobileprovision') | |
187 try: | |
188 os.remove(provision_file) | |
189 except OSError: | |
190 pass | |
191 | |
192 # Merge the dSYM slices. | |
193 dsym_path = os.path.join('WebRTC.dSYM', 'Contents', 'Resources', 'DWARF', | |
194 'WebRTC') | |
195 distutils.dir_util.copy_tree(os.path.join(arm64_lib_path, 'WebRTC.dSYM'), | |
196 os.path.join(args.output_dir, 'WebRTC.dSYM')) | |
197 try: | |
198 os.remove(os.path.join(args.output_dir, dsym_path)) | |
199 except OSError: | |
200 pass | |
201 logging.info('Merging dSYM slices.') | |
202 cmd = ['lipo', os.path.join(arm_lib_path, dsym_path), | |
203 os.path.join(arm64_lib_path, dsym_path), | |
204 os.path.join(x64_lib_path, dsym_path), | |
205 '-create', '-output', os.path.join(args.output_dir, dsym_path)] | |
206 _RunCommand(cmd) | |
207 | |
208 # Modify the version number. | |
209 # Format should be <Branch cut MXX>.<Hotfix #>.<Rev #>. | |
210 # e.g. 55.0.14986 means branch cut 55, no hotfixes, and revision 14986. | |
211 infoplist_path = os.path.join(args.output_dir, SDK_FRAMEWORK_NAME, | |
212 'Info.plist') | |
213 cmd = ['PlistBuddy', '-c', | |
214 'Print :CFBundleShortVersionString', infoplist_path] | |
215 major_minor = subprocess.check_output(cmd).strip() | |
216 version_number = '%s.%s' % (major_minor, args.revision) | |
217 logging.info('Substituting revision number: %s', version_number) | |
218 cmd = ['PlistBuddy', '-c', | |
219 'Set :CFBundleVersion ' + version_number, infoplist_path] | |
220 _RunCommand(cmd) | |
221 _RunCommand(['plutil', '-convert', 'binary1', infoplist_path]) | |
222 | |
223 logging.info('Done.') | |
224 return 0 | |
225 | |
226 | |
227 if __name__ == '__main__': | |
228 sys.exit(main()) | |
OLD | NEW |