]>
Commit | Line | Data |
---|---|---|
ea1f7807 | 1 | #!/usr/bin/python |
2 | ||
3 | import sys | |
4 | import os | |
5 | import re | |
6 | import string | |
7 | import getopt | |
8 | ||
9 | """ | |
10 | Given a directory, will look into lib*.pkg files to produce a dependency graph | |
11 | of libraries (and DA if there are some) | |
ea1f7807 | 12 | """ |
13 | ||
14 | __author__ = "L. Aphecetche aphecetc_at_in2p3_dot_fr" | |
48739cf2 | 15 | __version__ = "$Id$" |
ea1f7807 | 16 | |
17 | #_______________________________________________________________________________ | |
18 | def usage(): | |
19 | """Describe usage of script | |
20 | """ | |
21 | print "Usage: %s [-h | --help] [-d | --debug] [--noda] directory_to_scan" % sys.argv[0] | |
22 | sys.exit(1) | |
23 | ||
24 | #_______________________________________________________________________________ | |
25 | def getSourceFiles(lib): | |
26 | """Extract the list of classes from a libXXX.pkg file | |
27 | """ | |
28 | ||
29 | f = open(lib) | |
30 | sourcefiles = [] | |
31 | for line in f: | |
32 | l = line.strip() | |
33 | if re.search('Ali',l) and re.search('.cxx',l): | |
34 | l = re.sub('SRCS',' ',l) | |
35 | l = re.sub(':=',' ',l) | |
36 | l = re.sub('=',' ',l) | |
37 | l = re.sub("\\\\",' ',l) | |
38 | l = re.sub(".cxx",' ',l) | |
39 | for i in l.split(): | |
40 | sourcefiles.append(i) | |
41 | f.close() | |
42 | return sourcefiles | |
43 | ||
44 | #_______________________________________________________________________________ | |
45 | def getIncludeFiles(srcfile): | |
46 | """Extract the list of included classes from a class | |
47 | """ | |
48 | ||
49 | includes = [] | |
50 | ||
51 | try: | |
52 | f = open("%s.cxx" % srcfile) | |
53 | except: | |
54 | print "Could not open file %s.cxx" % srcfile | |
55 | return includes | |
56 | ||
57 | for line in f: | |
58 | line = line.strip() | |
59 | if re.search("^#",line) and re.search("#include",line) and re.search('Ali',line): | |
60 | line = re.sub("#include",' ',line) | |
61 | i = line.index(".h") | |
62 | line = line[:i] | |
63 | line = re.sub("\"",' ',line) | |
64 | line = line.strip() | |
65 | includes.append(line) | |
66 | f.close() | |
67 | return includes | |
68 | ||
69 | #_______________________________________________________________________________ | |
70 | def unique(list): | |
71 | """Extract a unique list from list | |
72 | """ | |
73 | d = {} | |
74 | for l in list: | |
75 | d[l] = 1 | |
76 | return d.keys() | |
77 | ||
78 | #_______________________________________________________________________________ | |
79 | def findLibrary(file,allfiles): | |
80 | """Find in which library a given class is defined | |
81 | """ | |
82 | for k,v in allfiles.items(): | |
83 | for f in v: | |
84 | a,f = os.path.split(f) | |
85 | if file == f: | |
86 | return k | |
87 | return "external" | |
88 | ||
89 | #_______________________________________________________________________________ | |
90 | def shorten(libname): | |
8a5956b2 | 91 | """From libYYYxxx.pkg to YYYxxx |
ea1f7807 | 92 | """ |
93 | s = libname | |
8a5956b2 | 94 | if re.search("lib",libname): |
95 | s = re.sub("lib","",s) | |
ea1f7807 | 96 | s = re.sub("\.pkg","",s) |
97 | return s | |
98 | ||
99 | #_______________________________________________________________________________ | |
100 | #_______________________________________________________________________________ | |
101 | #_______________________________________________________________________________ | |
102 | def main(): | |
103 | ||
104 | debug = False | |
105 | noda = False | |
106 | ||
107 | try: | |
108 | opts, args = getopt.getopt(sys.argv[1:],"hd",["help", "debug","noda"]) | |
109 | except getopt.GetoptError: | |
110 | print "Error in options" | |
111 | usage() | |
112 | ||
113 | for o, a in opts: | |
114 | if o in ( "-d","--debug" ): | |
115 | debug = True | |
116 | elif o in ( "-h","--help" ): | |
117 | usage() | |
118 | sys.exit() | |
119 | elif o == "--noda": | |
120 | noda = True | |
121 | else: | |
122 | assert False, "unhandled option" | |
123 | ||
124 | dir = args[0] | |
125 | ||
126 | # find the libraries defined in this directory (looking for libXXXX.pkg files) | |
127 | libraries = [] | |
128 | ||
129 | for file in os.listdir(dir): | |
130 | if re.search('^lib',file) and re.search('.pkg$',file): | |
131 | libraries.append(file) | |
132 | ||
133 | # append fake libraries for DAs | |
134 | if not noda: | |
135 | libraries.append("libMUONTRKda.pkg") | |
136 | libraries.append("libMUONTRGda.pkg") | |
137 | ||
138 | # srcfiles is a dictionary : | |
139 | # srcfiles[libXXX.pkg] -> { list of classes (inferred from list of .cxx files) } | |
140 | # | |
141 | srcfiles = {} | |
142 | ||
143 | # allfiles is a dictonary : | |
144 | # allfiles[libXXX.pkg] -> { list of all included files of that library } | |
145 | allfiles = {} | |
146 | ||
147 | for lib in libraries: | |
148 | if not re.search("da",lib): | |
149 | # handle the special case of DAs which are not part of libs, really | |
150 | srcfiles[lib] = getSourceFiles(lib) | |
151 | else: | |
152 | l = lib | |
153 | l = re.sub("lib","",l) | |
154 | l = re.sub("\.pkg","",l) | |
155 | srcfiles[lib] = [ l ] | |
156 | files = [] | |
157 | for src in srcfiles[lib]: | |
158 | files.extend(getIncludeFiles(src)) | |
159 | allfiles[lib] = unique(files) | |
160 | ||
161 | if debug: | |
162 | for lib in libraries: | |
163 | print lib | |
164 | for f in allfiles[lib]: | |
165 | l = findLibrary(f,srcfiles) | |
166 | print " ",f,"(",l,")" | |
167 | ||
168 | ||
169 | # deps is a dictionary | |
170 | # deps[libXXX.pkg] -> { list of libraries libXXX.pkg directly depends upon } | |
171 | ||
172 | deps = {} | |
173 | ||
174 | for lib,files in allfiles.items(): | |
175 | d = [] | |
176 | for f in files: | |
177 | l = findLibrary(f,srcfiles) | |
178 | if l != lib: | |
179 | d.append(l) | |
180 | deps[lib] = unique(d) | |
181 | ||
182 | if debug: | |
183 | for lib in deps: | |
184 | print lib, " depends on " | |
185 | for l in deps[lib]: | |
186 | print " ",l | |
187 | ||
188 | ||
189 | ofile = "%s.dot" % os.path.splitext(os.path.basename(sys.argv[0]))[0] | |
190 | ||
191 | f = open(ofile,"w") | |
192 | ||
193 | f.write("digraph G {") | |
194 | f.write("rankdir=BT;") | |
195 | ||
196 | for l,d in deps.items(): | |
197 | for dl in d: | |
198 | if re.search("MUON",dl): | |
199 | f.write("node [shape=box,style=filled,fillcolor=yellow];") | |
200 | else: | |
201 | f.write("node [shape=ellipse,style=filled,fillcolor=lightgray];") | |
202 | f.write("%s -> %s;\n" %(shorten(l),shorten(dl))) | |
203 | ||
204 | f.write("}") | |
205 | ||
206 | print "You should now do :" | |
207 | print "tred %s > %s.bis" % ( ofile, ofile ) | |
208 | print "dot -Tpng %s.bis > %s.png" % (ofile,ofile) | |
209 | ||
210 | if __name__ == "__main__": | |
211 | main() | |
212 |