12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)"""Process Android resources to generate R.java, and prepare for packaging.
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)This will crunch images and generate v14 compatible resources
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)(see generate_v14_compatible_resources.py).
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)"""
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import optparse
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import re
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import zipfile
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import generate_v14_compatible_resources
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from util import build_utils
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def ParseArgs():
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Parses command line options.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Returns:
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    An options object as from optparse.OptionsParser.parse_args()
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser = optparse.OptionParser()
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser.add_option('--android-sdk', help='path to the Android SDK folder')
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser.add_option('--android-sdk-tools',
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    help='path to the Android SDK build tools folder')
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser.add_option('--non-constant-id', action='store_true')
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser.add_option('--android-manifest', help='AndroidManifest.xml path')
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--custom-package', help='Java package for R.java')
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--resource-dirs',
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    help='Directories containing resources of this target.')
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--dependencies-res-zips',
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    help='Resources from dependents.')
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--R-dir', help='directory to hold generated R.java')
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--resource-zip-out',
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                    help='Path for output zipped resources.')
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  parser.add_option('--proguard-file',
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    help='Path to proguard.txt generated file')
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option(
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      '--v14-verify-only',
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      action='store_true',
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      help='Do not generate v14 resources. Instead, just verify that the '
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'resources are already compatible with v14, i.e. they don\'t use '
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'attributes that cause crashes on certain devices.')
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  parser.add_option(
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      '--extra-res-packages',
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      help='Additional package names to generate R.java files for')
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  parser.add_option(
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      '--extra-r-text-files',
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      help='For each additional package, the R.txt file should contain a '
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'list of resources to be included in the R.java file in the format '
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'generated by aapt')
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  parser.add_option('--stamp', help='File to touch on success')
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (options, args) = parser.parse_args()
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if args:
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parser.error('No positional arguments should be given.')
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  # Check that required options have been provided.
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  required_options = (
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'android_sdk',
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'android_sdk_tools',
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'android_manifest',
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'dependencies_res_zips',
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'resource_dirs',
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'resource_zip_out',
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      'R_dir',
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      )
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  build_utils.CheckOptions(options, parser, required=required_options)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return options
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def CreateExtraRJavaFiles(
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    r_dir, extra_packages, extra_r_text_files):
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if len(extra_packages) != len(extra_r_text_files):
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    raise Exception('--extra-res-packages and --extra-r-text-files'
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    'should have the same length')
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  java_files = build_utils.FindInDirectory(r_dir, "R.java")
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if len(java_files) != 1:
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  r_java_file = java_files[0]
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  r_java_contents = open(r_java_file).read()
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for package in extra_packages:
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    package_r_java_dir = os.path.join(r_dir, *package.split('.'))
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    build_utils.MakeDirectory(package_r_java_dir)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    open(package_r_java_path, 'w').write(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        re.sub(r'package [.\w]*;', 'package %s;' % package, r_java_contents))
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # TODO(cjhopman): These extra package's R.java files should be filtered to
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # only contain the resources listed in their R.txt files. At this point, we
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # have already compiled those other libraries, so doing this would only
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # affect how the code in this .apk target could refer to the resources.
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochdef DidCrunchFail(returncode, stderr):
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  """Determines whether aapt crunch failed from its return code and output.
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Because aapt's return code cannot be trusted, any output to stderr is
1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  an indication that aapt has failed (http://crbug.com/314885), except
1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  lines that contain "libpng warning", which is a known non-error condition
1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  (http://crbug.com/364355).
1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  """
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if returncode != 0:
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return True
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for line in stderr.splitlines():
1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if line and not 'libpng warning' in line:
1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return True
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return False
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def main():
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  options = ParseArgs()
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  android_jar = os.path.join(options.android_sdk, 'android.jar')
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aapt = os.path.join(options.android_sdk_tools, 'aapt')
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  build_utils.DeleteDirectory(options.R_dir)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  build_utils.MakeDirectory(options.R_dir)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  with build_utils.TempDir() as temp_dir:
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    deps_dir = os.path.join(temp_dir, 'deps')
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    build_utils.MakeDirectory(deps_dir)
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    v14_dir = os.path.join(temp_dir, 'v14')
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    build_utils.MakeDirectory(v14_dir)
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    input_resource_dirs = build_utils.ParseGypList(options.resource_dirs)
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for resource_dir in input_resource_dirs:
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      generate_v14_compatible_resources.GenerateV14Resources(
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          resource_dir,
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          v14_dir,
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          options.v14_verify_only)
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # Generate R.java. This R.java contains non-final constants and is used only
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # while compiling the library jar (e.g. chromium_content.jar). When building
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # an apk, a new R.java file with the correct resource -> ID mappings will be
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # generated by merging the resources from all libraries and the main apk
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # project.
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    package_command = [aapt,
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       'package',
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '-m',
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '-M', options.android_manifest,
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '--auto-add-overlay',
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '-I', android_jar,
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '--output-text-symbols', options.R_dir,
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       '-J', options.R_dir]
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for d in input_resource_dirs:
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      package_command += ['-S', d]
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    dep_zips = build_utils.ParseGypList(options.dependencies_res_zips)
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for z in dep_zips:
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      subdir = os.path.join(deps_dir, os.path.basename(z))
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if os.path.exists(subdir):
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        raise Exception('Resource zip name conflict: ' + os.path.basename(z))
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      build_utils.ExtractAll(z, path=subdir)
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      package_command += ['-S', subdir]
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if options.non_constant_id:
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      package_command.append('--non-constant-id')
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if options.custom_package:
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      package_command += ['--custom-package', options.custom_package]
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if options.proguard_file:
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      package_command += ['-G', options.proguard_file]
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    build_utils.CheckOutput(package_command, print_stderr=False)
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if options.extra_res_packages:
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateExtraRJavaFiles(
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          options.R_dir,
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          build_utils.ParseGypList(options.extra_res_packages),
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          build_utils.ParseGypList(options.extra_r_text_files))
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # This is the list of directories with resources to put in the final .zip
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # file. The order of these is important so that crunched/v14 resources
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # override the normal ones.
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    zip_resource_dirs = input_resource_dirs + [v14_dir]
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base_crunch_dir = os.path.join(temp_dir, 'crunch')
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # Crunch image resources. This shrinks png files and is necessary for
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # 9-patch images to display correctly. 'aapt crunch' accepts only a single
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # directory at a time and deletes everything in the output directory.
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for idx, d in enumerate(input_resource_dirs):
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      crunch_dir = os.path.join(base_crunch_dir, str(idx))
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      build_utils.MakeDirectory(crunch_dir)
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      zip_resource_dirs.append(crunch_dir)
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      aapt_cmd = [aapt,
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  'crunch',
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  '-C', crunch_dir,
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  '-S', d]
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      build_utils.CheckOutput(aapt_cmd, fail_func=DidCrunchFail)
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # Python zipfile does not provide a way to replace a file (it just writes
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # another file with the same name). So, first collect all the files to put
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    # in the zip (with proper overriding), and then zip them.
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    files_to_zip = dict()
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for d in zip_resource_dirs:
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      for root, _, files in os.walk(d):
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        for f in files:
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          archive_path = os.path.join(os.path.relpath(root, d), f)
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          path = os.path.join(root, f)
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          files_to_zip[archive_path] = path
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    with zipfile.ZipFile(options.resource_zip_out, 'w') as outzip:
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      for archive_path, path in files_to_zip.iteritems():
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        outzip.write(path, archive_path)
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if options.stamp:
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      build_utils.Touch(options.stamp)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)if __name__ == '__main__':
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  main()
233