• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright 2020 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
7"""
8Finds unreachable gn targets by analysing --ide=json output
9from gn gen.
10
11Usage:
12# Generate json file with targets info, will be located at out/project.json:
13gn gen out --ide=json
14# Lists all targets that are not reachable from //:all or //ci:test_all:
15find_unreachable.py --from //:all --from //ci:test_all --json-file out/project.json
16# Lists targets unreachable from //:all that aren't referenced by any other target:
17find_unreachable.py --from //:all --json-file out/project.json --no-refs
18"""
19
20import argparse
21import json
22import sys
23
24
25def find_reachable_targets(known, graph):
26  reachable = set()
27  to_visit = known
28  while to_visit:
29    next = to_visit.pop()
30    if next in reachable:
31      continue
32    reachable.add(next)
33    to_visit += graph[next]['deps']
34  return reachable
35
36
37def find_source_targets_from(targets, graph):
38  source_targets = set(targets)
39  for target in targets:
40    source_targets -= set(graph[target]['deps'])
41  return source_targets
42
43
44def main():
45  parser = argparse.ArgumentParser(description='''
46    Tool to find unreachable targets.
47    This can be useful to inspect forgotten targets,
48    for example tests or intermediate targets in templates
49    that are no longer needed.
50    ''')
51  parser.add_argument(
52    '--json-file', required=True,
53    help='JSON file from gn gen with --ide=json option')
54  parser.add_argument(
55    '--from', action='append', dest='roots',
56    help='Known "root" targets. Can be multiple. Those targets \
57        and all their recursive dependencies are considered reachable.\
58        Examples: //:all, //ci:test_all')
59  parser.add_argument(
60    '--no-refs', action='store_true',
61    help='Show only targets that aren\'t referenced by any other target')
62  cmd_args = parser.parse_args()
63
64  with open(cmd_args.json_file) as json_file:
65    targets_graph = json.load(json_file)['targets']
66
67  reachable = find_reachable_targets(cmd_args.roots, targets_graph)
68  all = set(targets_graph.keys())
69  unreachable = all - reachable
70
71  result = find_source_targets_from(unreachable, targets_graph) \
72    if cmd_args.no_refs else unreachable
73
74  print '\n'.join(sorted(result))
75
76
77if __name__ == '__main__':
78  sys.exit(main())
79