mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 09:46:09 +03:00
179 lines
6.0 KiB
Python
179 lines
6.0 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Copyright 2013 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.
|
||
|
|
||
|
import json
|
||
|
import logging
|
||
|
import optparse
|
||
|
import os
|
||
|
import shutil
|
||
|
import sys
|
||
|
import zipfile
|
||
|
|
||
|
from util import build_utils
|
||
|
|
||
|
|
||
|
def _CheckFilePathEndsWithJar(parser, file_path):
|
||
|
if not file_path.endswith(".jar"):
|
||
|
parser.error("%s does not end in .jar" % file_path)
|
||
|
|
||
|
|
||
|
def _CheckFilePathsEndWithJar(parser, file_paths):
|
||
|
for file_path in file_paths:
|
||
|
_CheckFilePathEndsWithJar(parser, file_path)
|
||
|
|
||
|
|
||
|
def _ParseArgs(args):
|
||
|
args = build_utils.ExpandFileArgs(args)
|
||
|
|
||
|
parser = optparse.OptionParser()
|
||
|
build_utils.AddDepfileOption(parser)
|
||
|
|
||
|
parser.add_option('--output-directory',
|
||
|
default=os.getcwd(),
|
||
|
help='Path to the output build directory.')
|
||
|
parser.add_option('--dex-path', help='Dex output path.')
|
||
|
parser.add_option('--configuration-name',
|
||
|
help='The build CONFIGURATION_NAME.')
|
||
|
parser.add_option('--proguard-enabled',
|
||
|
help='"true" if proguard is enabled.')
|
||
|
parser.add_option('--debug-build-proguard-enabled',
|
||
|
help='"true" if proguard is enabled for debug build.')
|
||
|
parser.add_option('--proguard-enabled-input-path',
|
||
|
help=('Path to dex in Release mode when proguard '
|
||
|
'is enabled.'))
|
||
|
parser.add_option('--inputs', help='A list of additional input paths.')
|
||
|
parser.add_option('--excluded-paths',
|
||
|
help='A list of paths to exclude from the dex file.')
|
||
|
parser.add_option('--main-dex-list-path',
|
||
|
help='A file containing a list of the classes to '
|
||
|
'include in the main dex.')
|
||
|
parser.add_option('--multidex-configuration-path',
|
||
|
help='A JSON file containing multidex build configuration.')
|
||
|
parser.add_option('--multi-dex', default=False, action='store_true',
|
||
|
help='Generate multiple dex files.')
|
||
|
parser.add_option('--d8-jar-path',
|
||
|
help='Path to D8 jar.')
|
||
|
|
||
|
options, paths = parser.parse_args(args)
|
||
|
|
||
|
required_options = ('d8_jar_path',)
|
||
|
build_utils.CheckOptions(options, parser, required=required_options)
|
||
|
|
||
|
if options.multidex_configuration_path:
|
||
|
with open(options.multidex_configuration_path) as multidex_config_file:
|
||
|
multidex_config = json.loads(multidex_config_file.read())
|
||
|
options.multi_dex = multidex_config.get('enabled', False)
|
||
|
|
||
|
if options.multi_dex and not options.main_dex_list_path:
|
||
|
logging.warning('multidex cannot be enabled without --main-dex-list-path')
|
||
|
options.multi_dex = False
|
||
|
elif options.main_dex_list_path and not options.multi_dex:
|
||
|
logging.warning('--main-dex-list-path is unused if multidex is not enabled')
|
||
|
|
||
|
if options.inputs:
|
||
|
options.inputs = build_utils.ParseGnList(options.inputs)
|
||
|
_CheckFilePathsEndWithJar(parser, options.inputs)
|
||
|
if options.excluded_paths:
|
||
|
options.excluded_paths = build_utils.ParseGnList(options.excluded_paths)
|
||
|
|
||
|
if options.proguard_enabled_input_path:
|
||
|
_CheckFilePathEndsWithJar(parser, options.proguard_enabled_input_path)
|
||
|
_CheckFilePathsEndWithJar(parser, paths)
|
||
|
|
||
|
return options, paths
|
||
|
|
||
|
|
||
|
def _MoveTempDexFile(tmp_dex_dir, dex_path):
|
||
|
"""Move the temp dex file out of |tmp_dex_dir|.
|
||
|
|
||
|
Args:
|
||
|
tmp_dex_dir: Path to temporary directory created with tempfile.mkdtemp().
|
||
|
The directory should have just a single file.
|
||
|
dex_path: Target path to move dex file to.
|
||
|
|
||
|
Raises:
|
||
|
Exception if there are multiple files in |tmp_dex_dir|.
|
||
|
"""
|
||
|
tempfiles = os.listdir(tmp_dex_dir)
|
||
|
if len(tempfiles) > 1:
|
||
|
raise Exception('%d files created, expected 1' % len(tempfiles))
|
||
|
|
||
|
tmp_dex_path = os.path.join(tmp_dex_dir, tempfiles[0])
|
||
|
shutil.move(tmp_dex_path, dex_path)
|
||
|
|
||
|
|
||
|
def _NoClassFiles(jar_paths):
|
||
|
"""Returns True if there are no .class files in the given JARs.
|
||
|
|
||
|
Args:
|
||
|
jar_paths: list of strings representing JAR file paths.
|
||
|
|
||
|
Returns:
|
||
|
(bool) True if no .class files are found.
|
||
|
"""
|
||
|
for jar_path in jar_paths:
|
||
|
with zipfile.ZipFile(jar_path) as jar:
|
||
|
if any(name.endswith('.class') for name in jar.namelist()):
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
|
||
|
def _RunD8(dex_cmd, input_paths, output_path):
|
||
|
dex_cmd += ['--output', output_path]
|
||
|
dex_cmd += input_paths
|
||
|
build_utils.CheckOutput(dex_cmd, print_stderr=False)
|
||
|
|
||
|
|
||
|
def main(args):
|
||
|
options, paths = _ParseArgs(args)
|
||
|
if ((options.proguard_enabled == 'true'
|
||
|
and options.configuration_name == 'Release')
|
||
|
or (options.debug_build_proguard_enabled == 'true'
|
||
|
and options.configuration_name == 'Debug')):
|
||
|
paths = [options.proguard_enabled_input_path]
|
||
|
|
||
|
if options.inputs:
|
||
|
paths += options.inputs
|
||
|
|
||
|
if options.excluded_paths:
|
||
|
# Excluded paths are relative to the output directory.
|
||
|
exclude_paths = options.excluded_paths
|
||
|
paths = [p for p in paths if not
|
||
|
os.path.relpath(p, options.output_directory) in exclude_paths]
|
||
|
|
||
|
input_paths = list(paths)
|
||
|
if options.multi_dex:
|
||
|
input_paths.append(options.main_dex_list_path)
|
||
|
|
||
|
dex_cmd = ['java', '-jar', options.d8_jar_path]
|
||
|
if options.multi_dex:
|
||
|
dex_cmd += ['--main-dex-list', options.main_dex_list_path]
|
||
|
|
||
|
is_dex = options.dex_path.endswith('.dex')
|
||
|
is_jar = options.dex_path.endswith('.jar')
|
||
|
|
||
|
if is_jar and _NoClassFiles(paths):
|
||
|
# Handle case where no classfiles are specified in inputs
|
||
|
# by creating an empty JAR
|
||
|
with zipfile.ZipFile(options.dex_path, 'w') as outfile:
|
||
|
outfile.comment = 'empty'
|
||
|
elif is_dex:
|
||
|
# .dex files can't specify a name for D8. Instead, we output them to a
|
||
|
# temp directory then move them after the command has finished running
|
||
|
# (see _MoveTempDexFile). For other files, tmp_dex_dir is None.
|
||
|
with build_utils.TempDir() as tmp_dex_dir:
|
||
|
_RunD8(dex_cmd, paths, tmp_dex_dir)
|
||
|
_MoveTempDexFile(tmp_dex_dir, options.dex_path)
|
||
|
else:
|
||
|
_RunD8(dex_cmd, paths, options.dex_path)
|
||
|
|
||
|
build_utils.WriteDepfile(
|
||
|
options.depfile, options.dex_path, input_paths, add_pydeps=False)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
sys.exit(main(sys.argv[1:]))
|