xref: /aosp_15_r20/external/angle/build/android/gyp/optimize_resources.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*8975f5c5SAndroid Build Coastguard Worker#
3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2021 The Chromium Authors
4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Workerimport argparse
8*8975f5c5SAndroid Build Coastguard Workerimport logging
9*8975f5c5SAndroid Build Coastguard Workerimport os
10*8975f5c5SAndroid Build Coastguard Workerimport sys
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Workerfrom util import build_utils
13*8975f5c5SAndroid Build Coastguard Workerimport action_helpers  # build_utils adds //build to sys.path.
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Workerdef _ParseArgs(args):
17*8975f5c5SAndroid Build Coastguard Worker  """Parses command line options.
18*8975f5c5SAndroid Build Coastguard Worker
19*8975f5c5SAndroid Build Coastguard Worker  Returns:
20*8975f5c5SAndroid Build Coastguard Worker    An options object as from argparse.ArgumentParser.parse_args()
21*8975f5c5SAndroid Build Coastguard Worker  """
22*8975f5c5SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
23*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--aapt2-path',
24*8975f5c5SAndroid Build Coastguard Worker                      required=True,
25*8975f5c5SAndroid Build Coastguard Worker                      help='Path to the Android aapt2 tool.')
26*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
27*8975f5c5SAndroid Build Coastguard Worker      '--short-resource-paths',
28*8975f5c5SAndroid Build Coastguard Worker      action='store_true',
29*8975f5c5SAndroid Build Coastguard Worker      help='Whether to shorten resource paths inside the apk or module.')
30*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
31*8975f5c5SAndroid Build Coastguard Worker      '--strip-resource-names',
32*8975f5c5SAndroid Build Coastguard Worker      action='store_true',
33*8975f5c5SAndroid Build Coastguard Worker      help='Whether to strip resource names from the resource table of the apk '
34*8975f5c5SAndroid Build Coastguard Worker      'or module.')
35*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--input-path',
36*8975f5c5SAndroid Build Coastguard Worker                      required=True,
37*8975f5c5SAndroid Build Coastguard Worker                      help='Input resources APK.')
38*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--resources-config-paths',
39*8975f5c5SAndroid Build Coastguard Worker                      default='[]',
40*8975f5c5SAndroid Build Coastguard Worker                      help='GN list of paths to aapt2 resources config files.')
41*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--r-text-in',
42*8975f5c5SAndroid Build Coastguard Worker                      required=True,
43*8975f5c5SAndroid Build Coastguard Worker                      help='Path to R.txt. Used to exclude id/ resources.')
44*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
45*8975f5c5SAndroid Build Coastguard Worker      '--resources-path-map-out-path',
46*8975f5c5SAndroid Build Coastguard Worker      help='Path to file produced by aapt2 that maps original resource paths '
47*8975f5c5SAndroid Build Coastguard Worker      'to shortened resource paths inside the apk or module.')
48*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--optimized-output-path',
49*8975f5c5SAndroid Build Coastguard Worker                      required=True,
50*8975f5c5SAndroid Build Coastguard Worker                      help='Output for `aapt2 optimize`.')
51*8975f5c5SAndroid Build Coastguard Worker  options = parser.parse_args(args)
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker  options.resources_config_paths = action_helpers.parse_gn_list(
54*8975f5c5SAndroid Build Coastguard Worker      options.resources_config_paths)
55*8975f5c5SAndroid Build Coastguard Worker
56*8975f5c5SAndroid Build Coastguard Worker  if options.resources_path_map_out_path and not options.short_resource_paths:
57*8975f5c5SAndroid Build Coastguard Worker    parser.error(
58*8975f5c5SAndroid Build Coastguard Worker        '--resources-path-map-out-path requires --short-resource-paths')
59*8975f5c5SAndroid Build Coastguard Worker  return options
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker
62*8975f5c5SAndroid Build Coastguard Workerdef _CombineResourceConfigs(resources_config_paths, out_config_path):
63*8975f5c5SAndroid Build Coastguard Worker  with open(out_config_path, 'w') as out_config:
64*8975f5c5SAndroid Build Coastguard Worker    for config_path in resources_config_paths:
65*8975f5c5SAndroid Build Coastguard Worker      with open(config_path) as config:
66*8975f5c5SAndroid Build Coastguard Worker        out_config.write(config.read())
67*8975f5c5SAndroid Build Coastguard Worker        out_config.write('\n')
68*8975f5c5SAndroid Build Coastguard Worker
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Workerdef _ExtractNonCollapsableResources(rtxt_path):
71*8975f5c5SAndroid Build Coastguard Worker  """Extract resources that should not be collapsed from the R.txt file
72*8975f5c5SAndroid Build Coastguard Worker
73*8975f5c5SAndroid Build Coastguard Worker  Resources of type ID are references to UI elements/views. They are used by
74*8975f5c5SAndroid Build Coastguard Worker  UI automation testing frameworks. They are kept in so that they don't break
75*8975f5c5SAndroid Build Coastguard Worker  tests, even though they may not actually be used during runtime. See
76*8975f5c5SAndroid Build Coastguard Worker  https://crbug.com/900993
77*8975f5c5SAndroid Build Coastguard Worker  App icons (aka mipmaps) are sometimes referenced by other apps by name so must
78*8975f5c5SAndroid Build Coastguard Worker  be keps as well. See https://b/161564466
79*8975f5c5SAndroid Build Coastguard Worker
80*8975f5c5SAndroid Build Coastguard Worker  Args:
81*8975f5c5SAndroid Build Coastguard Worker    rtxt_path: Path to R.txt file with all the resources
82*8975f5c5SAndroid Build Coastguard Worker  Returns:
83*8975f5c5SAndroid Build Coastguard Worker    List of resources in the form of <resource_type>/<resource_name>
84*8975f5c5SAndroid Build Coastguard Worker  """
85*8975f5c5SAndroid Build Coastguard Worker  resources = []
86*8975f5c5SAndroid Build Coastguard Worker  _NO_COLLAPSE_TYPES = ['id', 'mipmap']
87*8975f5c5SAndroid Build Coastguard Worker  with open(rtxt_path) as rtxt:
88*8975f5c5SAndroid Build Coastguard Worker    for line in rtxt:
89*8975f5c5SAndroid Build Coastguard Worker      for resource_type in _NO_COLLAPSE_TYPES:
90*8975f5c5SAndroid Build Coastguard Worker        if ' {} '.format(resource_type) in line:
91*8975f5c5SAndroid Build Coastguard Worker          resource_name = line.split()[2]
92*8975f5c5SAndroid Build Coastguard Worker          resources.append('{}/{}'.format(resource_type, resource_name))
93*8975f5c5SAndroid Build Coastguard Worker  return resources
94*8975f5c5SAndroid Build Coastguard Worker
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Workerdef _OptimizeApk(output, options, temp_dir, unoptimized_path, r_txt_path):
97*8975f5c5SAndroid Build Coastguard Worker  """Optimize intermediate .ap_ file with aapt2.
98*8975f5c5SAndroid Build Coastguard Worker
99*8975f5c5SAndroid Build Coastguard Worker  Args:
100*8975f5c5SAndroid Build Coastguard Worker    output: Path to write to.
101*8975f5c5SAndroid Build Coastguard Worker    options: The command-line options.
102*8975f5c5SAndroid Build Coastguard Worker    temp_dir: A temporary directory.
103*8975f5c5SAndroid Build Coastguard Worker    unoptimized_path: path of the apk to optimize.
104*8975f5c5SAndroid Build Coastguard Worker    r_txt_path: path to the R.txt file of the unoptimized apk.
105*8975f5c5SAndroid Build Coastguard Worker  """
106*8975f5c5SAndroid Build Coastguard Worker  optimize_command = [
107*8975f5c5SAndroid Build Coastguard Worker      options.aapt2_path,
108*8975f5c5SAndroid Build Coastguard Worker      'optimize',
109*8975f5c5SAndroid Build Coastguard Worker      unoptimized_path,
110*8975f5c5SAndroid Build Coastguard Worker      '-o',
111*8975f5c5SAndroid Build Coastguard Worker      output,
112*8975f5c5SAndroid Build Coastguard Worker  ]
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker  # Optimize the resources.pb file by obfuscating resource names and only
115*8975f5c5SAndroid Build Coastguard Worker  # allow usage via R.java constant.
116*8975f5c5SAndroid Build Coastguard Worker  if options.strip_resource_names:
117*8975f5c5SAndroid Build Coastguard Worker    no_collapse_resources = _ExtractNonCollapsableResources(r_txt_path)
118*8975f5c5SAndroid Build Coastguard Worker    gen_config_path = os.path.join(temp_dir, 'aapt2.config')
119*8975f5c5SAndroid Build Coastguard Worker    if options.resources_config_paths:
120*8975f5c5SAndroid Build Coastguard Worker      _CombineResourceConfigs(options.resources_config_paths, gen_config_path)
121*8975f5c5SAndroid Build Coastguard Worker    with open(gen_config_path, 'a') as config:
122*8975f5c5SAndroid Build Coastguard Worker      for resource in no_collapse_resources:
123*8975f5c5SAndroid Build Coastguard Worker        config.write('{}#no_collapse\n'.format(resource))
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker    optimize_command += [
126*8975f5c5SAndroid Build Coastguard Worker        '--collapse-resource-names',
127*8975f5c5SAndroid Build Coastguard Worker        '--resources-config-path',
128*8975f5c5SAndroid Build Coastguard Worker        gen_config_path,
129*8975f5c5SAndroid Build Coastguard Worker    ]
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker  if options.short_resource_paths:
132*8975f5c5SAndroid Build Coastguard Worker    optimize_command += ['--shorten-resource-paths']
133*8975f5c5SAndroid Build Coastguard Worker  if options.resources_path_map_out_path:
134*8975f5c5SAndroid Build Coastguard Worker    optimize_command += [
135*8975f5c5SAndroid Build Coastguard Worker        '--resource-path-shortening-map', options.resources_path_map_out_path
136*8975f5c5SAndroid Build Coastguard Worker    ]
137*8975f5c5SAndroid Build Coastguard Worker
138*8975f5c5SAndroid Build Coastguard Worker  logging.debug('Running aapt2 optimize')
139*8975f5c5SAndroid Build Coastguard Worker  build_utils.CheckOutput(optimize_command,
140*8975f5c5SAndroid Build Coastguard Worker                          print_stdout=False,
141*8975f5c5SAndroid Build Coastguard Worker                          print_stderr=False)
142*8975f5c5SAndroid Build Coastguard Worker
143*8975f5c5SAndroid Build Coastguard Worker
144*8975f5c5SAndroid Build Coastguard Workerdef main(args):
145*8975f5c5SAndroid Build Coastguard Worker  options = _ParseArgs(args)
146*8975f5c5SAndroid Build Coastguard Worker  with build_utils.TempDir() as temp_dir:
147*8975f5c5SAndroid Build Coastguard Worker    _OptimizeApk(options.optimized_output_path, options, temp_dir,
148*8975f5c5SAndroid Build Coastguard Worker                 options.input_path, options.r_text_in)
149*8975f5c5SAndroid Build Coastguard Worker
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
152*8975f5c5SAndroid Build Coastguard Worker  main(sys.argv[1:])
153