xref: /aosp_15_r20/external/cronet/build/android/gyp/dist_aar.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1#!/usr/bin/env python3
2#
3# Copyright 2017 The Chromium Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Creates an Android .aar file."""
8
9import argparse
10import os
11import posixpath
12import shutil
13import sys
14import tempfile
15import zipfile
16
17import filter_zip
18from util import build_utils
19import action_helpers  # build_utils adds //build to sys.path.
20import zip_helpers
21
22
23_ANDROID_BUILD_DIR = os.path.dirname(os.path.dirname(__file__))
24
25
26def _MergeRTxt(r_paths, include_globs):
27  """Merging the given R.txt files and returns them as a string."""
28  all_lines = set()
29  for r_path in r_paths:
30    if include_globs and not build_utils.MatchesGlob(r_path, include_globs):
31      continue
32    with open(r_path) as f:
33      all_lines.update(f.readlines())
34  return ''.join(sorted(all_lines))
35
36
37def _MergeProguardConfigs(proguard_configs):
38  """Merging the given proguard config files and returns them as a string."""
39  ret = []
40  for config in proguard_configs:
41    ret.append('# FROM: {}'.format(config))
42    with open(config) as f:
43      ret.append(f.read())
44  return '\n'.join(ret)
45
46
47def _AddResources(aar_zip, resource_zips, include_globs):
48  """Adds all resource zips to the given aar_zip.
49
50  Ensures all res/values/* files have unique names by prefixing them.
51  """
52  for i, path in enumerate(resource_zips):
53    if include_globs and not build_utils.MatchesGlob(path, include_globs):
54      continue
55    with zipfile.ZipFile(path) as res_zip:
56      for info in res_zip.infolist():
57        data = res_zip.read(info)
58        dirname, basename = posixpath.split(info.filename)
59        if 'values' in dirname:
60          root, ext = os.path.splitext(basename)
61          basename = '{}_{}{}'.format(root, i, ext)
62          info.filename = posixpath.join(dirname, basename)
63        info.filename = posixpath.join('res', info.filename)
64        aar_zip.writestr(info, data)
65
66
67def main(args):
68  args = build_utils.ExpandFileArgs(args)
69  parser = argparse.ArgumentParser()
70  action_helpers.add_depfile_arg(parser)
71  parser.add_argument('--output', required=True, help='Path to output aar.')
72  parser.add_argument('--jars', required=True, help='GN list of jar inputs.')
73  parser.add_argument('--dependencies-res-zips', required=True,
74                      help='GN list of resource zips')
75  parser.add_argument('--r-text-files', required=True,
76                      help='GN list of R.txt files to merge')
77  parser.add_argument('--proguard-configs', required=True,
78                      help='GN list of ProGuard flag files to merge.')
79  parser.add_argument(
80      '--android-manifest',
81      help='Path to AndroidManifest.xml to include.',
82      default=os.path.join(_ANDROID_BUILD_DIR, 'AndroidManifest.xml'))
83  parser.add_argument('--native-libraries', default='',
84                      help='GN list of native libraries. If non-empty then '
85                      'ABI must be specified.')
86  parser.add_argument('--abi',
87                      help='ABI (e.g. armeabi-v7a) for native libraries.')
88  parser.add_argument(
89      '--jar-excluded-globs',
90      help='GN-list of globs for paths to exclude in jar.')
91  parser.add_argument(
92      '--jar-included-globs',
93      help='GN-list of globs for paths to include in jar.')
94  parser.add_argument(
95      '--resource-included-globs',
96      help='GN-list of globs for paths to include in R.txt and resources zips.')
97
98  options = parser.parse_args(args)
99
100  if options.native_libraries and not options.abi:
101    parser.error('You must provide --abi if you have native libs')
102
103  options.jars = action_helpers.parse_gn_list(options.jars)
104  options.dependencies_res_zips = action_helpers.parse_gn_list(
105      options.dependencies_res_zips)
106  options.r_text_files = action_helpers.parse_gn_list(options.r_text_files)
107  options.proguard_configs = action_helpers.parse_gn_list(
108      options.proguard_configs)
109  options.native_libraries = action_helpers.parse_gn_list(
110      options.native_libraries)
111  options.jar_excluded_globs = action_helpers.parse_gn_list(
112      options.jar_excluded_globs)
113  options.jar_included_globs = action_helpers.parse_gn_list(
114      options.jar_included_globs)
115  options.resource_included_globs = action_helpers.parse_gn_list(
116      options.resource_included_globs)
117
118  with tempfile.NamedTemporaryFile(delete=False) as staging_file:
119    try:
120      with zipfile.ZipFile(staging_file.name, 'w') as z:
121        zip_helpers.add_to_zip_hermetic(z,
122                                        'AndroidManifest.xml',
123                                        src_path=options.android_manifest)
124
125        path_transform = filter_zip.CreatePathTransform(
126            options.jar_excluded_globs, options.jar_included_globs)
127        with tempfile.NamedTemporaryFile() as jar_file:
128          zip_helpers.merge_zips(jar_file.name,
129                                 options.jars,
130                                 path_transform=path_transform)
131          zip_helpers.add_to_zip_hermetic(z,
132                                          'classes.jar',
133                                          src_path=jar_file.name)
134
135        zip_helpers.add_to_zip_hermetic(z,
136                                        'R.txt',
137                                        data=_MergeRTxt(
138                                            options.r_text_files,
139                                            options.resource_included_globs))
140        zip_helpers.add_to_zip_hermetic(z, 'public.txt', data='')
141
142        if options.proguard_configs:
143          zip_helpers.add_to_zip_hermetic(z,
144                                          'proguard.txt',
145                                          data=_MergeProguardConfigs(
146                                              options.proguard_configs))
147
148        _AddResources(z, options.dependencies_res_zips,
149                      options.resource_included_globs)
150
151        for native_library in options.native_libraries:
152          libname = os.path.basename(native_library)
153          zip_helpers.add_to_zip_hermetic(z,
154                                          os.path.join('jni', options.abi,
155                                                       libname),
156                                          src_path=native_library)
157    except:
158      os.unlink(staging_file.name)
159      raise
160    shutil.move(staging_file.name, options.output)
161
162  if options.depfile:
163    all_inputs = (options.jars + options.dependencies_res_zips +
164                  options.r_text_files + options.proguard_configs)
165    action_helpers.write_depfile(options.depfile, options.output, all_inputs)
166
167
168if __name__ == '__main__':
169  main(sys.argv[1:])
170