blob: ca8b34bb25ac12a24befcb32b5bbf753c48cdfad [file] [log] [blame]
Takuto Ikutafc722252024-01-24 14:49:20 +09001#!/usr/bin/env python3
Alfred Zien6523a5f2020-05-08 21:52:14 +03002# 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
Takuto Ikutafc722252024-01-24 14:49:20 +090074 print('\n'.join(sorted(result)))
Alfred Zien6523a5f2020-05-08 21:52:14 +030075
76
77if __name__ == '__main__':
78 sys.exit(main())