summaryrefslogtreecommitdiff
path: root/deps/v8/build/android/gyp/aar.py
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/build/android/gyp/aar.py')
-rwxr-xr-xdeps/v8/build/android/gyp/aar.py166
1 files changed, 166 insertions, 0 deletions
diff --git a/deps/v8/build/android/gyp/aar.py b/deps/v8/build/android/gyp/aar.py
new file mode 100755
index 0000000000..d0f357db33
--- /dev/null
+++ b/deps/v8/build/android/gyp/aar.py
@@ -0,0 +1,166 @@
+#!/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
+ if 'native_libraries' in data:
+ data['native_libraries'].append(name)
+ else:
+ data['native_libraries'] = [name]
+ 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())