blob: d0689a6e0c8a5f668e847e534af68185706c9d35 [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
Henrique Nakashima5f3062292021-03-25 21:55:45101 @property
102 def build_config_path(self):
103 """Returns the filepath of the project's .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 return os.path.join(constants.GetOutDirectory(), 'gen', subpath)
110
Andrew Grievee95e8e282020-07-14 01:27:13111 def build_config(self):
112 """Reads and returns the project's .build_config JSON."""
113 if not self._build_config:
Henrique Nakashima5f3062292021-03-25 21:55:45114 with open(self.build_config_path) as jsonfile:
Andrew Grievee95e8e282020-07-14 01:27:13115 self._build_config = json.load(jsonfile)
116 return self._build_config
117
118 def get_type(self):
119 """Returns the target type from its .build_config."""
120 return self.build_config()['deps_info']['type']
121
Andrew Grievec5e15d1b2020-12-04 18:13:02122 def proguard_enabled(self):
123 """Returns whether proguard runs for this target."""
124 # Modules set proguard_enabled, but the proguarding happens only once at the
125 # bundle level.
126 if self.get_type() == 'android_app_bundle_module':
127 return False
128 return self.build_config()['deps_info'].get('proguard_enabled', False)
129
Andrew Grievee95e8e282020-07-14 01:27:13130
131def main():
132 parser = argparse.ArgumentParser(
133 description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
Peter Wena57817c2020-07-27 17:47:52134 parser.add_argument('-C',
135 '--output-directory',
136 help='If outdir is not provided, will attempt to guess.')
Andrew Grievee95e8e282020-07-14 01:27:13137 parser.add_argument('--gn-labels',
138 action='store_true',
139 help='Print GN labels rather than ninja targets')
140 parser.add_argument(
141 '--nested',
142 action='store_true',
143 help='Do not convert nested targets to their top-level equivalents. '
144 'E.g. Without this, foo_test__apk -> foo_test')
145 parser.add_argument('--print-types',
146 action='store_true',
147 help='Print type of each target')
Henrique Nakashima5f3062292021-03-25 21:55:45148 parser.add_argument('--print-build-config-paths',
149 action='store_true',
150 help='Print path to the .build_config of each target')
Andrew Grievec5e15d1b2020-12-04 18:13:02151 parser.add_argument('--build',
Andrew Grievee95e8e282020-07-14 01:27:13152 action='store_true',
153 help='Build all .build_config files.')
154 parser.add_argument('--type',
155 action='append',
156 help='Restrict to targets of given type',
157 choices=_VALID_TYPES)
158 parser.add_argument('--stats',
159 action='store_true',
160 help='Print counts of each target type.')
Andrew Grievec5e15d1b2020-12-04 18:13:02161 parser.add_argument('--proguard-enabled',
162 action='store_true',
163 help='Restrict to targets that have proguard enabled')
Andrew Grievee95e8e282020-07-14 01:27:13164 parser.add_argument('-v', '--verbose', default=0, action='count')
165 args = parser.parse_args()
166
Andrew Grievec5e15d1b2020-12-04 18:13:02167 args.build |= bool(args.type or args.proguard_enabled or args.print_types
168 or args.stats)
Andrew Grievee95e8e282020-07-14 01:27:13169
170 logging.basicConfig(level=logging.WARNING - (10 * args.verbose),
171 format='%(levelname).1s %(relativeCreated)6d %(message)s')
172
173 if args.output_directory:
174 constants.SetOutputDirectory(args.output_directory)
175 constants.CheckOutputDirectory()
176 output_dir = constants.GetOutDirectory()
177
178 # Query ninja for all __build_config_crbug_908819 targets.
179 targets = _query_for_build_config_targets(output_dir)
180 entries = [_TargetEntry(t) for t in targets]
181
Andrew Grievec5e15d1b2020-12-04 18:13:02182 if args.build:
Andrew Grievee95e8e282020-07-14 01:27:13183 logging.warning('Building %d .build_config files...', len(entries))
184 _run_ninja(output_dir, [e.ninja_build_config_target for e in entries])
185
186 if args.type:
187 entries = [e for e in entries if e.get_type() in args.type]
188
Andrew Grievec5e15d1b2020-12-04 18:13:02189 if args.proguard_enabled:
190 entries = [e for e in entries if e.proguard_enabled()]
191
Andrew Grievee95e8e282020-07-14 01:27:13192 if args.stats:
193 counts = collections.Counter(e.get_type() for e in entries)
194 for entry_type, count in sorted(counts.items()):
Peter Wena57817c2020-07-27 17:47:52195 print(f'{entry_type}: {count}')
Andrew Grievee95e8e282020-07-14 01:27:13196 else:
197 for e in entries:
198 if args.gn_labels:
199 to_print = e.gn_target
200 else:
201 to_print = e.ninja_target
202
203 # Convert to top-level target
204 if not args.nested:
Andrew Grievec5e15d1b2020-12-04 18:13:02205 to_print = to_print.replace('__test_apk', '').replace('__apk', '')
Andrew Grievee95e8e282020-07-14 01:27:13206
207 if args.print_types:
Peter Wena57817c2020-07-27 17:47:52208 to_print = f'{to_print}: {e.get_type()}'
Henrique Nakashima5f3062292021-03-25 21:55:45209 elif args.print_build_config_paths:
210 to_print = f'{to_print}: {e.build_config_path}'
Andrew Grievee95e8e282020-07-14 01:27:13211
212 print(to_print)
213
214
215if __name__ == '__main__':
216 main()