16d528ed9Sopenharmony_ci#!/usr/bin/env python3 26d528ed9Sopenharmony_ci# Copyright 2020 The Chromium Authors. All rights reserved. 36d528ed9Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 46d528ed9Sopenharmony_ci# found in the LICENSE file. 56d528ed9Sopenharmony_ci 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci""" 86d528ed9Sopenharmony_ciFinds unreachable gn targets by analysing --ide=json output 96d528ed9Sopenharmony_cifrom gn gen. 106d528ed9Sopenharmony_ci 116d528ed9Sopenharmony_ciUsage: 126d528ed9Sopenharmony_ci# Generate json file with targets info, will be located at out/project.json: 136d528ed9Sopenharmony_cign gen out --ide=json 146d528ed9Sopenharmony_ci# Lists all targets that are not reachable from //:all or //ci:test_all: 156d528ed9Sopenharmony_cifind_unreachable.py --from //:all --from //ci:test_all --json-file out/project.json 166d528ed9Sopenharmony_ci# Lists targets unreachable from //:all that aren't referenced by any other target: 176d528ed9Sopenharmony_cifind_unreachable.py --from //:all --json-file out/project.json --no-refs 186d528ed9Sopenharmony_ci""" 196d528ed9Sopenharmony_ci 206d528ed9Sopenharmony_ciimport argparse 216d528ed9Sopenharmony_ciimport json 226d528ed9Sopenharmony_ciimport sys 236d528ed9Sopenharmony_ci 246d528ed9Sopenharmony_ci 256d528ed9Sopenharmony_cidef find_reachable_targets(known, graph): 266d528ed9Sopenharmony_ci reachable = set() 276d528ed9Sopenharmony_ci to_visit = known 286d528ed9Sopenharmony_ci while to_visit: 296d528ed9Sopenharmony_ci next = to_visit.pop() 306d528ed9Sopenharmony_ci if next in reachable: 316d528ed9Sopenharmony_ci continue 326d528ed9Sopenharmony_ci reachable.add(next) 336d528ed9Sopenharmony_ci to_visit += graph[next]['deps'] 346d528ed9Sopenharmony_ci return reachable 356d528ed9Sopenharmony_ci 366d528ed9Sopenharmony_ci 376d528ed9Sopenharmony_cidef find_source_targets_from(targets, graph): 386d528ed9Sopenharmony_ci source_targets = set(targets) 396d528ed9Sopenharmony_ci for target in targets: 406d528ed9Sopenharmony_ci source_targets -= set(graph[target]['deps']) 416d528ed9Sopenharmony_ci return source_targets 426d528ed9Sopenharmony_ci 436d528ed9Sopenharmony_ci 446d528ed9Sopenharmony_cidef main(): 456d528ed9Sopenharmony_ci parser = argparse.ArgumentParser(description=''' 466d528ed9Sopenharmony_ci Tool to find unreachable targets. 476d528ed9Sopenharmony_ci This can be useful to inspect forgotten targets, 486d528ed9Sopenharmony_ci for example tests or intermediate targets in templates 496d528ed9Sopenharmony_ci that are no longer needed. 506d528ed9Sopenharmony_ci ''') 516d528ed9Sopenharmony_ci parser.add_argument( 526d528ed9Sopenharmony_ci '--json-file', required=True, 536d528ed9Sopenharmony_ci help='JSON file from gn gen with --ide=json option') 546d528ed9Sopenharmony_ci parser.add_argument( 556d528ed9Sopenharmony_ci '--from', action='append', dest='roots', 566d528ed9Sopenharmony_ci help='Known "root" targets. Can be multiple. Those targets \ 576d528ed9Sopenharmony_ci and all their recursive dependencies are considered reachable.\ 586d528ed9Sopenharmony_ci Examples: //:all, //ci:test_all') 596d528ed9Sopenharmony_ci parser.add_argument( 606d528ed9Sopenharmony_ci '--no-refs', action='store_true', 616d528ed9Sopenharmony_ci help='Show only targets that aren\'t referenced by any other target') 626d528ed9Sopenharmony_ci cmd_args = parser.parse_args() 636d528ed9Sopenharmony_ci 646d528ed9Sopenharmony_ci with open(cmd_args.json_file) as json_file: 656d528ed9Sopenharmony_ci targets_graph = json.load(json_file)['targets'] 666d528ed9Sopenharmony_ci 676d528ed9Sopenharmony_ci reachable = find_reachable_targets(cmd_args.roots, targets_graph) 686d528ed9Sopenharmony_ci all = set(targets_graph.keys()) 696d528ed9Sopenharmony_ci unreachable = all - reachable 706d528ed9Sopenharmony_ci 716d528ed9Sopenharmony_ci result = find_source_targets_from(unreachable, targets_graph) \ 726d528ed9Sopenharmony_ci if cmd_args.no_refs else unreachable 736d528ed9Sopenharmony_ci 746d528ed9Sopenharmony_ci print('\n'.join(sorted(result))) 756d528ed9Sopenharmony_ci 766d528ed9Sopenharmony_ci 776d528ed9Sopenharmony_ciif __name__ == '__main__': 786d528ed9Sopenharmony_ci sys.exit(main()) 79