| Index: build/android/gyp/process_resources.py | 
| diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py | 
| index b9a378647f9ca62c56587d6a0827f2354ef926d7..f8971aa9d2a3da428846b907aa90ec4a55df6e4e 100755 | 
| --- a/build/android/gyp/process_resources.py | 
| +++ b/build/android/gyp/process_resources.py | 
| @@ -17,7 +17,6 @@ | 
| import re | 
| import shutil | 
| import sys | 
| -import xml.etree.ElementTree | 
|  | 
| import generate_v14_compatible_resources | 
|  | 
| @@ -144,42 +143,64 @@ | 
| return options | 
|  | 
|  | 
| -def CreateRJavaFiles(srcjar_dir, main_r_txt_file, packages, r_txt_files, | 
| -                     shared_resources): | 
| -  assert len(packages) == len(r_txt_files), 'Need one R.txt file per package' | 
| - | 
| -  # Map of (resource_type, name) -> Entry. | 
| -  # Contains the correct values for resources. | 
| -  all_resources = {} | 
| -  for entry in _ParseTextSymbolsFile(main_r_txt_file): | 
| -    all_resources[(entry.resource_type, entry.name)] = entry | 
| - | 
| -  # Map of package_name->resource_type->entry | 
| -  resources_by_package = ( | 
| -      collections.defaultdict(lambda: collections.defaultdict(list))) | 
| -  # Build the R.java files using each package's R.txt file, but replacing | 
| -  # each entry's placeholder value with correct values from all_resources. | 
| -  for package, r_txt_file in zip(packages, r_txt_files): | 
| -    if package in resources_by_package: | 
| -      raise Exception(('Package name "%s" appeared twice. All ' | 
| -                       'android_resources() targets must use unique package ' | 
| -                       'names, or no package name at all.') % package) | 
| -    resources_by_type = resources_by_package[package] | 
| -    # The sub-R.txt files have the wrong values at this point. Read them to | 
| -    # figure out which entries belong to them, but use the values from the | 
| -    # main R.txt file. | 
| +def CreateExtraRJavaFiles( | 
| +      r_dir, extra_packages, extra_r_text_files, shared_resources, include_all): | 
| +  if include_all: | 
| +    java_files = build_utils.FindInDirectory(r_dir, "R.java") | 
| +    if len(java_files) != 1: | 
| +      return | 
| +    r_java_file = java_files[0] | 
| +    r_java_contents = codecs.open(r_java_file, encoding='utf-8').read() | 
| + | 
| +    for package in extra_packages: | 
| +      package_r_java_dir = os.path.join(r_dir, *package.split('.')) | 
| +      build_utils.MakeDirectory(package_r_java_dir) | 
| +      package_r_java_path = os.path.join(package_r_java_dir, 'R.java') | 
| +      new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package, | 
| +                          r_java_contents) | 
| +      codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java) | 
| +  else: | 
| +    if len(extra_packages) != len(extra_r_text_files): | 
| +      raise Exception('Need one R.txt file per extra package') | 
| + | 
| +    r_txt_file = os.path.join(r_dir, 'R.txt') | 
| +    if not os.path.exists(r_txt_file): | 
| +      return | 
| + | 
| +    # Map of (resource_type, name) -> Entry. | 
| +    # Contains the correct values for resources. | 
| +    all_resources = {} | 
| for entry in _ParseTextSymbolsFile(r_txt_file): | 
| -      entry = all_resources[(entry.resource_type, entry.name)] | 
| -      resources_by_type[entry.resource_type].append(entry) | 
| - | 
| -  for package, resources_by_type in resources_by_package.iteritems(): | 
| -    package_r_java_dir = os.path.join(srcjar_dir, *package.split('.')) | 
| -    build_utils.MakeDirectory(package_r_java_dir) | 
| -    package_r_java_path = os.path.join(package_r_java_dir, 'R.java') | 
| -    java_file_contents = _CreateRJavaFile( | 
| -        package, resources_by_type, shared_resources) | 
| -    with open(package_r_java_path, 'w') as f: | 
| -      f.write(java_file_contents) | 
| +      all_resources[(entry.resource_type, entry.name)] = entry | 
| + | 
| +    # Map of package_name->resource_type->entry | 
| +    resources_by_package = ( | 
| +        collections.defaultdict(lambda: collections.defaultdict(list))) | 
| +    # Build the R.java files using each package's R.txt file, but replacing | 
| +    # each entry's placeholder value with correct values from all_resources. | 
| +    for package, r_text_file in zip(extra_packages, extra_r_text_files): | 
| +      if not os.path.exists(r_text_file): | 
| +        continue | 
| +      if package in resources_by_package: | 
| +        raise Exception(('Package name "%s" appeared twice. All ' | 
| +                         'android_resources() targets must use unique package ' | 
| +                         'names, or no package name at all.') % package) | 
| +      resources_by_type = resources_by_package[package] | 
| +      # The sub-R.txt files have the wrong values at this point. Read them to | 
| +      # figure out which entries belong to them, but use the values from the | 
| +      # main R.txt file. | 
| +      for entry in _ParseTextSymbolsFile(r_text_file): | 
| +        entry = all_resources[(entry.resource_type, entry.name)] | 
| +        resources_by_type[entry.resource_type].append(entry) | 
| + | 
| +    for package, resources_by_type in resources_by_package.iteritems(): | 
| +      package_r_java_dir = os.path.join(r_dir, *package.split('.')) | 
| +      build_utils.MakeDirectory(package_r_java_dir) | 
| +      package_r_java_path = os.path.join(package_r_java_dir, 'R.java') | 
| +      java_file_contents = _CreateExtraRJavaFile( | 
| +          package, resources_by_type, shared_resources) | 
| +      with open(package_r_java_path, 'w') as f: | 
| +        f.write(java_file_contents) | 
|  | 
|  | 
| def _ParseTextSymbolsFile(path): | 
| @@ -195,7 +216,7 @@ | 
| return ret | 
|  | 
|  | 
| -def _CreateRJavaFile(package, resources_by_type, shared_resources): | 
| +def _CreateExtraRJavaFile(package, resources_by_type, shared_resources): | 
| """Generates the contents of a R.java file.""" | 
| template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */ | 
|  | 
| @@ -320,11 +341,6 @@ | 
| build_utils.MergeZips(output_path, zip_files, path_transform=path_transform) | 
|  | 
|  | 
| -def _ExtractPackageFromManifest(manifest_path): | 
| -  doc = xml.etree.ElementTree.parse(manifest_path) | 
| -  return doc.getroot().get('package') | 
| - | 
| - | 
| def _OnStaleMd5(options): | 
| aapt = options.aapt_path | 
| with build_utils.TempDir() as temp_dir: | 
| @@ -335,8 +351,6 @@ | 
|  | 
| gen_dir = os.path.join(temp_dir, 'gen') | 
| build_utils.MakeDirectory(gen_dir) | 
| -    r_txt_path = os.path.join(gen_dir, 'R.txt') | 
| -    srcjar_dir = os.path.join(temp_dir, 'java') | 
|  | 
| input_resource_dirs = options.resource_dirs | 
|  | 
| @@ -368,72 +382,34 @@ | 
| '--no-version-vectors', | 
| '-I', options.android_sdk_jar, | 
| '--output-text-symbols', gen_dir, | 
| -                       '-J', gen_dir,  # Required for R.txt generation. | 
| +                       '-J', gen_dir, | 
| '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN] | 
| - | 
| -    # aapt supports only the "--include-all-resources" mode, where each R.java | 
| -    # file ends up with all symbols, rather than only those that it had at the | 
| -    # time it was originally generated. This subtle difference makes no | 
| -    # difference when compiling, but can lead to increased unused symbols in the | 
| -    # resulting R.class files. | 
| -    # TODO(agrieve): See if proguard makes this difference actually translate | 
| -    # into a size difference. If not, we can delete all of our custom R.java | 
| -    # template code above (and make include_all_resources the default). | 
| -    if options.include_all_resources: | 
| -      srcjar_dir = gen_dir | 
| -      if options.extra_res_packages: | 
| -        colon_separated = ':'.join(options.extra_res_packages) | 
| -        package_command += ['--extra-packages', colon_separated] | 
| -      if options.non_constant_id: | 
| -        package_command.append('--non-constant-id') | 
| -      if options.custom_package: | 
| -        package_command += ['--custom-package', options.custom_package] | 
| -      if options.shared_resources: | 
| -        package_command.append('--shared-lib') | 
| -      if options.app_as_shared_lib: | 
| -        package_command.append('--app-as-shared-lib') | 
|  | 
| for d in input_resource_dirs: | 
| package_command += ['-S', d] | 
|  | 
| -    # Adding all dependencies as sources is necessary for @type/foo references | 
| -    # to symbols within dependencies to resolve. However, it has the side-effect | 
| -    # that all Java symbols from dependencies are copied into the new R.java. | 
| -    # E.g.: It enables an arguably incorrect usage of | 
| -    # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be | 
| -    # more correct. This is just how Android works. | 
| for d in dep_subdirs: | 
| package_command += ['-S', d] | 
|  | 
| +    if options.non_constant_id: | 
| +      package_command.append('--non-constant-id') | 
| +    if options.custom_package: | 
| +      package_command += ['--custom-package', options.custom_package] | 
| if options.proguard_file: | 
| package_command += ['-G', options.proguard_file] | 
| +    if options.shared_resources: | 
| +      package_command.append('--shared-lib') | 
| +    if options.app_as_shared_lib: | 
| +      package_command.append('--app-as-shared-lib') | 
| build_utils.CheckOutput(package_command, print_stderr=False) | 
|  | 
| -    # When an empty res/ directory is passed, aapt does not write an R.txt. | 
| -    if not os.path.exists(r_txt_path): | 
| -      build_utils.Touch(r_txt_path) | 
| - | 
| -    if not options.include_all_resources: | 
| -      packages = list(options.extra_res_packages) | 
| -      r_txt_files = list(options.extra_r_text_files) | 
| - | 
| -      cur_package = options.custom_package | 
| -      if not options.custom_package: | 
| -        cur_package = _ExtractPackageFromManifest(options.android_manifest) | 
| - | 
| -      # Don't create a .java file for the current resource target when: | 
| -      # - no package name was provided (either by manifest or build rules), | 
| -      # - there was already a dependent android_resources() with the same | 
| -      #   package (occurs mostly when an apk target and resources target share | 
| -      #   an AndroidManifest.xml) | 
| -      if cur_package != 'dummy.package' and cur_package not in packages: | 
| -        packages.append(cur_package) | 
| -        r_txt_files.append(r_txt_path) | 
| - | 
| -      if packages: | 
| -        shared_resources = options.shared_resources or options.app_as_shared_lib | 
| -        CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files, | 
| -                         shared_resources) | 
| +    if options.extra_res_packages: | 
| +      CreateExtraRJavaFiles( | 
| +          gen_dir, | 
| +          options.extra_res_packages, | 
| +          options.extra_r_text_files, | 
| +          options.shared_resources or options.app_as_shared_lib, | 
| +          options.include_all_resources) | 
|  | 
| # This is the list of directories with resources to put in the final .zip | 
| # file. The order of these is important so that crunched/v14 resources | 
| @@ -459,12 +435,16 @@ | 
|  | 
| if options.R_dir: | 
| build_utils.DeleteDirectory(options.R_dir) | 
| -      shutil.copytree(srcjar_dir, options.R_dir) | 
| +      shutil.copytree(gen_dir, options.R_dir) | 
| else: | 
| -      build_utils.ZipDir(options.srcjar_out, srcjar_dir) | 
| +      build_utils.ZipDir(options.srcjar_out, gen_dir) | 
|  | 
| if options.r_text_out: | 
| -      shutil.copyfile(r_txt_path, options.r_text_out) | 
| +      r_text_path = os.path.join(gen_dir, 'R.txt') | 
| +      if os.path.exists(r_text_path): | 
| +        shutil.copyfile(r_text_path, options.r_text_out) | 
| +      else: | 
| +        open(options.r_text_out, 'w').close() | 
|  | 
|  | 
| def main(args): | 
| @@ -497,7 +477,7 @@ | 
| options.android_sdk_jar, | 
| ] | 
| input_paths.extend(options.dependencies_res_zips) | 
| -  input_paths.extend(options.extra_r_text_files) | 
| +  input_paths.extend(p for p in options.extra_r_text_files if os.path.exists(p)) | 
|  | 
| resource_names = [] | 
| for resource_dir in options.resource_dirs: | 
|  |