gyp-explain.py revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Prints paths between gyp targets.
7"""
8
9import json
10import os
11import sys
12import time
13
14from collections import deque
15
16def usage():
17  print """\
18Usage:
19  tools/gyp-explain.py chrome_dll# gtest#
20"""
21
22
23def GetPath(graph, fro, to):
24  """Given a graph in (node -> list of successor nodes) dictionary format,
25  yields all paths from |fro| to |to|, starting with the shortest."""
26  # Storing full paths in the queue is a bit wasteful, but good enough for this.
27  q = deque([(fro, [])])
28  while q:
29    t, path = q.popleft()
30    if t == to:
31      yield path + [t]
32    for d in graph[t]:
33      q.append((d, path + [t]))
34
35
36def MatchNode(graph, substring):
37  """Given a dictionary, returns the key that matches |substring| best. Exits
38  if there's not one single best match."""
39  candidates = []
40  for target in graph:
41    if substring in target:
42      candidates.append(target)
43
44  if not candidates:
45    print 'No targets match "%s"' % substring
46    sys.exit(1)
47  if len(candidates) > 1:
48    print 'More than one target matches "%s": %s' % (
49        substring, ' '.join(candidates))
50    sys.exit(1)
51  return candidates[0]
52
53
54def Main(argv):
55  # Check that dump.json exists and that it's not too old.
56  dump_json_dirty = False
57  try:
58    st = os.stat('dump.json')
59    file_age_s = time.time() - st.st_mtime
60    if file_age_s > 2 * 60 * 60:
61      print 'dump.json is more than 2 hours old.'
62      dump_json_dirty = True
63  except OSError:
64    print 'dump.json not found.'
65    dump_json_dirty = True
66
67  if dump_json_dirty:
68    print 'Run'
69    print '    GYP_GENERATORS=dump_dependency_json build/gyp_chromium'
70    print 'first, then try again.'
71    sys.exit(1)
72
73  g = json.load(open('dump.json'))
74
75  if len(argv) != 3:
76    usage()
77    sys.exit(1)
78
79  fro = MatchNode(g, argv[1])
80  to = MatchNode(g, argv[2])
81
82  paths = list(GetPath(g, fro, to))
83  if len(paths) > 0:
84    print 'These paths lead from %s to %s:' % (fro, to)
85    for path in paths:
86      print ' -> '.join(path)
87  else:
88    print 'No paths found from %s to %s.' % (fro, to)
89
90
91if __name__ == '__main__':
92  Main(sys.argv)
93