Commit cdbfcdfd authored by Andrew Grieve's avatar Andrew Grieve Committed by Commit Bot

Android: Fix SuperSize attribution of .aar classes and resources

The source paths for these should point at the .aar file rather than
the extracted location of its contents.

Bug: 978310
Change-Id: Id3447a96589bce079b7351304a3e2098b33e8f5a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1984820
Commit-Queue: Eric Stevenson <estevenson@chromium.org>
Auto-Submit: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarEric Stevenson <estevenson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#728112}
parent 34fba514
......@@ -91,6 +91,9 @@ def _PerformExtract(aar_file, output_dir, name_whitelist):
os.mkdir(tmp_dir)
build_utils.ExtractAll(
aar_file, path=tmp_dir, predicate=name_whitelist.__contains__)
# Write a breadcrumb so that SuperSize can attribute files back to the .aar.
with open(os.path.join(tmp_dir, 'source.info'), 'w') as f:
f.write('source={}\n'.format(aar_file))
shutil.rmtree(output_dir, ignore_errors=True)
shutil.move(tmp_dir, output_dir)
......@@ -147,10 +150,12 @@ def main():
if args.ignore_resources:
names = [n for n in names if not n.startswith('res')]
output_paths = [os.path.join(args.output_dir, n) for n in names]
output_paths.append(os.path.join(args.output_dir, 'source.info'))
md5_check.CallAndRecordIfStale(
lambda: _PerformExtract(args.aar_file, args.output_dir, set(names)),
input_paths=[args.aar_file],
output_paths=[os.path.join(args.output_dir, n) for n in names])
output_paths=output_paths)
elif args.command == 'list':
aar_output_present = args.output != '-' and os.path.isfile(args.output)
......
......@@ -60,29 +60,41 @@ def _MergeJarInfoFiles(output, inputs):
Args:
output: output file path.
inputs: List of .info.jar or .jar files.
inputs: List of .jar.info or .jar files.
"""
info_data = dict()
for path in inputs:
# android_java_prebuilt adds jar files in the src directory (relative to
# the output directory, usually ../../third_party/example.jar).
# android_aar_prebuilt collects jar files in the aar file and uses the
# java_prebuilt rule to generate gen/example/classes.jar files.
# We scan these prebuilt jars to parse each class path for the FQN. This
# allows us to later map these classes back to their respective src
# directories.
# TODO(agrieve): This should probably also check that the mtime of the .info
# is newer than that of the .jar, or change prebuilts to always output
# .info files so that they always exist (and change the depfile to
# depend directly on them).
# For non-prebuilts: .jar.info files are written by compile_java.py and map
# .class files to .java source paths.
#
# For prebuilts: No .jar.info file exists, we scan the .jar files here and
# map .class files to the .jar.
#
# For .aar files: We look for a "source.info" file in the containing
# directory in order to map classes back to the .aar (rather than mapping
# them to the extracted .jar file).
if path.endswith('.info'):
info_data.update(jar_info_utils.ParseJarInfoFile(path))
else:
attributed_path = path
if not path.startswith('..'):
parent_path = os.path.dirname(path)
# See if it's an sub-jar within the .aar.
if os.path.basename(parent_path) == 'libs':
parent_path = os.path.dirname(parent_path)
aar_source_info_path = os.path.join(parent_path, 'source.info')
# source.info files exist only for jars from android_aar_prebuilt().
# E.g. Could have an java_prebuilt() pointing to a generated .jar.
if os.path.exists(aar_source_info_path):
attributed_path = jar_info_utils.ReadAarSourceInfo(
aar_source_info_path)
with zipfile.ZipFile(path) as zip_info:
for name in zip_info.namelist():
fully_qualified_name = _FullJavaNameFromClassFilePath(name)
if fully_qualified_name:
info_data[fully_qualified_name] = '{}/{}'.format(path, name)
info_data[fully_qualified_name] = '{}/{}'.format(
attributed_path, name)
# only_if_changed=False since no build rules depend on this as an input.
with build_utils.AtomicOutput(output, only_if_changed=False) as f:
......@@ -147,7 +159,7 @@ def main(args):
# Don't bother re-running if no .info files have changed (saves ~250ms).
md5_check.CallAndRecordIfStale(
lambda: _MergeJarInfoFiles(options.jar_info_path, jar_inputs),
input_paths=jar_inputs,
input_paths=jar_inputs + [__file__],
output_paths=[options.jar_info_path])
# Always recreate these (just as fast as md5 checking them).
......
......@@ -16,6 +16,7 @@ import sys
import zipfile
from util import build_utils
from util import jar_info_utils
from util import manifest_utils
from util import md5_check
from util import resource_utils
......@@ -108,10 +109,21 @@ def _ZipResources(resource_dirs, zip_path, ignore_pattern):
files_to_zip = []
path_info = resource_utils.ResourceInfoFile()
for index, resource_dir in enumerate(resource_dirs):
attributed_aar = None
if not resource_dir.startswith('..'):
aar_source_info_path = os.path.join(
os.path.dirname(resource_dir), 'source.info')
if os.path.exists(aar_source_info_path):
attributed_aar = jar_info_utils.ReadAarSourceInfo(aar_source_info_path)
for path, archive_path in resource_utils.IterResourceFilesInDirectories(
[resource_dir], ignore_pattern):
# Put the non-prefixed path in the .info file.
path_info.AddMapping(archive_path, path)
attributed_path = path
if attributed_aar:
attributed_path = os.path.join(attributed_aar, 'res',
path[len(resource_dir) + 1:])
# Use the non-prefixed archive_path in the .info file.
path_info.AddMapping(archive_path, attributed_path)
resource_dir_name = os.path.basename(resource_dir)
archive_path = '{}_{}/{}'.format(index, resource_dir_name, archive_path)
......
......@@ -25,6 +25,7 @@
prepare_resources.py
util/__init__.py
util/build_utils.py
util/jar_info_utils.py
util/manifest_utils.py
util/md5_check.py
util/resource_utils.py
......@@ -13,6 +13,13 @@ import os
# contains its .class definition instead.
def ReadAarSourceInfo(info_path):
"""Returns the source= path from an .aar's source.info file."""
# The .info looks like: "source=path/to/.aar\n".
with open(info_path) as f:
return f.read().rstrip().split('=', 1)[1]
def ParseJarInfoFile(info_path):
"""Parse a given .jar.info file as a dictionary.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment