#!/usr/bin/env python3 # Copyright 2020 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
# Lint as: python3 """Prints out available java targets.
Examples: # List GN target for bundles:
build/android/list_java_targets.py -C out/Default --type android_app_bundle \
--gn-labels
# List all android targets with types:
build/android/list_java_targets.py -C out/Default --print-types
def _resolve_ninja(): # Prefer the version on PATH, but fallback to known version if PATH doesn't # have one (e.g. on bots). if shutil.which('ninja') isNone: return os.path.join(_SRC_ROOT, 'third_party', 'ninja', 'ninja') return'ninja'
def _query_for_build_config_targets(output_dir): # Query ninja rather than GN since it's faster. # Use ninja rather than autoninja to avoid extra output if user has set the # NINJA_SUMMARIZE_BUILD environment variable.
cmd = [_resolve_ninja(), '-C', output_dir, '-t', 'targets']
logging.info('Running: %r', cmd)
ninja_output = subprocess.run(cmd,
check=True,
capture_output=True,
encoding='ascii').stdout
ret = []
SUFFIX = '__build_config_crbug_908819'
SUFFIX_LEN = len(SUFFIX) for line in ninja_output.splitlines():
ninja_target = line.rsplit(':', 1)[0] # Ignore root aliases by ensuring a : exists. if':'in ninja_target and ninja_target.endswith(SUFFIX):
ret.append(f'//{ninja_target[:-SUFFIX_LEN]}') return ret
def _query_json(*, json_dict: dict, query: str, path: str): """Traverses through the json dictionary according to the query.
If at any point a key does not exist, return the empty string, but raise an
error if a key exists but is the wrong type.
This is roughly equivalent to returning
json_dict[queries[0]]?[queries[1]]?...[queries[N]]? where the ? means that if
the key doesn't exist, the empty string is returned.
Example:
Given json_dict = {'a': {'b': 'c'}}
- If queries = ['a', 'b'] Return: 'c'
- If queries = ['a', 'd'] Return''
- If queries = ['x'] Return''
- If queries = ['a', 'b', 'x'] Raise an error since json_dict['a']['b'] is the string 'c' instead of an
expected dict that can be indexed into.
Returns the final result after exhausting all the queries. """
queries = query.split('.')
value = json_dict try: for key in queries:
value = value.get(key) if value isNone: return'' except AttributeError as e: raise Exception(
f'Failed when attempting to get {queries} from {path}') from e return value
class _TargetEntry:
def __init__(self, gn_target): assert gn_target.startswith('//'), f'{gn_target} does not start with //' assert':'in gn_target, f'Non-root {gn_target} required'
self.gn_target = gn_target
self._build_config = None
@property def build_config_path(self): """Returns the filepath of the project's .build_config.json."""
ninja_target = self.ninja_target # Support targets at the root level. e.g. //:foo if ninja_target[0] == ':':
ninja_target = ninja_target[1:]
subpath = ninja_target.replace(':', os.path.sep) + '.build_config.json' return os.path.join(constants.GetOutDirectory(), 'gen', subpath)
def build_config(self): """Reads and returns the project's .build_config.json JSON.""" ifnot self._build_config: with open(self.build_config_path) as jsonfile:
self._build_config = json.load(jsonfile) return self._build_config
def get_type(self): """Returns the target type from its .build_config.json.""" return self.build_config()['deps_info']['type']
def proguard_enabled(self): """Returns whether proguard runs for this target.""" # Modules set proguard_enabled, but the proguarding happens only once at the # bundle level. if self.get_type() == 'android_app_bundle_module': returnFalse return self.build_config()['deps_info'].get('proguard_enabled', False)
def main():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-C', '--output-directory',
help='If outdir is not provided, will attempt to guess.')
parser.add_argument('--gn-labels',
action='store_true',
help='Print GN labels rather than ninja targets')
parser.add_argument( '--nested',
action='store_true',
help='Do not convert nested targets to their top-level equivalents. ' 'E.g. Without this, foo_test__apk -> foo_test')
parser.add_argument('--print-types',
action='store_true',
help='Print type of each target')
parser.add_argument( '--print-build-config-paths',
action='store_true',
help='Print path to the .build_config.json of each target')
parser.add_argument('--build',
action='store_true',
help='Build all .build_config.json files.')
parser.add_argument('--type',
action='append',
help='Restrict to targets of given type',
choices=_VALID_TYPES)
parser.add_argument('--stats',
action='store_true',
help='Print counts of each target type.')
parser.add_argument('--proguard-enabled',
action='store_true',
help='Restrict to targets that have proguard enabled.')
parser.add_argument('--query',
help='A dot separated string specifying a query for a ' 'build config json value of each target. Example: Use ' '--query deps_info.unprocessed_jar_path to show a list ' 'of all targets that have a non-empty deps_info dict and ' 'non-empty "unprocessed_jar_path" value in that dict.')
parser.add_argument('-v', '--verbose', default=0, action='count')
parser.add_argument('-q', '--quiet', default=0, action='count')
args = parser.parse_args()
args.build |= bool(args.type or args.proguard_enabled or args.print_types or args.stats or args.query)
if args.output_directory:
constants.SetOutputDirectory(args.output_directory)
constants.CheckOutputDirectory()
output_dir = constants.GetOutDirectory()
if args.build:
_compile(output_dir, ['build.ninja'])
# Query ninja for all __build_config_crbug_908819 targets.
targets = _query_for_build_config_targets(output_dir)
entries = [_TargetEntry(t) for t in targets]
ifnot entries:
logging.warning('No targets found. Run with --build')
sys.exit(1)
if args.build:
logging.warning('Building %d .build_config.json files...', len(entries))
_compile(output_dir, [e.ninja_build_config_target for e in entries],
quiet=args.quiet)
if args.type:
entries = [e for e in entries if e.get_type() in args.type]
if args.proguard_enabled:
entries = [e for e in entries if e.proguard_enabled()]
if args.stats:
counts = collections.Counter(e.get_type() for e in entries) for entry_type, count in sorted(counts.items()):
print(f'{entry_type}: {count}') else: for e in entries: if args.gn_labels:
to_print = e.gn_target else:
to_print = e.ninja_target
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.