mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
163 lines
5.2 KiB
Python
Executable File
163 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2016 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.
|
|
|
|
"""Processes an Android AAR file."""
|
|
|
|
import argparse
|
|
import os
|
|
import posixpath
|
|
import re
|
|
import shutil
|
|
import sys
|
|
from xml.etree import ElementTree
|
|
import zipfile
|
|
|
|
from util import build_utils
|
|
from util import md5_check
|
|
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
|
|
os.pardir, os.pardir)))
|
|
import gn_helpers
|
|
|
|
|
|
def _IsManifestEmpty(manifest_str):
|
|
"""Returns whether the given manifest has merge-worthy elements.
|
|
|
|
E.g.: <activity>, <service>, etc.
|
|
"""
|
|
doc = ElementTree.fromstring(manifest_str)
|
|
for node in doc:
|
|
if node.tag == 'application':
|
|
if len(node):
|
|
return False
|
|
elif node.tag != 'uses-sdk':
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def _CreateInfo(aar_file):
|
|
data = {}
|
|
data['aidl'] = []
|
|
data['assets'] = []
|
|
data['resources'] = []
|
|
data['subjars'] = []
|
|
data['subjar_tuples'] = []
|
|
data['has_classes_jar'] = False
|
|
data['has_proguard_flags'] = False
|
|
data['has_native_libraries'] = False
|
|
data['has_r_text_file'] = False
|
|
with zipfile.ZipFile(aar_file) as z:
|
|
data['is_manifest_empty'] = (
|
|
_IsManifestEmpty(z.read('AndroidManifest.xml')))
|
|
|
|
for name in z.namelist():
|
|
if name.endswith('/'):
|
|
continue
|
|
if name.startswith('aidl/'):
|
|
data['aidl'].append(name)
|
|
elif name.startswith('res/'):
|
|
data['resources'].append(name)
|
|
elif name.startswith('libs/') and name.endswith('.jar'):
|
|
label = posixpath.basename(name)[:-4]
|
|
label = re.sub(r'[^a-zA-Z0-9._]', '_', label)
|
|
data['subjars'].append(name)
|
|
data['subjar_tuples'].append([label, name])
|
|
elif name.startswith('assets/'):
|
|
data['assets'].append(name)
|
|
elif name.startswith('jni/'):
|
|
data['has_native_libraries'] = True
|
|
elif name == 'classes.jar':
|
|
data['has_classes_jar'] = True
|
|
elif name == 'proguard.txt':
|
|
data['has_proguard_flags'] = True
|
|
elif name == 'R.txt':
|
|
# Some AARs, e.g. gvr_controller_java, have empty R.txt. Such AARs
|
|
# have no resources as well. We treat empty R.txt as having no R.txt.
|
|
data['has_r_text_file'] = (z.read('R.txt').strip() != '')
|
|
|
|
return """\
|
|
# Generated by //build/android/gyp/aar.py
|
|
# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
|
|
|
|
""" + gn_helpers.ToGNString(data)
|
|
|
|
|
|
def _AddCommonArgs(parser):
|
|
parser.add_argument('aar_file',
|
|
help='Path to the AAR file.',
|
|
type=os.path.normpath)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
command_parsers = parser.add_subparsers(dest='command')
|
|
subp = command_parsers.add_parser(
|
|
'list', help='Output a GN scope describing the contents of the .aar.')
|
|
_AddCommonArgs(subp)
|
|
subp.add_argument('--output',
|
|
help='Output file.',
|
|
default='-')
|
|
|
|
subp = command_parsers.add_parser('extract', help='Extracts the .aar')
|
|
_AddCommonArgs(subp)
|
|
subp.add_argument('--output-dir',
|
|
help='Output directory for the extracted files.',
|
|
required=True,
|
|
type=os.path.normpath)
|
|
subp.add_argument('--assert-info-file',
|
|
help='Path to .info file. Asserts that it matches what '
|
|
'"list" would output.',
|
|
type=argparse.FileType('r'))
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.command == 'extract':
|
|
if args.assert_info_file:
|
|
expected = _CreateInfo(args.aar_file)
|
|
actual = args.assert_info_file.read()
|
|
if actual != expected:
|
|
raise Exception('android_aar_prebuilt() cached .info file is '
|
|
'out-of-date. Run gn gen with '
|
|
'update_android_aar_prebuilts=true to update it.')
|
|
|
|
def clobber():
|
|
# Clear previously extracted versions of the AAR if it is obsolete.
|
|
shutil.rmtree(args.output_dir, ignore_errors=True)
|
|
build_utils.ExtractAll(args.aar_file, path=args.output_dir)
|
|
|
|
with zipfile.ZipFile(args.aar_file) as zf:
|
|
md5_check.CallAndRecordIfStale(
|
|
clobber, input_paths=[args.aar_file],
|
|
output_paths=[
|
|
os.path.join(args.output_dir, n) for n in zf.namelist()])
|
|
|
|
elif args.command == 'list':
|
|
aar_info = _CreateInfo(args.aar_file)
|
|
aar_output_present = args.output != '-' and os.path.isfile(args.output)
|
|
if aar_output_present:
|
|
# Some .info files are read-only, for examples the cipd-controlled ones
|
|
# under third_party/android_deps/repositoty. To deal with these, first
|
|
# that its content is correct, and if it is, exit without touching
|
|
# the file system.
|
|
file_info = open(args.output, 'r').read()
|
|
if file_info == aar_info:
|
|
return
|
|
|
|
# Try to write the file. This may fail for read-only ones that were
|
|
# not updated.
|
|
try:
|
|
with open(args.output, 'w') as f:
|
|
f.write(aar_info)
|
|
except IOError as e:
|
|
if not aar_output_present:
|
|
raise e
|
|
raise Exception('Could not update output file: %s\n%s\n' %
|
|
(args.output, e))
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|