1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
import sys
import subprocess
import tempfile
import os
class Opts(object):
def __init__(self, args):
self.archiver = args[0]
self.arch_type = args[1]
self.llvm_ar_format = args[2]
self.build_root = args[3]
self.plugin = args[4]
self.output = args[5]
auto_input = args[6:]
self.need_modify = False
self.extra_args = []
if self.arch_type.endswith('_AR'):
if self.arch_type == 'GNU_AR':
self.create_flags = ['rcs']
self.modify_flags = ['-M']
elif self.arch_type == 'LLVM_AR':
self.create_flags = ['rcs', '--format=%s' % self.llvm_ar_format]
self.modify_flags = ['-M']
self.need_modify = any(item.endswith('.a') for item in auto_input)
if self.need_modify:
self.objs = filter(lambda x: x.endswith('.o'), auto_input)
self.libs = filter(lambda x: x.endswith('.a'), auto_input)
else:
self.objs = auto_input
self.libs = []
self.output_opts = [self.output]
elif self.arch_type == 'LIBTOOL':
self.create_flags = ['-static']
self.objs = auto_input
self.libs = []
self.output_opts = ['-o', self.output]
elif self.arch_type == 'LIB':
self.create_flags = []
self.extra_args = list( filter(lambda x: x.startswith('/'), auto_input) )
self.objs = list( filter(lambda x: not x.startswith('/'), auto_input) )
self.libs = []
self.output_opts = ['/OUT:' + self.output]
self.plugin_flags = ['--plugin', self.plugin] if self.plugin != 'None' else []
def get_opts(args):
return Opts(args)
if __name__ == "__main__":
opts = get_opts(sys.argv[1:])
# There is a bug in llvm-ar. Some files with size slightly greater 2^32
# still have GNU format instead of GNU64 and cause link problems.
# Workaround just lowers llvm-ar's GNU64 threshold to 2^31.
if opts.arch_type == 'LLVM_AR':
os.environ['SYM64_THRESHOLD'] = '31'
def call():
try:
p = subprocess.Popen(cmd, stdin=stdin, cwd=opts.build_root)
rc = p.wait()
return rc
except OSError as e:
raise Exception('while running %s: %s' % (' '.join(cmd), e))
try:
os.unlink(opts.output)
except OSError:
pass
if not opts.need_modify:
cmd = [opts.archiver] + opts.create_flags + opts.plugin_flags + opts.extra_args + opts.output_opts + opts.objs
stdin = None
exit_code = call()
else:
temp = tempfile.NamedTemporaryFile(dir=os.path.dirname(opts.output), delete=False)
with open(temp.name, 'w') as tmp:
tmp.write('CREATE {0}\n'.format(opts.output))
for lib in opts.libs:
tmp.write('ADDLIB {0}\n'.format(lib))
for obj in opts.objs:
tmp.write('ADDMOD {0}\n'.format(obj))
tmp.write('SAVE\n')
tmp.write('END\n')
cmd = [opts.archiver] + opts.modify_flags + opts.plugin_flags
stdin = open(temp.name)
exit_code = call()
os.remove(temp.name)
if exit_code != 0:
raise Exception('{0} returned non-zero exit code {1}. Stop.'.format(' '.join(cmd), exit_code))
|