1 | #!/usr/bin/env python |
---|
2 | ''' |
---|
3 | *macRelink: Remove hardcoded library references* |
---|
4 | =================================================== |
---|
5 | |
---|
6 | ''' |
---|
7 | from __future__ import division, print_function |
---|
8 | import sys, os, glob, subprocess |
---|
9 | #os.path, stat, shutil, subprocess, plistlib |
---|
10 | def Usage(): |
---|
11 | print("\n\tUsage: python "+sys.argv[0]+" <binary-dir>\n") |
---|
12 | sys.exit() |
---|
13 | |
---|
14 | def MakeByte2str(arg): |
---|
15 | '''Convert output from subprocess pipes (bytes) to str (unicode) in Python 3. |
---|
16 | In Python 2: Leaves output alone (already str). |
---|
17 | Leaves stuff of other types alone (including unicode in Py2) |
---|
18 | Works recursively for string-like stuff in nested loops and tuples. |
---|
19 | |
---|
20 | typical use:: |
---|
21 | |
---|
22 | out = MakeByte2str(out) |
---|
23 | |
---|
24 | or:: |
---|
25 | |
---|
26 | out,err = MakeByte2str(s.communicate()) |
---|
27 | |
---|
28 | ''' |
---|
29 | if isinstance(arg,str): return arg |
---|
30 | if isinstance(arg,bytes): return arg.decode() |
---|
31 | if isinstance(arg,list): |
---|
32 | return [MakeByte2str(i) for i in arg] |
---|
33 | if isinstance(arg,tuple): |
---|
34 | return tuple([MakeByte2str(i) for i in arg]) |
---|
35 | return arg |
---|
36 | |
---|
37 | if __name__ == '__main__': |
---|
38 | if len(sys.argv) == 2: |
---|
39 | dirloc = os.path.abspath(sys.argv[1]) |
---|
40 | else: |
---|
41 | Usage() |
---|
42 | raise Exception |
---|
43 | |
---|
44 | fileList = glob.glob(os.path.join(dirloc,'*.so')) |
---|
45 | fileList += glob.glob(os.path.join(dirloc,'convcell')) |
---|
46 | fileList += glob.glob(os.path.join(dirloc,'LATTIC')) |
---|
47 | |
---|
48 | libs = {} |
---|
49 | ignorelist = [] |
---|
50 | for f in fileList: |
---|
51 | cmd = ['otool','-L',f] |
---|
52 | s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE) |
---|
53 | out,err = MakeByte2str(s.communicate()) |
---|
54 | for i in out.split('\n')[1:]: |
---|
55 | if not i: continue |
---|
56 | lib = i.split()[0] |
---|
57 | if os.path.split(lib)[0] == "/usr/lib": # ignore items in system library (usually libSystem.B.dylib) |
---|
58 | if "libSystem" not in lib: print("ignoring ",lib) |
---|
59 | continue |
---|
60 | if "@rpath" in lib and lib not in ignorelist: |
---|
61 | ignorelist.append(lib) |
---|
62 | print("ignoring ",lib) |
---|
63 | continue |
---|
64 | if lib not in libs: |
---|
65 | libs[lib] = [] |
---|
66 | libs[lib].append(f) |
---|
67 | for key in libs: |
---|
68 | newkey = os.path.join('@rpath',os.path.split(key)[1]) |
---|
69 | print('Fixing',key,'to',newkey) |
---|
70 | for f in libs[key]: |
---|
71 | print('\t',os.path.split(f)[1]) |
---|
72 | cmd = ["install_name_tool","-change",key,newkey,f] |
---|
73 | #print(cmd) |
---|
74 | s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE) |
---|
75 | out,err = MakeByte2str(s.communicate()) |
---|