blob: 111825155e52f2e81926069fd545dfa82980758e [file] [log] [blame]
Christoffer Jansson4e8a7732022-02-08 08:01:121#!/usr/bin/env vpython3
hjonbc73fe12016-03-21 18:38:262
3# Copyright 2016 The WebRTC project authors. All Rights Reserved.
tkchin@webrtc.org64eb2ff2015-03-23 19:07:374#
hjonbc73fe12016-03-21 18:38:265# 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.
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3710"""Script for merging generated iOS libraries."""
11
tkchin5209d672016-04-16 19:06:3312import sys
tkchin5209d672016-04-16 19:06:3313import argparse
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3714import os
15import re
16import subprocess
Christoffer Jansson4e8a7732022-02-08 08:01:1217from six.moves import range
18
tkchin5209d672016-04-16 19:06:3319
20# Valid arch subdir names.
21VALID_ARCHS = ['arm_libs', 'arm64_libs', 'ia32_libs', 'x64_libs']
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3722
23
24def MergeLibs(lib_base_dir):
Christoffer Jansson4e8a7732022-02-08 08:01:1225 """Merges generated iOS libraries for different archs.
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3726
27 Uses libtool to generate FAT archive files for each generated library.
28
29 Args:
30 lib_base_dir: directory whose subdirectories are named by architecture and
31 contain the built libraries for that architecture
32
33 Returns:
34 Exit code of libtool.
35 """
Christoffer Jansson4e8a7732022-02-08 08:01:1236 output_dir_name = 'fat_libs'
37 archs = [arch for arch in os.listdir(lib_base_dir) if arch in VALID_ARCHS]
38 # For each arch, find (library name, libary path) for arch. We will merge
39 # all libraries with the same name.
40 libs = {}
41 for lib_dir in [os.path.join(lib_base_dir, arch) for arch in VALID_ARCHS]:
42 if not os.path.exists(lib_dir):
43 continue
44 for dirpath, _, filenames in os.walk(lib_dir):
45 for filename in filenames:
46 if not filename.endswith('.a'):
47 continue
48 entry = libs.get(filename, [])
49 entry.append(os.path.join(dirpath, filename))
50 libs[filename] = entry
51 orphaned_libs = {}
52 valid_libs = {}
53 for library, paths in list(libs.items()):
54 if len(paths) < len(archs):
55 orphaned_libs[library] = paths
56 else:
57 valid_libs[library] = paths
58 for library, paths in list(orphaned_libs.items()):
59 components = library[:-2].split('_')[:-1]
60 found = False
61 # Find directly matching parent libs by stripping suffix.
62 while components and not found:
63 parent_library = '_'.join(components) + '.a'
64 if parent_library in valid_libs:
65 valid_libs[parent_library].extend(paths)
66 found = True
67 break
68 components = components[:-1]
69 # Find next best match by finding parent libs with the same prefix.
70 if not found:
71 base_prefix = library[:-2].split('_')[0]
72 for valid_lib, valid_paths in list(valid_libs.items()):
73 if valid_lib[:len(base_prefix)] == base_prefix:
74 valid_paths.extend(paths)
75 found = True
76 break
77 assert found
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3778
Christoffer Jansson4e8a7732022-02-08 08:01:1279 # Create output directory.
80 output_dir_path = os.path.join(lib_base_dir, output_dir_name)
81 if not os.path.exists(output_dir_path):
82 os.mkdir(output_dir_path)
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3783
Christoffer Jansson4e8a7732022-02-08 08:01:1284 # Use this so libtool merged binaries are always the same.
85 env = os.environ.copy()
86 env['ZERO_AR_DATE'] = '1'
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3787
Christoffer Jansson4e8a7732022-02-08 08:01:1288 # Ignore certain errors.
89 libtool_re = re.compile(r'^.*libtool:.*file: .* has no symbols$')
tkchin@webrtc.org64eb2ff2015-03-23 19:07:3790
Christoffer Jansson4e8a7732022-02-08 08:01:1291 # Merge libraries using libtool.
92 libtool_returncode = 0
93 for library, paths in list(valid_libs.items()):
94 cmd_list = [
95 'libtool', '-static', '-v', '-o',
96 os.path.join(output_dir_path, library)
97 ] + paths
98 libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env)
99 _, err = libtoolout.communicate()
100 for line in err.splitlines():
101 if not libtool_re.match(line):
102 print(line, file=sys.stderr)
103 # Unconditionally touch the output .a file on the command line if present
104 # and the command succeeded. A bit hacky.
105 libtool_returncode = libtoolout.returncode
106 if not libtool_returncode:
107 for i in range(len(cmd_list) - 1):
108 if cmd_list[i] == '-o' and cmd_list[i + 1].endswith('.a'):
109 os.utime(cmd_list[i + 1], None)
110 break
111 return libtool_returncode
tkchin@webrtc.org64eb2ff2015-03-23 19:07:37112
113
Christoffer Jansson4e8a7732022-02-08 08:01:12114def main():
115 parser_description = 'Merge WebRTC libraries.'
116 parser = argparse.ArgumentParser(description=parser_description)
117 parser.add_argument('lib_base_dir',
118 help='Directory with built libraries. ',
119 type=str)
120 args = parser.parse_args()
121 lib_base_dir = args.lib_base_dir
122 MergeLibs(lib_base_dir)
Mirko Bonadei8cc66952020-10-30 09:13:45123
tkchin@webrtc.org64eb2ff2015-03-23 19:07:37124
125if __name__ == '__main__':
Christoffer Jansson4e8a7732022-02-08 08:01:12126 sys.exit(main())