| Index: build/android/pylib/utils/proguard.py
|
| diff --git a/build/android/pylib/utils/proguard.py b/build/android/pylib/utils/proguard.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..34ad5c36316d8672f85c6c8028e7f078013a3487
|
| --- /dev/null
|
| +++ b/build/android/pylib/utils/proguard.py
|
| @@ -0,0 +1,148 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import os
|
| +import re
|
| +import tempfile
|
| +
|
| +from pylib import constants
|
| +from pylib import cmd_helper
|
| +
|
| +
|
| +_PROGUARD_CLASS_RE = re.compile(r'\s*?- Program class:\s*([\S]+)$')
|
| +_PROGUARD_SUPERCLASS_RE = re.compile(r'\s*? Superclass:\s*([\S]+)$')
|
| +_PROGUARD_SECTION_RE = re.compile(
|
| + r'^(?:Interfaces|Constant Pool|Fields|Methods|Class file attributes) '
|
| + r'\(count = \d+\):$')
|
| +_PROGUARD_METHOD_RE = re.compile(r'\s*?- Method:\s*(\S*)[(].*$')
|
| +_PROGUARD_ANNOTATION_RE = re.compile(r'\s*?- Annotation \[L(\S*);\]:$')
|
| +_PROGUARD_ANNOTATION_CONST_RE = (
|
| + re.compile(r'\s*?- Constant element value.*$'))
|
| +_PROGUARD_ANNOTATION_VALUE_RE = re.compile(r'\s*?- \S+? \[(.*)\]$')
|
| +
|
| +_PROGUARD_PATH_SDK = os.path.join(
|
| + constants.ANDROID_SDK_ROOT, 'tools', 'proguard', 'lib', 'proguard.jar')
|
| +_PROGUARD_PATH_BUILT = (
|
| + os.path.join(os.environ['ANDROID_BUILD_TOP'], 'external', 'proguard',
|
| + 'lib', 'proguard.jar')
|
| + if 'ANDROID_BUILD_TOP' in os.environ else None)
|
| +_PROGUARD_PATH = (
|
| + _PROGUARD_PATH_SDK if os.path.exists(_PROGUARD_PATH_SDK)
|
| + else _PROGUARD_PATH_BUILT)
|
| +
|
| +
|
| +def Dump(jar_path):
|
| + """Dumps class and method information from a JAR into a dict via proguard.
|
| +
|
| + Args:
|
| + jar_path: An absolute path to the JAR file to dump.
|
| + Returns:
|
| + A dict in the following format:
|
| + {
|
| + 'classes': [
|
| + {
|
| + 'class': '',
|
| + 'superclass': '',
|
| + 'annotations': {},
|
| + 'methods': [
|
| + {
|
| + 'method': '',
|
| + 'annotations': {},
|
| + },
|
| + ...
|
| + ],
|
| + },
|
| + ...
|
| + ],
|
| + }
|
| + """
|
| +
|
| + with tempfile.NamedTemporaryFile() as proguard_output:
|
| + cmd_helper.RunCmd(['java', '-jar',
|
| + _PROGUARD_PATH,
|
| + '-injars', jar_path,
|
| + '-dontshrink',
|
| + '-dontoptimize',
|
| + '-dontobfuscate',
|
| + '-dontpreverify',
|
| + '-dump', proguard_output.name])
|
| +
|
| +
|
| + results = {
|
| + 'classes': [],
|
| + }
|
| +
|
| + annotation = None
|
| + annotation_has_value = False
|
| + class_result = None
|
| + method_result = None
|
| +
|
| + for line in proguard_output:
|
| + line = line.strip('\r\n')
|
| +
|
| + m = _PROGUARD_CLASS_RE.match(line)
|
| + if m:
|
| + class_result = {
|
| + 'class': m.group(1).replace('/', '.'),
|
| + 'superclass': '',
|
| + 'annotations': {},
|
| + 'methods': [],
|
| + }
|
| + results['classes'].append(class_result)
|
| + annotation = None
|
| + annotation_has_value = False
|
| + method_result = None
|
| + continue
|
| +
|
| + if not class_result:
|
| + continue
|
| +
|
| + m = _PROGUARD_SUPERCLASS_RE.match(line)
|
| + if m:
|
| + class_result['superclass'] = m.group(1).replace('/', '.')
|
| + continue
|
| +
|
| + m = _PROGUARD_SECTION_RE.match(line)
|
| + if m:
|
| + annotation = None
|
| + annotation_has_value = False
|
| + method_result = None
|
| + continue
|
| +
|
| + m = _PROGUARD_METHOD_RE.match(line)
|
| + if m:
|
| + method_result = {
|
| + 'method': m.group(1),
|
| + 'annotations': {},
|
| + }
|
| + class_result['methods'].append(method_result)
|
| + annotation = None
|
| + annotation_has_value = False
|
| + continue
|
| +
|
| + m = _PROGUARD_ANNOTATION_RE.match(line)
|
| + if m:
|
| + # Ignore the annotation package.
|
| + annotation = m.group(1).split('/')[-1]
|
| + if method_result:
|
| + method_result['annotations'][annotation] = None
|
| + else:
|
| + class_result['annotations'][annotation] = None
|
| + continue
|
| +
|
| + if annotation:
|
| + if not annotation_has_value:
|
| + m = _PROGUARD_ANNOTATION_CONST_RE.match(line)
|
| + annotation_has_value = bool(m)
|
| + else:
|
| + m = _PROGUARD_ANNOTATION_VALUE_RE.match(line)
|
| + if m:
|
| + if method_result:
|
| + method_result['annotations'][annotation] = m.group(1)
|
| + else:
|
| + class_result['annotations'][annotation] = m.group(1)
|
| + annotation_has_value = None
|
| +
|
| + return results
|
| +
|
|
|