Chromium Code Reviews| Index: tools/gyp-explain.py |
| diff --git a/tools/gyp-explain.py b/tools/gyp-explain.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..84212f5befe6de5ce9a2939c769130bed0a49a68 |
| --- /dev/null |
| +++ b/tools/gyp-explain.py |
| @@ -0,0 +1,95 @@ |
| +#!/usr/bin/env python |
| + |
|
M-A Ruel
2011/11/23 20:28:05
Most script don't put an empty line here, in fact
Nico
2011/11/23 20:33:01
Done.
Mark Mentovai
2011/11/23 21:01:23
I actually prefer the empty line because it lets t
|
| +# 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. |
| + |
| +"""Prints paths between gyp targets. |
| +""" |
| + |
| +import json |
| +import os |
| +import sys |
| +import time |
| + |
| +from collections import deque |
| + |
| +def usage(): |
| + print """\ |
| +Usage: |
| + tools/gyp-explain.sh chrome_dll gtest# |
| +""" |
| + |
| +def GetPath(graph, fro, to, get_all=False): |
| + """Given a graph in (node -> list of successor nodes) dictionary format, |
| + yields either the shortest path from |fro| to |to|, or if |get_all| is True, |
| + all paths from |fro| to |to|.""" |
| + # Storing full paths in the queue is a bit wasteful, but good enough for this. |
| + q = deque([(fro, [])]) |
| + while len(q) > 0: |
| + t, path = q.popleft() |
| + if t == to: |
| + yield path + [t] |
| + if not get_all: |
| + break |
| + for d in graph[t]: |
| + q.append((d, path + [t])) |
| + |
| + |
| +def MatchNode(graph, substring): |
| + """Given a dictionary, returns the key that matches |substring| best. Exits |
| + if there's not one single best match.""" |
| + candidates = [] |
| + for target in graph: |
| + if substring in target: |
| + candidates.append(target) |
| + |
| + if not candidates: |
| + print 'No targets match "%s"' % substring |
| + sys.exit(1) |
| + if len(candidates) > 1: |
| + print 'More than one target matches "%s": %s' % ( |
| + substring, ' '.join(candidates)) |
| + sys.exit(1) |
| + return candidates[0] |
| + |
| + |
| +def Main(argv): |
| + # Check that dump.json exists and that it's not too old. |
| + dump_json_dirty = False |
| + try: |
| + st = os.stat('dump.json') |
| + file_age_s = time.time() - st.st_mtime |
| + if file_age_s > 2 * 60 * 60: |
| + print 'dump.json is more than 2 hours old.' |
| + dump_json_dirty = True |
| + except IOError: |
| + print 'dump.json not found.' |
| + dump_json_dirty = True |
| + |
| + if dump_json_dirty: |
| + print 'Run' |
| + print ' GYP_GENERATORS=dump_dependency_json build/gyp_chromium' |
|
M-A Ruel
2011/11/23 20:28:05
Why not run it automatically? It'd be more user fr
Nico
2011/11/23 20:33:01
I disagree.
M-A Ruel
2011/11/23 20:35:57
Ah, why?
Nico
2011/11/23 20:37:30
No particular reason. I'll roll it now.
|
| + print 'first, then try again.' |
| + sys.exit(1) |
|
M-A Ruel
2011/11/23 20:28:05
I highly prefer to return 1 and have
sys.exit(Ma
Nico
2011/11/23 20:33:01
Yeah, me too, but I already sys.exit from MatchNod
|
| + |
| + g = json.load(open('dump.json')) |
| + |
| + if len(argv) != 3: |
| + usage() |
| + sys.exit(1) |
| + |
| + fro = MatchNode(g, argv[1]) |
| + to = MatchNode(g, argv[2]) |
| + |
| + paths = list(GetPath(g, fro, to, get_all=True)) |
| + if len(paths) > 0: |
| + print 'These paths lead from %s to %s:' % (fro, to) |
| + for path in paths: |
| + print ' -> '.join(path) |
| + else: |
| + print 'No paths found from %s to %s.' % (fro, to) |
|
M-A Ruel
2011/11/23 20:28:05
return 1 so this can be used as a test?
Nico
2011/11/23 20:33:01
Can be added once something needs it :-)
|
| + |
| + |
| +if __name__ == '__main__': |
| + Main(sys.argv) |