OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 | |
3 # Copyright (c) 2011 Google Inc. All rights reserved. | |
4 # Use of this source code is governed by a BSD-style license that can be | |
5 # found in the LICENSE file. | |
6 | |
7 """Using the JSON dumped by the dump-dependency-json generator, | |
8 generate input suitable for graphviz to render a dependency graph of | |
9 targets.""" | |
10 | |
11 import collections | |
12 import json | |
13 import sys | |
14 | |
15 def ParseTarget(target): | |
16 target, _, suffix = target.partition('#') | |
17 filename, _, target = target.partition(':') | |
18 return filename, target, suffix | |
19 | |
20 | |
21 def LoadEdges(filename, targets): | |
22 """Load the edges map from the dump file, and filter it to only | |
23 show targets in |targets| and their depedendents.""" | |
24 | |
25 file = open('dump.json') | |
26 edges = json.load(file) | |
27 file.close() | |
28 | |
29 # Copy out only the edges we're interested in from the full edge list. | |
30 target_edges = {} | |
31 to_visit = targets[:] | |
32 while to_visit: | |
33 src = to_visit.pop() | |
34 if src in target_edges: | |
35 continue | |
36 target_edges[src] = edges[src] | |
37 to_visit.extend(edges[src]) | |
38 | |
39 return target_edges | |
40 | |
41 | |
42 def WriteGraph(edges): | |
43 """Print a graphviz graph to stdout. | |
44 |edges| is a map of target to a list of other targets it depends on.""" | |
45 | |
46 # Bucket targets by file. | |
47 files = collections.defaultdict(list) | |
48 for src, dst in edges.items(): | |
49 build_file, target_name, toolset = ParseTarget(src) | |
50 files[build_file].append(src) | |
51 | |
52 print 'digraph D {' | |
53 print ' fontsize=8' # Used by subgraphs. | |
54 print ' node [fontsize=8]' | |
55 | |
56 # Output nodes by file. We must first write out each node within | |
57 # its file grouping before writing out any edges that may refer | |
58 # to those nodes. | |
59 for filename, targets in files.items(): | |
60 if len(targets) == 1: | |
61 # If there's only one node for this file, simplify | |
62 # the display by making it a box without an internal node. | |
63 target = targets[0] | |
64 build_file, target_name, toolset = ParseTarget(target) | |
65 print ' "%s" [shape=box, label="%s\\n%s"]' % (target, filename, | |
66 target_name) | |
67 else: | |
68 # Group multiple nodes together in a subgraph. | |
69 print ' subgraph "cluster_%s" {' % filename | |
70 print ' label = "%s"' % filename | |
71 for target in targets: | |
72 build_file, target_name, toolset = ParseTarget(target) | |
73 print ' "%s" [label="%s"]' % (target, target_name) | |
74 print ' }' | |
75 | |
76 # Now that we've placed all the nodes within subgraphs, output all | |
77 # the edges between nodes. | |
78 for src, dsts in edges.items(): | |
79 for dst in dsts: | |
80 print ' "%s" -> "%s"' % (src, dst) | |
81 | |
82 print '}' | |
83 | |
84 | |
85 if __name__ == '__main__': | |
86 if len(sys.argv) < 2: | |
87 print __doc__ | |
Mark Mentovai
2011/05/26 00:38:13
I’d send this stuff to sys.stderr.
| |
88 print | |
89 print 'usage: %s target1 target2...' % (sys.argv[0]) | |
90 sys.exit(1) | |
91 | |
92 edges = LoadEdges('dump.json', sys.argv[1:]) | |
93 | |
94 WriteGraph(edges) | |
OLD | NEW |