mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-25 13:28:46 +03:00
297 lines
11 KiB
Python
297 lines
11 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||
|
# Use of this source code is governed by a BSD-style license that can be
|
||
|
# found in the LICENSE file.
|
||
|
|
||
|
"""Process Android resource directories to generate .resources.zip, R.txt and
|
||
|
.srcjar files."""
|
||
|
|
||
|
import argparse
|
||
|
import collections
|
||
|
import os
|
||
|
import re
|
||
|
import shutil
|
||
|
import sys
|
||
|
|
||
|
import generate_v14_compatible_resources
|
||
|
|
||
|
from util import build_utils
|
||
|
from util import resource_utils
|
||
|
|
||
|
|
||
|
def _ParseArgs(args):
|
||
|
"""Parses command line options.
|
||
|
|
||
|
Returns:
|
||
|
An options object as from argparse.ArgumentParser.parse_args()
|
||
|
"""
|
||
|
parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
|
||
|
|
||
|
input_opts.add_argument('--resource-dirs',
|
||
|
default='[]',
|
||
|
help='A list of input directories containing resources '
|
||
|
'for this target.')
|
||
|
|
||
|
input_opts.add_argument(
|
||
|
'--shared-resources',
|
||
|
action='store_true',
|
||
|
help='Make resources shareable by generating an onResourcesLoaded() '
|
||
|
'method in the R.java source file.')
|
||
|
|
||
|
input_opts.add_argument('--custom-package',
|
||
|
help='Optional Java package for main R.java.')
|
||
|
|
||
|
input_opts.add_argument(
|
||
|
'--android-manifest',
|
||
|
help='Optional AndroidManifest.xml path. Only used to extract a package '
|
||
|
'name for R.java if a --custom-package is not provided.')
|
||
|
|
||
|
output_opts.add_argument(
|
||
|
'--resource-zip-out',
|
||
|
help='Path to a zip archive containing all resources from '
|
||
|
'--resource-dirs, merged into a single directory tree. This will '
|
||
|
'also include auto-generated v14-compatible resources unless '
|
||
|
'--v14-skip is used.')
|
||
|
|
||
|
output_opts.add_argument('--srcjar-out',
|
||
|
help='Path to .srcjar to contain the generated R.java.')
|
||
|
|
||
|
output_opts.add_argument('--r-text-out',
|
||
|
help='Path to store the generated R.txt file.')
|
||
|
|
||
|
input_opts.add_argument(
|
||
|
'--v14-skip',
|
||
|
action="store_true",
|
||
|
help='Do not generate nor verify v14 resources.')
|
||
|
|
||
|
options = parser.parse_args(args)
|
||
|
|
||
|
resource_utils.HandleCommonOptions(options)
|
||
|
|
||
|
options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
|
||
|
|
||
|
return options
|
||
|
|
||
|
|
||
|
def _GenerateGlobs(pattern):
|
||
|
# This function processes the aapt ignore assets pattern into a list of globs
|
||
|
# to be used to exclude files on the python side. It removes the '!', which is
|
||
|
# used by aapt to mean 'not chatty' so it does not output if the file is
|
||
|
# ignored (we dont output anyways, so it is not required). This function does
|
||
|
# not handle the <dir> and <file> prefixes used by aapt and are assumed not to
|
||
|
# be included in the pattern string.
|
||
|
return pattern.replace('!', '').split(':')
|
||
|
|
||
|
|
||
|
def _ZipResources(resource_dirs, zip_path, ignore_pattern):
|
||
|
# Python zipfile does not provide a way to replace a file (it just writes
|
||
|
# another file with the same name). So, first collect all the files to put
|
||
|
# in the zip (with proper overriding), and then zip them.
|
||
|
# ignore_pattern is a string of ':' delimited list of globs used to ignore
|
||
|
# files that should not be part of the final resource zip.
|
||
|
files_to_zip = dict()
|
||
|
files_to_zip_without_generated = dict()
|
||
|
globs = _GenerateGlobs(ignore_pattern)
|
||
|
for d in resource_dirs:
|
||
|
for root, _, files in os.walk(d):
|
||
|
for f in files:
|
||
|
archive_path = f
|
||
|
parent_dir = os.path.relpath(root, d)
|
||
|
if parent_dir != '.':
|
||
|
archive_path = os.path.join(parent_dir, f)
|
||
|
path = os.path.join(root, f)
|
||
|
if build_utils.MatchesGlob(archive_path, globs):
|
||
|
continue
|
||
|
# We want the original resource dirs in the .info file rather than the
|
||
|
# generated overridden path.
|
||
|
if not path.startswith('/tmp'):
|
||
|
files_to_zip_without_generated[archive_path] = path
|
||
|
files_to_zip[archive_path] = path
|
||
|
resource_utils.CreateResourceInfoFile(files_to_zip_without_generated,
|
||
|
zip_path)
|
||
|
build_utils.DoZip(files_to_zip.iteritems(), zip_path)
|
||
|
|
||
|
|
||
|
def _GenerateRTxt(options, dep_subdirs, gen_dir):
|
||
|
"""Generate R.txt file.
|
||
|
|
||
|
Args:
|
||
|
options: The command-line options tuple.
|
||
|
dep_subdirs: List of directories containing extracted dependency resources.
|
||
|
gen_dir: Locates where the aapt-generated files will go. In particular
|
||
|
the output file is always generated as |{gen_dir}/R.txt|.
|
||
|
"""
|
||
|
# NOTE: This uses aapt rather than aapt2 because 'aapt2 compile' does not
|
||
|
# support the --output-text-symbols option yet (https://crbug.com/820460).
|
||
|
package_command = [options.aapt_path,
|
||
|
'package',
|
||
|
'-m',
|
||
|
'-M', resource_utils.EMPTY_ANDROID_MANIFEST_PATH,
|
||
|
'--no-crunch',
|
||
|
'--auto-add-overlay',
|
||
|
'--no-version-vectors',
|
||
|
]
|
||
|
for j in options.android_sdk_jars:
|
||
|
package_command += ['-I', j]
|
||
|
|
||
|
package_command += [
|
||
|
'--output-text-symbols', gen_dir,
|
||
|
'-J', gen_dir, # Required for R.txt generation.
|
||
|
'--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
|
||
|
|
||
|
# 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]
|
||
|
|
||
|
for d in options.resource_dirs:
|
||
|
package_command += ['-S', d]
|
||
|
|
||
|
# Only creates an R.txt
|
||
|
build_utils.CheckOutput(
|
||
|
package_command, print_stdout=False, print_stderr=False)
|
||
|
|
||
|
|
||
|
def _GenerateResourcesZip(output_resource_zip, input_resource_dirs,
|
||
|
v14_skip, temp_dir):
|
||
|
"""Generate a .resources.zip file fron a list of input resource dirs.
|
||
|
|
||
|
Args:
|
||
|
output_resource_zip: Path to the output .resources.zip file.
|
||
|
input_resource_dirs: A list of input resource directories.
|
||
|
v14_skip: If False, then v14-compatible resource will also be
|
||
|
generated in |{temp_dir}/v14| and added to the final zip.
|
||
|
temp_dir: Path to temporary directory.
|
||
|
"""
|
||
|
if not v14_skip:
|
||
|
# Generate v14-compatible resources in temp_dir.
|
||
|
v14_dir = os.path.join(temp_dir, 'v14')
|
||
|
build_utils.MakeDirectory(v14_dir)
|
||
|
|
||
|
for resource_dir in input_resource_dirs:
|
||
|
generate_v14_compatible_resources.GenerateV14Resources(
|
||
|
resource_dir,
|
||
|
v14_dir)
|
||
|
|
||
|
input_resource_dirs.append(v14_dir)
|
||
|
|
||
|
_ZipResources(input_resource_dirs, output_resource_zip,
|
||
|
build_utils.AAPT_IGNORE_PATTERN)
|
||
|
|
||
|
|
||
|
def _OnStaleMd5(options):
|
||
|
with resource_utils.BuildContext() as build:
|
||
|
if options.r_text_in:
|
||
|
r_txt_path = options.r_text_in
|
||
|
else:
|
||
|
# Extract dependencies to resolve @foo/type references into
|
||
|
# dependent packages.
|
||
|
dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
|
||
|
build.deps_dir)
|
||
|
|
||
|
_GenerateRTxt(options, dep_subdirs, build.gen_dir)
|
||
|
r_txt_path = build.r_txt_path
|
||
|
|
||
|
# 'aapt' doesn't generate any R.txt file if res/ was empty.
|
||
|
if not os.path.exists(r_txt_path):
|
||
|
build_utils.Touch(r_txt_path)
|
||
|
|
||
|
if options.r_text_out:
|
||
|
shutil.copyfile(r_txt_path, options.r_text_out)
|
||
|
|
||
|
if options.srcjar_out:
|
||
|
package = options.custom_package
|
||
|
if not package and options.android_manifest:
|
||
|
package = resource_utils.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).
|
||
|
if package:
|
||
|
# All resource IDs should be non-final here, but the
|
||
|
# onResourcesLoaded() method should only be generated if
|
||
|
# --shared-resources is used.
|
||
|
rjava_build_options = resource_utils.RJavaBuildOptions()
|
||
|
rjava_build_options.ExportAllResources()
|
||
|
rjava_build_options.ExportAllStyleables()
|
||
|
if options.shared_resources:
|
||
|
rjava_build_options.GenerateOnResourcesLoaded()
|
||
|
|
||
|
resource_utils.CreateRJavaFiles(
|
||
|
build.srcjar_dir, package, r_txt_path,
|
||
|
options.extra_res_packages,
|
||
|
options.extra_r_text_files,
|
||
|
rjava_build_options)
|
||
|
|
||
|
build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
|
||
|
|
||
|
if options.resource_zip_out:
|
||
|
_GenerateResourcesZip(options.resource_zip_out, options.resource_dirs,
|
||
|
options.v14_skip, build.temp_dir)
|
||
|
|
||
|
|
||
|
def main(args):
|
||
|
args = build_utils.ExpandFileArgs(args)
|
||
|
options = _ParseArgs(args)
|
||
|
|
||
|
# Order of these must match order specified in GN so that the correct one
|
||
|
# appears first in the depfile.
|
||
|
possible_output_paths = [
|
||
|
options.resource_zip_out,
|
||
|
options.r_text_out,
|
||
|
options.srcjar_out,
|
||
|
]
|
||
|
output_paths = [x for x in possible_output_paths if x]
|
||
|
|
||
|
# List python deps in input_strings rather than input_paths since the contents
|
||
|
# of them does not change what gets written to the depsfile.
|
||
|
input_strings = options.extra_res_packages + [
|
||
|
options.custom_package,
|
||
|
options.shared_resources,
|
||
|
options.v14_skip,
|
||
|
]
|
||
|
|
||
|
possible_input_paths = [
|
||
|
options.aapt_path,
|
||
|
options.android_manifest,
|
||
|
]
|
||
|
possible_input_paths += options.android_sdk_jars
|
||
|
input_paths = [x for x in possible_input_paths if x]
|
||
|
input_paths.extend(options.dependencies_res_zips)
|
||
|
input_paths.extend(options.extra_r_text_files)
|
||
|
|
||
|
# Resource files aren't explicitly listed in GN. Listing them in the depfile
|
||
|
# ensures the target will be marked stale when resource files are removed.
|
||
|
depfile_deps = []
|
||
|
resource_names = []
|
||
|
for resource_dir in options.resource_dirs:
|
||
|
for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
|
||
|
# Don't list the empty .keep file in depfile. Since it doesn't end up
|
||
|
# included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
|
||
|
# if ever moved.
|
||
|
if not resource_file.endswith(os.path.join('empty', '.keep')):
|
||
|
input_paths.append(resource_file)
|
||
|
depfile_deps.append(resource_file)
|
||
|
resource_names.append(os.path.relpath(resource_file, resource_dir))
|
||
|
|
||
|
# Resource filenames matter to the output, so add them to strings as well.
|
||
|
# This matters if a file is renamed but not changed (http://crbug.com/597126).
|
||
|
input_strings.extend(sorted(resource_names))
|
||
|
|
||
|
build_utils.CallAndWriteDepfileIfStale(
|
||
|
lambda: _OnStaleMd5(options),
|
||
|
options,
|
||
|
input_paths=input_paths,
|
||
|
input_strings=input_strings,
|
||
|
output_paths=output_paths,
|
||
|
depfile_deps=depfile_deps)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main(sys.argv[1:])
|