Commit 235ea291 authored by newt@chromium.org's avatar newt@chromium.org

Update find_unused_resources.py to ignore third party resources.

find_unused_resources.py thinks that resources defined in third party
libraries are all unused. This updates the script to ignore those
resources.

BUG=149661
R=bulach@chromium.org, cjhopman@chromium.org

Review URL: https://codereview.chromium.org/23591017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221769 0039d316-1c4b-4281-b951-d872f2087c98
parent b245e75b
...@@ -11,25 +11,32 @@ import subprocess ...@@ -11,25 +11,32 @@ import subprocess
import sys import sys
def GetApkResources(apk_path): def GetLibraryResources(r_txt_paths):
"""Returns the types and names of resources packaged in an APK. """Returns the resources packaged in a list of libraries.
Args: Args:
apk_path: path to the APK. r_txt_paths: paths to each library's generated R.txt file which lists the
resources it contains.
Returns: Returns:
The resources in the APK as a list of tuples (type, name). Example: The resources in the libraries as a list of tuples (type, name). Example:
[('drawable', 'arrow'), ('layout', 'month_picker'), ...] [('drawable', 'arrow'), ('layout', 'month_picker'), ...]
""" """
p = subprocess.Popen( resources = []
['aapt', 'dump', 'resources', apk_path], for r_txt_path in r_txt_paths:
stdout=subprocess.PIPE) with open(r_txt_path, 'r') as f:
dump_out, _ = p.communicate() for line in f:
assert p.returncode == 0, 'aapt dump failed' line = line.strip()
matches = re.finditer( if not line:
r'^\s+spec resource 0x[0-9a-fA-F]+ [\w.]+:(?P<type>\w+)/(?P<name>\w+)', continue
dump_out, re.MULTILINE) data_type, res_type, name, _ = line.split(None, 3)
return [m.group('type', 'name') for m in matches] assert data_type in ('int', 'int[]')
# Hide attrs, which are redundant with styleables and always appear
# unused, and hide ids, which are innocuous even if unused.
if res_type in ('attr', 'id'):
continue
resources.append((res_type, name))
return resources
def GetUsedResources(source_paths, resource_types): def GetUsedResources(source_paths, resource_types):
...@@ -79,43 +86,55 @@ def FormatResources(resources): ...@@ -79,43 +86,55 @@ def FormatResources(resources):
def ParseArgs(args): def ParseArgs(args):
usage = 'usage: %prog [-v] APK_PATH SOURCE_PATH...' parser = optparse.OptionParser()
parser = optparse.OptionParser(usage=usage)
parser.add_option('-v', help='Show verbose output', action='store_true') parser.add_option('-v', help='Show verbose output', action='store_true')
parser.add_option('-s', '--source-path', help='Specify a source folder path '
'(e.g. ui/android/java)', action='append', default=[])
parser.add_option('-r', '--r-txt-path', help='Specify a "first-party" R.txt '
'file (e.g. out/Debug/content_shell_apk/R.txt)',
action='append', default=[])
parser.add_option('-t', '--third-party-r-txt-path', help='Specify an R.txt '
'file for a third party library', action='append',
default=[])
options, args = parser.parse_args(args=args) options, args = parser.parse_args(args=args)
if len(args) < 2: if args:
parser.error('must provide APK_PATH and SOURCE_PATH arguments') parser.error('positional arguments not allowed')
return options.v, args[0], args[1:] if not options.source_path:
parser.error('at least one source folder path must be specified with -s')
if not options.r_txt_path:
parser.error('at least one R.txt path must be specified with -r')
return (options.v, options.source_path, options.r_txt_path,
options.third_party_r_txt_path)
def main(args=None): def main(args=None):
verbose, apk_path, source_paths = ParseArgs(args) verbose, source_paths, r_txt_paths, third_party_r_txt_paths = ParseArgs(args)
apk_resources = GetApkResources(apk_path) defined_resources = (set(GetLibraryResources(r_txt_paths)) -
resource_types = list(set([r[0] for r in apk_resources])) set(GetLibraryResources(third_party_r_txt_paths)))
used_resources = GetUsedResources(source_paths, resource_types) resource_types = list(set([r[0] for r in defined_resources]))
unused_resources = set(apk_resources) - set(used_resources) used_resources = set(GetUsedResources(source_paths, resource_types))
undefined_resources = set(used_resources) - set(apk_resources) unused_resources = defined_resources - used_resources
undefined_resources = used_resources - defined_resources
# aapt dump fails silently. Notify the user if things look wrong. # aapt dump fails silently. Notify the user if things look wrong.
if not apk_resources: if not defined_resources:
print >> sys.stderr, ( print >> sys.stderr, (
'Warning: No resources found in the APK. Did you provide the correct ' 'Warning: No resources found. Did you provide the correct R.txt paths?')
'APK path?')
if not used_resources: if not used_resources:
print >> sys.stderr, ( print >> sys.stderr, (
'Warning: No resources references from Java or resource files. Did you ' 'Warning: No resources referenced from Java or resource files. Did you '
'provide the correct source paths?') 'provide the correct source paths?')
if undefined_resources: if undefined_resources:
print >> sys.stderr, ( print >> sys.stderr, (
'Warning: found %d "undefined" resources that are referenced by Java ' 'Warning: found %d "undefined" resources that are referenced by Java '
'files or by other resources, but are not in the APK. Run with -v to ' 'files or by other resources, but are not defined anywhere. Run with '
'see them.' % len(undefined_resources)) '-v to see them.' % len(undefined_resources))
if verbose: if verbose:
print '%d undefined resources:' % len(undefined_resources) print '%d undefined resources:' % len(undefined_resources)
print FormatResources(undefined_resources), '\n' print FormatResources(undefined_resources), '\n'
print '%d resources packaged into the APK:' % len(apk_resources) print '%d resources defined:' % len(defined_resources)
print FormatResources(apk_resources), '\n' print FormatResources(defined_resources), '\n'
print '%d used resources:' % len(used_resources) print '%d used resources:' % len(used_resources)
print FormatResources(used_resources), '\n' print FormatResources(used_resources), '\n'
print '%d unused resources:' % len(unused_resources) print '%d unused resources:' % len(unused_resources)
......
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