blob: cd123c1a6b1ca1cb3b218562a500231e6805d516 [file] [log] [blame]
Richard He6663ed02020-07-27 18:55:501#!/usr/bin/env vpython3
Andrew Grievee95e8e282020-07-14 01:27:132# 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# Lint as: python3
7"""Prints out available java targets.
8
9Examples:
10# List GN target for bundles:
Peter Wena57817c2020-07-27 17:47:5211build/android/list_java_targets.py -C out/Default --type android_app_bundle \
12--gn-labels
Andrew Grievee95e8e282020-07-14 01:27:1313
14# List all android targets with types:
Peter Wena57817c2020-07-27 17:47:5215build/android/list_java_targets.py -C out/Default --print-types
Andrew Grievee95e8e282020-07-14 01:27:1316
17# Build all apk targets:
Peter Wena57817c2020-07-27 17:47:5218build/android/list_java_targets.py -C out/Default --type android_apk | xargs \
19autoninja -C out/Default
Andrew Grievee95e8e282020-07-14 01:27:1320
21# Show how many of each target type exist:
Peter Wena57817c2020-07-27 17:47:5222build/android/list_java_targets.py -C out/Default --stats
Andrew Grievee95e8e282020-07-14 01:27:1323
24"""
25
26import argparse
27import collections
28import json
29import logging
30import os
31import subprocess
32import sys
33
34_SRC_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '..',
35 '..'))
36sys.path.append(os.path.join(_SRC_ROOT, 'build', 'android'))
37from pylib import constants
38
39_VALID_TYPES = (
40 'android_apk',
41 'android_app_bundle',
42 'android_app_bundle_module',
43 'android_assets',
44 'android_resources',
45 'dist_aar',
46 'dist_jar',
47 'group',
48 'java_annotation_processor',
49 'java_binary',
50 'java_library',
51 'junit_binary',
52 'system_java_library',
53)
54
55
56def _run_ninja(output_dir, args):
57 cmd = [
58 'autoninja',
59 '-C',
60 output_dir,
61 ]
62 cmd.extend(args)
63 logging.info('Running: %r', cmd)
64 subprocess.run(cmd, check=True, stdout=sys.stderr)
65
66
67def _query_for_build_config_targets(output_dir):
68 # Query ninja rather than GN since it's faster.
69 cmd = ['ninja', '-C', output_dir, '-t', 'targets']
70 logging.info('Running: %r', cmd)
71 ninja_output = subprocess.run(cmd,
72 check=True,
73 capture_output=True,
74 encoding='ascii').stdout
75 ret = []
76 SUFFIX = '__build_config_crbug_908819'
77 SUFFIX_LEN = len(SUFFIX)
78 for line in ninja_output.splitlines():
79 ninja_target = line.rsplit(':', 1)[0]
80 # Ignore root aliases by ensuring a : exists.
81 if ':' in ninja_target and ninja_target.endswith(SUFFIX):
Peter Wena57817c2020-07-27 17:47:5282 ret.append(f'//{ninja_target[:-SUFFIX_LEN]}')
Andrew Grievee95e8e282020-07-14 01:27:1383 return ret
84
85
86class _TargetEntry(object):
Andrew Grievee95e8e282020-07-14 01:27:1387 def __init__(self, gn_target):
Peter Wena57817c2020-07-27 17:47:5288 assert gn_target.startswith('//'), f'{gn_target} does not start with //'
89 assert ':' in gn_target, f'Non-root {gn_target} required'
Andrew Grievee95e8e282020-07-14 01:27:1390 self.gn_target = gn_target
91 self._build_config = None
Andrew Grievee95e8e282020-07-14 01:27:1392
93 @property
94 def ninja_target(self):
95 return self.gn_target[2:]
96
97 @property
98 def ninja_build_config_target(self):
99 return self.ninja_target + '__build_config_crbug_908819'
100
101 def build_config(self):
102 """Reads and returns the project's .build_config JSON."""
103 if not self._build_config:
104 ninja_target = self.ninja_target
105 # Support targets at the root level. e.g. //:foo
106 if ninja_target[0] == ':':
107 ninja_target = ninja_target[1:]
108 subpath = ninja_target.replace(':', os.path.sep) + '.build_config'
109 path = os.path.join('gen', subpath)
110 with open(os.path.join(constants.GetOutDirectory(), path)) as jsonfile:
111 self._build_config = json.load(jsonfile)
112 return self._build_config
113
114 def get_type(self):
115 """Returns the target type from its .build_config."""
116 return self.build_config()['deps_info']['type']
117
Andrew Grievec5e15d1b2020-12-04 18:13:02118 def proguard_enabled(self):
119 """Returns whether proguard runs for this target."""
120 # Modules set proguard_enabled, but the proguarding happens only once at the
121 # bundle level.
122 if self.get_type() == 'android_app_bundle_module':
123 return False
124 return self.build_config()['deps_info'].get('proguard_enabled', False)
125
Andrew Grievee95e8e282020-07-14 01:27:13126
127def main():
128 parser = argparse.ArgumentParser(
129 description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
Peter Wena57817c2020-07-27 17:47:52130 parser.add_argument('-C',
131 '--output-directory',
132 help='If outdir is not provided, will attempt to guess.')
Andrew Grievee95e8e282020-07-14 01:27:13133 parser.add_argument('--gn-labels',
134 action='store_true',
135 help='Print GN labels rather than ninja targets')
136 parser.add_argument(
137 '--nested',
138 action='store_true',
139 help='Do not convert nested targets to their top-level equivalents. '
140 'E.g. Without this, foo_test__apk -> foo_test')
141 parser.add_argument('--print-types',
142 action='store_true',
143 help='Print type of each target')
Andrew Grievec5e15d1b2020-12-04 18:13:02144 parser.add_argument('--build',
Andrew Grievee95e8e282020-07-14 01:27:13145 action='store_true',
146 help='Build all .build_config files.')
147 parser.add_argument('--type',
148 action='append',
149 help='Restrict to targets of given type',
150 choices=_VALID_TYPES)
151 parser.add_argument('--stats',
152 action='store_true',
153 help='Print counts of each target type.')
Andrew Grievec5e15d1b2020-12-04 18:13:02154 parser.add_argument('--proguard-enabled',
155 action='store_true',
156 help='Restrict to targets that have proguard enabled')
Andrew Grievee95e8e282020-07-14 01:27:13157 parser.add_argument('-v', '--verbose', default=0, action='count')
158 args = parser.parse_args()
159
Andrew Grievec5e15d1b2020-12-04 18:13:02160 args.build |= bool(args.type or args.proguard_enabled or args.print_types
161 or args.stats)
Andrew Grievee95e8e282020-07-14 01:27:13162
163 logging.basicConfig(level=logging.WARNING - (10 * args.verbose),
164 format='%(levelname).1s %(relativeCreated)6d %(message)s')
165
166 if args.output_directory:
167 constants.SetOutputDirectory(args.output_directory)
168 constants.CheckOutputDirectory()
169 output_dir = constants.GetOutDirectory()
170
171 # Query ninja for all __build_config_crbug_908819 targets.
172 targets = _query_for_build_config_targets(output_dir)
173 entries = [_TargetEntry(t) for t in targets]
174
Andrew Grievec5e15d1b2020-12-04 18:13:02175 if args.build:
Andrew Grievee95e8e282020-07-14 01:27:13176 logging.warning('Building %d .build_config files...', len(entries))
177 _run_ninja(output_dir, [e.ninja_build_config_target for e in entries])
178
179 if args.type:
180 entries = [e for e in entries if e.get_type() in args.type]
181
Andrew Grievec5e15d1b2020-12-04 18:13:02182 if args.proguard_enabled:
183 entries = [e for e in entries if e.proguard_enabled()]
184
Andrew Grievee95e8e282020-07-14 01:27:13185 if args.stats:
186 counts = collections.Counter(e.get_type() for e in entries)
187 for entry_type, count in sorted(counts.items()):
Peter Wena57817c2020-07-27 17:47:52188 print(f'{entry_type}: {count}')
Andrew Grievee95e8e282020-07-14 01:27:13189 else:
190 for e in entries:
191 if args.gn_labels:
192 to_print = e.gn_target
193 else:
194 to_print = e.ninja_target
195
196 # Convert to top-level target
197 if not args.nested:
Andrew Grievec5e15d1b2020-12-04 18:13:02198 to_print = to_print.replace('__test_apk', '').replace('__apk', '')
Andrew Grievee95e8e282020-07-14 01:27:13199
200 if args.print_types:
Peter Wena57817c2020-07-27 17:47:52201 to_print = f'{to_print}: {e.get_type()}'
Andrew Grievee95e8e282020-07-14 01:27:13202
203 print(to_print)
204
205
206if __name__ == '__main__':
207 main()