Chromium Code Reviews| Index: tools/graphviz.py |
| diff --git a/tools/graphviz.py b/tools/graphviz.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..65daab0cc6896ef531fe668d4ab22e4e04bab2e7 |
| --- /dev/null |
| +++ b/tools/graphviz.py |
| @@ -0,0 +1,94 @@ |
| +#!/usr/bin/python |
| + |
| +# Copyright (c) 2011 Google Inc. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +"""Using the JSON dumped by the dump-dependency-json generator, |
| +generate input suitable for graphviz to render a dependency graph of |
| +targets.""" |
| + |
| +import collections |
| +import json |
| +import sys |
| + |
| +def ParseTarget(target): |
| + target, _, suffix = target.partition('#') |
| + filename, _, target = target.partition(':') |
| + return filename, target, suffix |
| + |
| + |
| +def LoadEdges(filename, targets): |
| + """Load the edges map from the dump file, and filter it to only |
| + show targets in |targets| and their depedendents.""" |
| + |
| + file = open('dump.json') |
| + edges = json.load(file) |
| + file.close() |
| + |
| + # Copy out only the edges we're interested in from the full edge list. |
| + target_edges = {} |
| + to_visit = targets[:] |
| + while to_visit: |
| + src = to_visit.pop() |
| + if src in target_edges: |
| + continue |
| + target_edges[src] = edges[src] |
| + to_visit.extend(edges[src]) |
| + |
| + return target_edges |
| + |
| + |
| +def WriteGraph(edges): |
| + """Print a graphviz graph to stdout. |
| + |edges| is a map of target to a list of other targets it depends on.""" |
| + |
| + # Bucket targets by file. |
| + files = collections.defaultdict(list) |
| + for src, dst in edges.items(): |
| + build_file, target_name, toolset = ParseTarget(src) |
| + files[build_file].append(src) |
| + |
| + print 'digraph D {' |
| + print ' fontsize=8' # Used by subgraphs. |
| + print ' node [fontsize=8]' |
| + |
| + # Output nodes by file. We must first write out each node within |
| + # its file grouping before writing out any edges that may refer |
| + # to those nodes. |
| + for filename, targets in files.items(): |
| + if len(targets) == 1: |
| + # If there's only one node for this file, simplify |
| + # the display by making it a box without an internal node. |
| + target = targets[0] |
| + build_file, target_name, toolset = ParseTarget(target) |
| + print ' "%s" [shape=box, label="%s\\n%s"]' % (target, filename, |
| + target_name) |
| + else: |
| + # Group multiple nodes together in a subgraph. |
| + print ' subgraph "cluster_%s" {' % filename |
| + print ' label = "%s"' % filename |
| + for target in targets: |
| + build_file, target_name, toolset = ParseTarget(target) |
| + print ' "%s" [label="%s"]' % (target, target_name) |
| + print ' }' |
| + |
| + # Now that we've placed all the nodes within subgraphs, output all |
| + # the edges between nodes. |
| + for src, dsts in edges.items(): |
| + for dst in dsts: |
| + print ' "%s" -> "%s"' % (src, dst) |
| + |
| + print '}' |
| + |
| + |
| +if __name__ == '__main__': |
| + if len(sys.argv) < 2: |
| + print __doc__ |
|
Mark Mentovai
2011/05/26 00:38:13
I’d send this stuff to sys.stderr.
|
| + print 'usage: %s target1 target2...' % (sys.argv[0]) |
| + sys.exit(1) |
| + |
| + edges = LoadEdges('dump.json', sys.argv[1:]) |
| + |
| + WriteGraph(edges) |