aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/link_lib.py
blob: 7d4cf84c5e3e943a9c077be2b4046bf74b199664 (plain) (blame)
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
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:]
 
        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']
        elif self.arch_type == 'LIBTOOL': 
            self.create_flags = ['-static', '-o'] 
            self.modify_flags = [] 
 
        need_modify = self.arch_type != 'LIBTOOL' and any(item.endswith('.a') for item in auto_input)
        if 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.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.libs: 
        cmd = [opts.archiver] + opts.create_flags + opts.plugin_flags + [opts.output] + 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))