PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/extern/llvm/utils/GenLibDeps.pl

https://bitbucket.org/dwilliamson/clreflect/
Perl | 384 lines | 343 code | 18 blank | 23 comment | 42 complexity | e16fde75c742b461d47d0f25b25ab8da MD5 | raw file
Possible License(s): JSON, BSD-3-Clause
  1. #!/usr/bin/perl -w
  2. #
  3. # Program: GenLibDeps.pl
  4. #
  5. # Synopsis: Generate HTML output that shows the dependencies between a set of
  6. # libraries. The output of this script should periodically replace
  7. # the similar content in the UsingLibraries.html document.
  8. #
  9. # Syntax: GenLibDeps.pl [-flat] <directory_with_libraries_in_it> [path_to_nm_binary]
  10. #
  11. use strict;
  12. use warnings;
  13. # Parse arguments...
  14. my $FLAT = 0;
  15. my $WHY = 0;
  16. my $PEROBJ = 0;
  17. my $PEROBJINCL = 0;
  18. while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
  19. shift;
  20. last if /^--$/; # Stop processing arguments on --
  21. # List command line options here...
  22. if (/^-flat$/) { $FLAT = 1; next; }
  23. if (/^-why/) { $WHY = 1; $FLAT = 1; next; }
  24. if (/^-perobj$/) { $PEROBJ = 1; next; }
  25. if (/^-perobjincl/) { $PEROBJINCL = 1; next;}
  26. print "Unknown option: $_ : ignoring!\n";
  27. }
  28. # Give first option a name.
  29. my $Directory = $ARGV[0];
  30. if (!defined($Directory) || ! -d "$Directory") {
  31. die "First argument must specify the directory containing LLVM libs\n";
  32. }
  33. my $nmPath = $ARGV[1];
  34. # Find the "dot" program
  35. my $DotPath="";
  36. if (!$FLAT) {
  37. chomp($DotPath = `which dot`);
  38. die "Can't find 'dot'" if (! -x "$DotPath");
  39. }
  40. if (defined($ENV{NM})) {
  41. chomp($nmPath=$ENV{NM});
  42. }
  43. if (!defined($nmPath) || $nmPath eq "") {
  44. chomp($nmPath=`which nm`);
  45. die "Can't find 'nm'" if (! -x "$nmPath");
  46. }
  47. my $ranlibPath;
  48. if ($PEROBJ) {
  49. $ranlibPath = $ARGV[2];
  50. if (defined($ENV{RANLIB})) {
  51. chomp($ranlibPath=$ENV{RANLIB});
  52. }
  53. if (!defined($ranlibPath) || $ranlibPath eq "") {
  54. chomp($ranlibPath=`which ranlib`);
  55. die "Can't find 'ranlib'" if (! -x "$ranlibPath");
  56. }
  57. }
  58. # Open the directory and read its contents, sorting by name and differentiating
  59. # by whether its a library (.a) or an object file (.o)
  60. opendir DIR,$Directory;
  61. my @files = readdir DIR;
  62. closedir DIR;
  63. my @libs = grep(/libLLVM.*\.(dylib|so|a)$/,sort(@files));
  64. # Omit the all-of-llvm shared library.
  65. @libs = grep(!/libLLVM-\d\.\d(svn)?\.(dylib|so)/, @libs);
  66. my @objs = grep(/LLVM.*\.o$/,sort(@files));
  67. # Declare the hashes we will use to keep track of the library and object file
  68. # symbol definitions.
  69. my %libdefs;
  70. my %objdefs;
  71. my %libobjs;
  72. my %objdeps=();
  73. # Gather library definitions at object file granularity (optional)
  74. if ($PEROBJ) {
  75. foreach my $lib (@libs ) {
  76. `$ranlibPath $Directory/$lib`;
  77. my $libpath = $lib;
  78. $libpath =~ s/^libLLVM(.*)\.a/$1/;
  79. $libpath =~ s/(.+)CodeGen$/Target\/$1/;
  80. $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
  81. $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
  82. $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
  83. $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
  84. $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
  85. $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
  86. $libpath =~ s/^BitReader/Bitcode\/Reader/;
  87. $libpath =~ s/^BitWriter/Bitcode\/Writer/;
  88. $libpath =~ s/^CppBackend/Target\/CppBackend/;
  89. $libpath =~ s/^MSIL/Target\/MSIL/;
  90. $libpath =~ s/^Core/VMCore/;
  91. $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
  92. $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
  93. $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
  94. $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
  95. $libpath =~ s/^TransformUtils/Transforms\/Utils/;
  96. $libpath =~ s/^ipa/Analysis\/IPA/;
  97. $libpath =~ s/^ipo/Transforms\/IPO/;
  98. $libpath = "lib/".$libpath."/";
  99. open DEFS, "$nmPath -sg $Directory/$lib|";
  100. while (<DEFS>) {
  101. chomp;
  102. if (/^([^ ]*) in ([^ ]*)/) {
  103. my $objfile = $libpath.$2;
  104. $objdefs{$1} = $objfile;
  105. $objdeps{$objfile} = {};
  106. $libobjs{$lib}{$objfile}=1;
  107. # my $p = "../llvm/".$objfile;
  108. # $p =~ s/Support\/reg(.*).o/Support\/reg$1.c/;
  109. # $p =~ s/.o$/.cpp/;
  110. # unless (-e $p) {
  111. # die "$p\n"
  112. # }
  113. }
  114. }
  115. close DEFS or die "nm failed";
  116. }
  117. foreach my $lib (@libs ) {
  118. my $libpath = $lib;
  119. $libpath =~ s/^libLLVM(.*)\.a/$1/;
  120. $libpath =~ s/(.+)CodeGen$/Target\/$1/;
  121. $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
  122. $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
  123. $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
  124. $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
  125. $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
  126. $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
  127. $libpath =~ s/^BitReader/Bitcode\/Reader/;
  128. $libpath =~ s/^BitWriter/Bitcode\/Writer/;
  129. $libpath =~ s/^CppBackend/Target\/CppBackend/;
  130. $libpath =~ s/^MSIL/Target\/MSIL/;
  131. $libpath =~ s/^Core/VMCore/;
  132. $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
  133. $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
  134. $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
  135. $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
  136. $libpath =~ s/^TransformUtils/Transforms\/Utils/;
  137. $libpath =~ s/^ipa/Analysis\/IPA/;
  138. $libpath =~ s/^ipo/Transforms\/IPO/;
  139. $libpath = "lib/".$libpath."/";
  140. open UDEFS, "$nmPath -Aup $Directory/$lib|";
  141. while (<UDEFS>) {
  142. chomp;
  143. if (/:([^:]+):/) {
  144. my $obj = $libpath.$1;
  145. s/[^ ]+: *U //;
  146. if (defined($objdefs{$_})) {
  147. $objdeps{$obj}{$objdefs{$_}}=1;
  148. }
  149. }
  150. }
  151. close UDEFS or die "nm failed"
  152. }
  153. } else {
  154. # Gather definitions from the libraries
  155. foreach my $lib (@libs ) {
  156. open DEFS, "$nmPath -g $Directory/$lib|";
  157. while (<DEFS>) {
  158. next if (! / [ABCDGRST] /);
  159. s/^[^ ]* [ABCDGRST] //;
  160. s/\015?\012//; # not sure if <DEFS> is in binmode and uses LF or CRLF.
  161. # this strips both LF and CRLF.
  162. $libdefs{$_} = $lib;
  163. }
  164. close DEFS or die "nm failed";
  165. }
  166. }
  167. # Gather definitions from the object files.
  168. foreach my $obj (@objs ) {
  169. open DEFS, "$nmPath -g $Directory/$obj |";
  170. while (<DEFS>) {
  171. next if (! / [ABCDGRST] /);
  172. s/^[^ ]* [ABCDGRST] //;
  173. s/\015?\012//; # not sure if <DEFS> is in binmode and uses LF or CRLF.
  174. # this strips both LF and CRLF.
  175. $objdefs{$_} = $obj;
  176. }
  177. close DEFS or die "nm failed";
  178. }
  179. # Generate one entry in the <dl> list. This generates the <dt> and <dd> elements
  180. # for one library or object file. The <dt> provides the name of the library or
  181. # object. The <dd> provides a list of the libraries/objects it depends on.
  182. sub gen_one_entry {
  183. my $lib = $_[0];
  184. my $lib_ns = $lib;
  185. $lib_ns =~ s/(.*)\.[oa]/$1/;
  186. if ($FLAT) {
  187. print "$lib:";
  188. if ($WHY) { print "\n"; }
  189. } else {
  190. print " <dt><b>$lib</b></dt><dd><ul>\n";
  191. }
  192. open UNDEFS,
  193. "$nmPath -u $Directory/$lib | sed -e 's/^[ 0]* U //' | sort | uniq |";
  194. my %DepLibs;
  195. while (<UNDEFS>) {
  196. chomp;
  197. my $lib_printed = 0;
  198. if (defined($libdefs{$_}) && $libdefs{$_} ne $lib) {
  199. $DepLibs{$libdefs{$_}} = [] unless exists $DepLibs{$libdefs{$_}};
  200. push(@{$DepLibs{$libdefs{$_}}}, $_);
  201. } elsif (defined($objdefs{$_}) && $objdefs{$_} ne $lib) {
  202. if ($PEROBJ && !$PEROBJINCL) {
  203. # -perobjincl makes .a files depend on .o files they contain themselves
  204. # default is don't depend on these.
  205. next if defined $libobjs{$lib}{$objdefs{$_}};
  206. }
  207. my $libroot = $lib;
  208. $libroot =~ s/lib(.*).a/$1/;
  209. if ($objdefs{$_} ne "$libroot.o") {
  210. $DepLibs{$objdefs{$_}} = [] unless exists $DepLibs{$objdefs{$_}};
  211. push(@{$DepLibs{$objdefs{$_}}}, $_);
  212. }
  213. }
  214. }
  215. close UNDEFS or die "nm failed";
  216. unless(keys %DepLibs) {
  217. # above failed
  218. open UNDEFS, "$nmPath -u $Directory/$lib |";
  219. while (<UNDEFS>) {
  220. # to bypass non-working sed
  221. if (' ' eq substr($_,0,2) and index($_,'U ')) {
  222. $_ = substr($_,index($_,'U ')+2)
  223. };
  224. $_ = substr($_,index($_,' *U ')+5) if -1!=index($_,' *U ');
  225. chomp;
  226. my $lib_printed = 0;
  227. if (defined($libdefs{$_}) && $libdefs{$_} ne $lib) {
  228. $DepLibs{$libdefs{$_}} = [] unless exists $DepLibs{$libdefs{$_}};
  229. push(@{$DepLibs{$libdefs{$_}}}, $_);
  230. } elsif (defined($objdefs{$_}) && $objdefs{$_} ne $lib) {
  231. my $libroot = $lib;
  232. $libroot =~ s/lib(.*).a/$1/;
  233. if ($objdefs{$_} ne "$libroot.o") {
  234. $DepLibs{$objdefs{$_}} = [] unless exists $DepLibs{$objdefs{$_}};
  235. push(@{$DepLibs{$objdefs{$_}}}, $_);
  236. }
  237. }
  238. }
  239. close UNDEFS or die "nm failed";
  240. }
  241. if ($PEROBJINCL) {
  242. # include the .a's objects
  243. for my $obj (keys %{$libobjs{$lib}}) {
  244. $DepLibs{$obj} = ["<.a object>"] unless exists $DepLibs{$obj};
  245. }
  246. my $madechange = 1;
  247. while($madechange) {
  248. $madechange = 0;
  249. my %temp = %DepLibs;
  250. foreach my $obj (keys %DepLibs) {
  251. foreach my $objdeps (keys %{$objdeps{$obj}}) {
  252. next if defined $temp{$objdeps};
  253. push(@{$temp{$objdeps}}, $obj);
  254. $madechange = 1;
  255. }
  256. }
  257. %DepLibs = %temp;
  258. }
  259. }
  260. for my $key (sort keys %DepLibs) {
  261. if ($FLAT) {
  262. print " $key";
  263. if ($WHY) {
  264. print "\n";
  265. my @syms = @{$DepLibs{$key}};
  266. foreach my $sym (@syms) {
  267. print " $sym\n";
  268. }
  269. }
  270. } else {
  271. print " <li>$key</li>\n";
  272. }
  273. my $suffix = substr($key,length($key)-1,1);
  274. $key =~ s/(.*)\.[oa]/$1/;
  275. if ($suffix eq "a") {
  276. if (!$FLAT) { print DOT "$lib_ns -> $key [ weight=0 ];\n" };
  277. } else {
  278. if (!$FLAT) { print DOT "$lib_ns -> $key [ weight=10];\n" };
  279. }
  280. }
  281. if ($FLAT) {
  282. if (!$WHY) {
  283. print "\n";
  284. }
  285. } else {
  286. print " </ul></dd>\n";
  287. }
  288. }
  289. # Make sure we flush on write. This is slower but correct based on the way we
  290. # write I/O in gen_one_entry.
  291. $| = 1;
  292. # Print the definition list tag
  293. if (!$FLAT) {
  294. print "<dl>\n";
  295. open DOT, "| $DotPath -Tgif > libdeps.gif";
  296. print DOT "digraph LibDeps {\n";
  297. print DOT " size=\"40,15\"; \n";
  298. print DOT " ratio=\"1.33333\"; \n";
  299. print DOT " margin=\"0.25\"; \n";
  300. print DOT " rankdir=\"LR\"; \n";
  301. print DOT " mclimit=\"50.0\"; \n";
  302. print DOT " ordering=\"out\"; \n";
  303. print DOT " center=\"1\";\n";
  304. print DOT "node [shape=\"box\",\n";
  305. print DOT " color=\"#000088\",\n";
  306. print DOT " fillcolor=\"#FFFACD\",\n";
  307. print DOT " fontcolor=\"#3355BB\",\n";
  308. print DOT " style=\"filled\",\n";
  309. print DOT " fontname=\"sans\",\n";
  310. print DOT " fontsize=\"24\"\n";
  311. print DOT "];\n";
  312. print DOT "edge [dir=\"forward\",style=\"solid\",color=\"#000088\"];\n";
  313. }
  314. # Print libraries first
  315. foreach my $lib (@libs) {
  316. gen_one_entry($lib);
  317. }
  318. if ($PEROBJ) {
  319. foreach my $obj (keys %objdeps) {
  320. print "$obj:";
  321. if (!$PEROBJINCL) {
  322. foreach my $dep (keys %{$objdeps{$obj}}) {
  323. print " $dep";
  324. }
  325. }
  326. print "\n";
  327. }
  328. }
  329. if (!$FLAT) {
  330. print DOT "}\n";
  331. close DOT;
  332. open DOT, "| $DotPath -Tgif > objdeps.gif";
  333. print DOT "digraph ObjDeps {\n";
  334. print DOT " size=\"8,10\";\n";
  335. print DOT " margin=\"0.25\";\n";
  336. print DOT " rankdir=\"LR\";\n";
  337. print DOT " mclimit=\"50.0\";\n";
  338. print DOT " ordering=\"out\";\n";
  339. print DOT " center=\"1\";\n";
  340. print DOT "node [shape=\"box\",\n";
  341. print DOT " color=\"#000088\",\n";
  342. print DOT " fillcolor=\"#FFFACD\",\n";
  343. print DOT " fontcolor=\"#3355BB\",\n";
  344. print DOT " fontname=\"sans\",\n";
  345. print DOT " style=\"filled\",\n";
  346. print DOT " fontsize=\"24\"\n";
  347. print DOT "];\n";
  348. print DOT "edge [dir=\"forward\",style=\"solid\",color=\"#000088\"];\n";
  349. }
  350. # Print objects second
  351. foreach my $obj (@objs) {
  352. gen_one_entry($obj);
  353. }
  354. if (!$FLAT) {
  355. print DOT "}\n";
  356. close DOT;
  357. # Print end tag of definition list element
  358. print "</dl>\n";
  359. }