tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

unused_resources.py (4459B)


      1 #!/usr/bin/env python3
      2 # encoding: utf-8
      3 # Copyright 2021 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 import argparse
      8 import os
      9 import pathlib
     10 import sys
     11 
     12 from util import build_utils
     13 from util import resource_utils
     14 import action_helpers  # build_utils adds //build to sys.path.
     15 
     16 
     17 def _FilterUnusedResources(r_text_in, r_text_out, unused_resources_config):
     18  removed_resources = set()
     19  with open(unused_resources_config, encoding='utf-8') as output_config:
     20    for line in output_config:
     21      # example line: attr/line_height#remove
     22      resource = line.split('#')[0]
     23      resource_type, resource_name = resource.split('/')
     24      removed_resources.add((resource_type, resource_name))
     25  kept_lines = []
     26  with open(r_text_in, encoding='utf-8') as infile:
     27    for line in infile:
     28      # example line: int attr line_height 0x7f0014ee
     29      resource_type, resource_name = line.split(' ')[1:3]
     30      if (resource_type, resource_name) not in removed_resources:
     31        kept_lines.append(line)
     32 
     33  with open(r_text_out, 'w', encoding='utf-8') as out_file:
     34    out_file.writelines(kept_lines)
     35 
     36 
     37 def _WritePaths(dest_path, lines):
     38  pathlib.Path(dest_path).write_text('\n'.join(lines) + '\n')
     39 
     40 
     41 def main(args):
     42  parser = argparse.ArgumentParser()
     43 
     44  action_helpers.add_depfile_arg(parser)
     45  parser.add_argument('--script',
     46                      required=True,
     47                      help='Path to the unused resources detector script.')
     48  parser.add_argument(
     49      '--dependencies-res-zips',
     50      required=True,
     51      action='append',
     52      help='Resources zip archives to investigate for unused resources.')
     53  parser.add_argument('--dexes',
     54                      action='append',
     55                      required=True,
     56                      help='Path to dex file, or zip with dex files.')
     57  parser.add_argument(
     58      '--proguard-mapping',
     59      help='Path to proguard mapping file for the optimized dex.')
     60  parser.add_argument('--r-text-in', required=True, help='Path to input R.txt')
     61  parser.add_argument(
     62      '--r-text-out',
     63      help='Path to output R.txt with unused resources removed.')
     64  parser.add_argument('--android-manifests',
     65                      action='append',
     66                      required=True,
     67                      help='Path to AndroidManifest')
     68  parser.add_argument('--output-config',
     69                      required=True,
     70                      help='Path to output the aapt2 config to.')
     71  args = build_utils.ExpandFileArgs(args)
     72  options = parser.parse_args(args)
     73  options.dependencies_res_zips = (action_helpers.parse_gn_list(
     74      options.dependencies_res_zips))
     75 
     76  # in case of no resources, short circuit early.
     77  if not options.dependencies_res_zips:
     78    build_utils.Touch(options.output_config)
     79    return
     80 
     81  with build_utils.TempDir() as temp_dir:
     82    dep_subdirs = []
     83    for dependency_res_zip in options.dependencies_res_zips:
     84      dep_subdirs += resource_utils.ExtractDeps([dependency_res_zip], temp_dir)
     85 
     86    # Use files for paths to avoid command line getting too long.
     87    # https://crbug.com/362019371
     88    manifests_file = os.path.join(temp_dir, 'manifests-inputs.txt')
     89    resources_file = os.path.join(temp_dir, 'resources-inputs.txt')
     90    dexes_file = os.path.join(temp_dir, 'dexes-inputs.txt')
     91 
     92    _WritePaths(manifests_file, options.android_manifests)
     93    _WritePaths(resources_file, dep_subdirs)
     94    _WritePaths(dexes_file, options.dexes)
     95 
     96    cmd = [
     97        options.script,
     98        '--rtxts',
     99        options.r_text_in,
    100        '--manifests',
    101        manifests_file,
    102        '--resourceDirs',
    103        resources_file,
    104        '--dexes',
    105        dexes_file,
    106        '--outputConfig',
    107        options.output_config,
    108    ]
    109    if options.proguard_mapping:
    110      cmd += [
    111          '--mapping',
    112          options.proguard_mapping,
    113      ]
    114    build_utils.CheckOutput(cmd)
    115 
    116  if options.r_text_out:
    117    _FilterUnusedResources(options.r_text_in, options.r_text_out,
    118                           options.output_config)
    119 
    120  if options.depfile:
    121    depfile_deps = (options.dependencies_res_zips + options.android_manifests +
    122                    options.dexes) + [options.r_text_in]
    123    if options.proguard_mapping:
    124      depfile_deps.append(options.proguard_mapping)
    125    action_helpers.write_depfile(options.depfile, options.output_config,
    126                                 depfile_deps)
    127 
    128 
    129 if __name__ == '__main__':
    130  main(sys.argv[1:])