Project

General

Profile

RE: dng metadata tag ยป depends.py

Robin Mills, 26 Apr 2016 19:55

 
1
#!/usr/bin/python
2

    
3
r"""depends.py - find the ordered dependancies of a library/executable (deepest first)
4

    
5
To use this:
6
	depends.py <pathtolibrary/pathtoexecutable>
7

    
8
"""
9
__author__	= "Robin Mills <robin@clanmills.com>"
10

    
11
import string
12
import os
13
import sys
14
from sets import Set
15

    
16
##
17
# recursively update dependdict for libname (which can be @executable_path etc)
18
# execdir is the directory of @executable_path
19
# loaddir is the directory of @loader_path
20
# returns path to libname or '' (empty string)
21
def depend(execdir,loaddir,libname,dependdict):
22
	""" recursive descent of the libraries """
23
	# print "depend: execdir=%s, loadpath=%s, libname=%s" % (execdir,loadpath,libname)
24

    
25
	##
26
	# discover libpath for libname
27
	epath='@executable_path/'
28
	lpath='@loader_path/'
29
	libpath=libname
30
	if libname[:len(epath)] == epath:
31
		libpath=os.path.join(execdir,libname[len(epath):])
32
	if libname[:len(lpath)] == lpath:
33
		libpath=os.path.join(loadpath,libname[len(lpath):])
34
	libpath=os.path.abspath(libpath)
35

    
36
	if os.path.isfile(libpath):
37
		if not dependdict.has_key(libpath):
38
			dependdict[libpath]=Set([])                 # push now to prevent infinite loop in recursion
39
			cmd = 'otool -L "%s"' % libpath         	# otool -L prints library dependancies:
40
														# libpath:
41
														# <tab>dependancy (metadata) ...
42
			for line in os.popen(cmd).readlines():      # run cmd
43
				if line[:1]=='\t':                      # parse <tab>dependancy (metadata)
44
					dependancy=line.split()[0]
45
					# print libpath,' => ',dependancy
46
					# recurse to find dependancies of dependancy
47
					dpath=depend(execdir,libpath,dependancy,dependdict)
48
					dependdict[libpath].add(dpath)      # update dependdict from recursion
49
	else:
50
		print "*** error NOT a FILE libname=%s libpath=%s ***" % (libname,libpath)
51
		libpath=''
52

    
53
	return libpath
54

    
55
##
56
#
57
def tsort(dependdict): # returns (ordered) array of libraries
58
	filename='/tmp/tsortXX.txt'
59
	file=open(filename,'w')
60
	for key in dependdict.keys():
61
		depends=dependdict[key]
62
		for d in depends:
63
			if len(d) > 0:
64
				file.write( '%s %s\n' % (key,d) )
65
	file.close()
66
	cmd='tsort "%s" 2>/dev/null' % (filename)
67
	lines=os.popen(cmd).readlines()
68
	lines.reverse()
69

    
70
	result=[]
71
	for line in lines:
72
		result.append(line[:-1])
73
	return result;
74
#
75
##
76

    
77
##
78
#
79
def main(argv):
80
	##
81
	# dependdict key is a library path.  Value is a set of dependant library paths
82
	dependdict = {}  # dependdict['/usr/lib/foo.dylib'] = Set([ '/usr/lib/a.dylib', ... ])
83
	libname    = argv[0]
84
	execdir    = os.path.abspath(os.path.join(libname,'..'))
85

    
86
	##
87
	# recursively build the dependency dictionary
88
	depend(execdir,execdir,libname,dependdict)
89

    
90
	##
91
	# sort and report
92
	results=tsort(dependdict)
93
	for result in results:
94
		print result
95
#
96
##
97

    
98
if __name__ == '__main__':
99
	main(sys.argv[1:])
100

    
101
# That's all Folks!
102
##
    (1-1/1)