Commit 09a941a9 authored by Martin Šrámek's avatar Martin Šrámek Committed by Commit Bot

Revert "Android: Use R8 for dex splitting."

This reverts commit b283bd25.

Reason for revert: Probable culprit for the intermittent compile failures on android_arm64-builder-perf. See crbug.com/1045866.

Original change's description:
> Android: Use R8 for dex splitting.
> 
> R8 has now added support (b/122902374) for this, fixing a few
> outstanding bugs related to class merging. This also makes build rules
> a bit simpler.
> 
> Still need to switch Trichrome synchronized proguard over to using
> R8 for dexsplitting, then we can remove dexsplitter support entirely.
> 
> This CL updates R8 with another patch, but does not change the R8
> base version used.
> 
> Binary-Size: R8 patch now keeping extra methods.
> Bug: 1032609
> Change-Id: I79f88736c20d96b718eb129cdbd093fe1cd297b9
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2014309
> Commit-Queue: Eric Stevenson <estevenson@chromium.org>
> Reviewed-by: Sam Maier <smaier@chromium.org>
> Reviewed-by: Andrew Grieve <agrieve@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#735315}

TBR=agrieve@chromium.org,estevenson@chromium.org,smaier@chromium.org

Change-Id: I917a73a43e38a4583d9fcedf43d8a29fffbdf914
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1032609, 1045866
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2020964Reviewed-by: default avatarMartin Šrámek <msramek@chromium.org>
Commit-Queue: Martin Šrámek <msramek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735345}
parent d4b79b05
...@@ -1400,7 +1400,7 @@ deps = { ...@@ -1400,7 +1400,7 @@ deps = {
'packages': [ 'packages': [
{ {
'package': 'chromium/third_party/r8', 'package': 'chromium/third_party/r8',
'version': 'vDpIPy78EWpdAzbQ6cYYJMQaFQghOjmCtF0NcaoO0IIC', 'version': '-oXGY8FjY2ZuIBHoGAByn8N6Vn2b0wB2QO8Ct_169XoC',
}, },
], ],
'condition': 'checkout_android', 'condition': 'checkout_android',
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# found in the LICENSE file. # found in the LICENSE file.
import argparse import argparse
import itertools
import os import os
import re import re
import shutil import shutil
...@@ -112,7 +111,8 @@ def _ParseOptions(): ...@@ -112,7 +111,8 @@ def _ParseOptions():
group.add_argument('--r8-path', help='Path to the R8.jar to use.') group.add_argument('--r8-path', help='Path to the R8.jar to use.')
parser.add_argument( parser.add_argument(
'--input-paths', required=True, help='GN-list of .jar files to optimize.') '--input-paths', required=True, help='GN-list of .jar files to optimize.')
parser.add_argument('--output-path', help='Path to the generated .jar file.') parser.add_argument(
'--output-path', required=True, help='Path to the generated .jar file.')
parser.add_argument( parser.add_argument(
'--proguard-configs', '--proguard-configs',
action='append', action='append',
...@@ -160,34 +160,9 @@ def _ParseOptions(): ...@@ -160,34 +160,9 @@ def _ParseOptions():
'--disable-checkdiscard', '--disable-checkdiscard',
action='store_true', action='store_true',
help='Disable -checkdiscard directives') help='Disable -checkdiscard directives')
parser.add_argument(
'--feature-jars',
action='append',
help='GN list of path to jars which comprise the corresponding feature.')
parser.add_argument(
'--dex-dest',
action='append',
dest='dex_dests',
help='Destination for dex file of the corresponding feature.')
parser.add_argument(
'--feature-name',
action='append',
dest='feature_names',
help='The name of the feature module.')
parser.add_argument(
'--stamp',
help='File to touch upon success. Mutually exclusive with --output-path')
options = parser.parse_args(args) options = parser.parse_args(args)
if options.feature_names:
if options.output_path:
parser.error('Feature splits cannot specify an output in GN.')
if not options.stamp:
parser.error('Feature splits require a stamp file as output.')
elif not options.output_path:
parser.error('Output path required when feature splits aren\'t used')
if options.main_dex_rules_path and not options.r8_path: if options.main_dex_rules_path and not options.r8_path:
parser.error('R8 must be enabled to pass main dex rules.') parser.error('R8 must be enabled to pass main dex rules.')
...@@ -203,17 +178,6 @@ def _ParseOptions(): ...@@ -203,17 +178,6 @@ def _ParseOptions():
options.extra_mapping_output_paths = build_utils.ParseGnList( options.extra_mapping_output_paths = build_utils.ParseGnList(
options.extra_mapping_output_paths) options.extra_mapping_output_paths)
if options.feature_names:
if 'base' not in options.feature_names:
parser.error('"base" feature required when feature arguments are used.')
if len(options.feature_names) != len(options.feature_jars) or len(
options.feature_names) != len(options.dex_dests):
parser.error('Invalid feature argument lengths.')
options.feature_jars = [
build_utils.ParseGnList(x) for x in options.feature_jars
]
return options return options
...@@ -235,36 +199,6 @@ https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/android/java/README ...@@ -235,36 +199,6 @@ https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/android/java/README
f.write(msg) f.write(msg)
class _DexPathContext(object):
def __init__(self, name, output_path, input_jars, work_dir):
self.name = name
self.input_paths = input_jars
self._final_output_path = output_path
self._temporary_dir = os.path.join(work_dir, name)
def OutputPath(self):
if not os.path.exists(self._temporary_dir):
os.mkdir(self._temporary_dir)
return self._temporary_dir
def Commit(self):
found_files = build_utils.FindInDirectory(self._temporary_dir)
if self._final_output_path.endswith('.dex'):
if len(found_files) != 1:
raise Exception('Expected exactly 1 dex file output, found: {}'.format(
len(found_files)))
shutil.move(found_files[0], self._final_output_path)
else:
if len(found_files) == 0:
raise Exception('Missing dex outputs in {}'.format(self._temporary_dir))
# Add to .jar using Python rather than having R8 output to a .zip directly
# in order to disable compression of the .jar, saving ~500ms.
tmp_jar_output = self._temporary_dir + '.jar'
build_utils.DoZip(
found_files, tmp_jar_output, base_dir=self._temporary_dir)
shutil.move(tmp_jar_output, self._final_output_path)
def _OptimizeWithR8(options, def _OptimizeWithR8(options,
config_paths, config_paths,
libraries, libraries,
...@@ -285,20 +219,6 @@ def _OptimizeWithR8(options, ...@@ -285,20 +219,6 @@ def _OptimizeWithR8(options,
tmp_output = os.path.join(tmp_dir, 'r8out') tmp_output = os.path.join(tmp_dir, 'r8out')
os.mkdir(tmp_output) os.mkdir(tmp_output)
feature_contexts = []
if options.feature_names:
for name, dest_dex, input_paths in itertools.izip(
options.feature_names, options.dex_dests, options.feature_jars):
feature_context = _DexPathContext(name, dest_dex, input_paths,
tmp_output)
if name == 'base':
base_dex_context = feature_context
else:
feature_contexts.append(feature_context)
else:
base_dex_context = _DexPathContext('base', options.output_path,
options.input_paths, tmp_output)
cmd = [ cmd = [
build_utils.JAVA_PATH, build_utils.JAVA_PATH,
'-jar', '-jar',
...@@ -306,7 +226,7 @@ def _OptimizeWithR8(options, ...@@ -306,7 +226,7 @@ def _OptimizeWithR8(options,
'--no-desugaring', '--no-desugaring',
'--no-data-resources', '--no-data-resources',
'--output', '--output',
base_dex_context.OutputPath(), tmp_output,
'--pg-map-output', '--pg-map-output',
tmp_mapping_path, tmp_mapping_path,
] ]
...@@ -324,19 +244,7 @@ def _OptimizeWithR8(options, ...@@ -324,19 +244,7 @@ def _OptimizeWithR8(options,
for main_dex_rule in options.main_dex_rules_path: for main_dex_rule in options.main_dex_rules_path:
cmd += ['--main-dex-rules', main_dex_rule] cmd += ['--main-dex-rules', main_dex_rule]
input_code_paths = set() cmd += options.input_paths
for feature in feature_contexts:
for feature_input_jar in feature.input_paths:
if feature_input_jar not in base_dex_context.input_paths:
input_code_paths.add(feature_input_jar)
cmd += [
'--feature-jar', feature_input_jar + ':' + feature.OutputPath()
]
input_code_paths.update(base_dex_context.input_paths)
assert input_code_paths == set(options.input_paths), (
'Sum of feature input jars not equal to expected runtime classpath.')
cmd += base_dex_context.input_paths
env = os.environ.copy() env = os.environ.copy()
stderr_filter = lambda l: re.sub(r'.*_JAVA_OPTIONS.*\n?', '', l) stderr_filter = lambda l: re.sub(r'.*_JAVA_OPTIONS.*\n?', '', l)
...@@ -353,10 +261,17 @@ def _OptimizeWithR8(options, ...@@ -353,10 +261,17 @@ def _OptimizeWithR8(options,
'android/docs/java_optimization.md#Debugging-common-failures\n')) 'android/docs/java_optimization.md#Debugging-common-failures\n'))
raise ProguardProcessError(err, debugging_link) raise ProguardProcessError(err, debugging_link)
base_dex_context.Commit() found_files = build_utils.FindInDirectory(tmp_output)
if options.feature_names: if not options.output_path.endswith('.dex'):
for feature in feature_contexts: # Add to .jar using Python rather than having R8 output to a .zip directly
feature.Commit() # in order to disable compression of the .jar, saving ~500ms.
tmp_jar_output = tmp_output + '.jar'
build_utils.DoZip(found_files, tmp_jar_output, base_dir=tmp_output)
shutil.move(tmp_jar_output, options.output_path)
else:
if len(found_files) > 1:
raise Exception('Too many files created: {}'.format(found_files))
shutil.move(found_files[0], options.output_path)
with open(options.mapping_output, 'w') as out_file, \ with open(options.mapping_output, 'w') as out_file, \
open(tmp_mapping_path) as in_file: open(tmp_mapping_path) as in_file:
...@@ -364,8 +279,6 @@ def _OptimizeWithR8(options, ...@@ -364,8 +279,6 @@ def _OptimizeWithR8(options,
# some of our tooling so remove those (specifically: apkanalyzer). # some of our tooling so remove those (specifically: apkanalyzer).
out_file.writelines(l for l in in_file if not l.startswith('#')) out_file.writelines(l for l in in_file if not l.startswith('#'))
return input_code_paths
def _OptimizeWithProguard(options, def _OptimizeWithProguard(options,
config_paths, config_paths,
...@@ -546,29 +459,23 @@ def main(): ...@@ -546,29 +459,23 @@ def main():
options.output_config, options.output_config,
options.proguard_expectations_failure_file) options.proguard_expectations_failure_file)
inputs = options.proguard_configs + libraries
if options.r8_path: if options.r8_path:
inputs += _OptimizeWithR8(options, proguard_configs, libraries, _OptimizeWithR8(options, proguard_configs, libraries, dynamic_config_data,
dynamic_config_data, print_stdout) print_stdout)
else: else:
_OptimizeWithProguard(options, proguard_configs, libraries, _OptimizeWithProguard(options, proguard_configs, libraries,
dynamic_config_data, print_stdout) dynamic_config_data, print_stdout)
inputs += options.input_paths
# After ProGuard / R8 has run: # After ProGuard / R8 has run:
for output in options.extra_mapping_output_paths: for output in options.extra_mapping_output_paths:
shutil.copy(options.mapping_output, output) shutil.copy(options.mapping_output, output)
inputs = options.proguard_configs + options.input_paths + libraries
if options.apply_mapping: if options.apply_mapping:
inputs.append(options.apply_mapping) inputs.append(options.apply_mapping)
output_path = options.output_path
if options.stamp:
build_utils.Touch(options.stamp)
output_path = options.stamp
build_utils.WriteDepfile( build_utils.WriteDepfile(
options.depfile, output_path, inputs=inputs, add_pydeps=False) options.depfile, options.output_path, inputs=inputs, add_pydeps=False)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -969,10 +969,16 @@ if (enable_java_templates) { ...@@ -969,10 +969,16 @@ if (enable_java_templates) {
_mapping_path = invoker.proguard_mapping_path _mapping_path = invoker.proguard_mapping_path
} }
depfile = "${target_gen_dir}/${target_name}.d" depfile = "${target_gen_dir}/${target_name}.d"
outputs = [
_output_path,
_mapping_path,
]
_rebased_build_config = rebase_path(invoker.build_config, root_build_dir) _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
args = [ args = [
"--depfile", "--depfile",
rebase_path(depfile, root_build_dir), rebase_path(depfile, root_build_dir),
"--output-path",
rebase_path(_output_path, root_build_dir),
"--mapping-output", "--mapping-output",
rebase_path(_mapping_path, root_build_dir), rebase_path(_mapping_path, root_build_dir),
"--classpath", "--classpath",
...@@ -981,35 +987,6 @@ if (enable_java_templates) { ...@@ -981,35 +987,6 @@ if (enable_java_templates) {
"@FileArg($_rebased_build_config:android:sdk_jars)", "@FileArg($_rebased_build_config:android:sdk_jars)",
] ]
if (defined(invoker.modules)) {
foreach(_feature_module, invoker.modules) {
_rebased_module_build_config =
rebase_path(_feature_module.build_config, root_build_dir)
args += [
"--feature-name",
_feature_module.name,
"--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)",
]
if (!defined(invoker.feature_jars_args)) {
args += [ "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:java_runtime_classpath)" ]
}
deps += [ _feature_module.build_config_target ]
}
_stamp = "${target_gen_dir}/${target_name}.stamp"
outputs = [ _stamp ]
args += [
"--stamp",
rebase_path(_stamp, root_build_dir),
]
} else {
args += [
"--output-path",
rebase_path(_output_path, root_build_dir),
]
outputs = [ _output_path ]
}
outputs += [ _mapping_path ]
if (defined(invoker.disable_r8_outlining) && if (defined(invoker.disable_r8_outlining) &&
invoker.disable_r8_outlining) { invoker.disable_r8_outlining) {
args += [ "--disable-outlining" ] args += [ "--disable-outlining" ]
...@@ -1129,6 +1106,8 @@ if (enable_java_templates) { ...@@ -1129,6 +1106,8 @@ if (enable_java_templates) {
# apply_mapping: The path to the ProGuard mapping file to apply. # apply_mapping: The path to the ProGuard mapping file to apply.
# disable_incremental: Disable incremental dexing. # disable_incremental: Disable incremental dexing.
template("dex") { template("dex") {
assert(defined(invoker.output))
_proguard_enabled = _proguard_enabled =
defined(invoker.proguard_enabled) && invoker.proguard_enabled defined(invoker.proguard_enabled) && invoker.proguard_enabled
_proguarding_with_r8 = _proguarding_with_r8 =
...@@ -1143,8 +1122,7 @@ if (enable_java_templates) { ...@@ -1143,8 +1122,7 @@ if (enable_java_templates) {
not_needed(invoker, [ "negative_main_dex_globs" ]) not_needed(invoker, [ "negative_main_dex_globs" ])
} }
} }
assert(defined(invoker.output) ||
(_proguarding_with_r8 && defined(invoker.modules)))
assert(!_proguard_enabled || !(defined(invoker.input_dex_filearg) || assert(!_proguard_enabled || !(defined(invoker.input_dex_filearg) ||
defined(invoker.input_classes_filearg) || defined(invoker.input_classes_filearg) ||
defined(invoker.input_class_jars)), defined(invoker.input_class_jars)),
...@@ -1159,13 +1137,7 @@ if (enable_java_templates) { ...@@ -1159,13 +1137,7 @@ if (enable_java_templates) {
if (_proguard_enabled) { if (_proguard_enabled) {
if (_proguarding_with_r8) { if (_proguarding_with_r8) {
if (defined(invoker.output)) { _proguard_output_path = invoker.output
_proguard_output_path = invoker.output
} else {
# This will never actually be created, but other outputs use this as
# a base bath.
_proguard_output_path = "$target_gen_dir/$target_name.jar"
}
_proguard_target_name = target_name _proguard_target_name = target_name
_proguard_config_output_path = "$_proguard_output_path.proguard_flags" _proguard_config_output_path = "$_proguard_output_path.proguard_flags"
} else { } else {
...@@ -1181,7 +1153,6 @@ if (enable_java_templates) { ...@@ -1181,7 +1153,6 @@ if (enable_java_templates) {
"disable_r8_outlining", "disable_r8_outlining",
"deps", "deps",
"failed_proguard_expectation_file", "failed_proguard_expectation_file",
"modules",
"proguard_expectations_file", "proguard_expectations_file",
"proguard_jar_path", "proguard_jar_path",
"proguard_mapping_path", "proguard_mapping_path",
......
...@@ -4462,9 +4462,12 @@ if (enable_java_templates) { ...@@ -4462,9 +4462,12 @@ if (enable_java_templates) {
_uses_static_library_synchronized_proguard = _uses_static_library_synchronized_proguard =
defined(invoker.static_library_synchronized_proguard) && defined(invoker.static_library_synchronized_proguard) &&
invoker.static_library_synchronized_proguard invoker.static_library_synchronized_proguard
if (_uses_static_library_synchronized_proguard) {
# TODO(crbug.com/1032609): Remove dexsplitter from Trichrome Proguard. _sync_dex_target_dep = "${invoker.static_library_provider}__dexsplitter"
_dex_target = "${_target_name}__dex" } else {
_sync_dex_target = "${_target_name}__sync_dex"
_sync_dex_target_dep = ":$_sync_dex_target"
}
_proguard_mapping_path = "${_bundle_path}.mapping" _proguard_mapping_path = "${_bundle_path}.mapping"
} }
...@@ -4578,12 +4581,16 @@ if (enable_java_templates) { ...@@ -4578,12 +4581,16 @@ if (enable_java_templates) {
_proguard_mapping_path = "${_bundle_path}.mapping" _proguard_mapping_path = "${_bundle_path}.mapping"
} }
_unsplit_dex_zip =
"${target_gen_dir}/${_target_name}/${_target_name}__unsplit_dex.zip"
write_build_config(_build_config_target) { write_build_config(_build_config_target) {
type = "android_app_bundle" type = "android_app_bundle"
possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ] possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ]
build_config = _build_config build_config = _build_config
proguard_enabled = _proguard_enabled proguard_enabled = _proguard_enabled
module_build_configs = _module_build_configs module_build_configs = _module_build_configs
final_dex_path = _unsplit_dex_zip
if (_proguard_enabled) { if (_proguard_enabled) {
proguard_mapping_path = _proguard_mapping_path proguard_mapping_path = _proguard_mapping_path
...@@ -4608,7 +4615,7 @@ if (enable_java_templates) { ...@@ -4608,7 +4615,7 @@ if (enable_java_templates) {
get_label_info(":$_target_name", "dir") + get_label_info(":$_target_name", "dir") +
"/java/$_target_name.proguard_flags.expected" "/java/$_target_name.proguard_flags.expected"
} }
dex(_dex_target) { dex(_sync_dex_target) {
enable_multidex = _enable_multidex enable_multidex = _enable_multidex
proguard_enabled = true proguard_enabled = true
proguard_mapping_path = _proguard_mapping_path proguard_mapping_path = _proguard_mapping_path
...@@ -4625,9 +4632,20 @@ if (enable_java_templates) { ...@@ -4625,9 +4632,20 @@ if (enable_java_templates) {
} }
deps = _module_java_targets + [ ":$_build_config_target" ] deps = _module_java_targets + [ ":$_build_config_target" ]
modules = _modules output = _unsplit_dex_zip
} }
} }
_dexsplitter_target = "${_target_name}__dexsplitter"
dexsplitter(_dexsplitter_target) {
input_dex_zip = _unsplit_dex_zip
proguard_mapping = _proguard_mapping_path
all_modules = _modules
deps = [
":$_build_config_target",
_sync_dex_target_dep,
] + _module_java_targets
}
} }
_all_create_module_targets = [] _all_create_module_targets = []
...@@ -4641,7 +4659,7 @@ if (enable_java_templates) { ...@@ -4641,7 +4659,7 @@ if (enable_java_templates) {
if (!_proguard_enabled) { if (!_proguard_enabled) {
_dex_target_for_module = "${_module_target}__final_dex" _dex_target_for_module = "${_module_target}__final_dex"
} else { } else {
_dex_target_for_module = ":$_dex_target" _dex_target_for_module = ":$_dexsplitter_target"
} }
# Generate one module .zip file per bundle module. # Generate one module .zip file per bundle module.
......
...@@ -18,7 +18,6 @@ Turning off outlining because it caused issues when synchronized proguarding ...@@ -18,7 +18,6 @@ Turning off outlining because it caused issues when synchronized proguarding
Trichrome due to illegal dex references (crbug.com/956839). Will only be used Trichrome due to illegal dex references (crbug.com/956839). Will only be used
for android_apk() targets that set `disable_r8_outlining = true`): for android_apk() targets that set `disable_r8_outlining = true`):
Adding command line support for having R8 generate feature module .dex files Increase callGraphCycleEliminatorMaxDepthThreshold (b/143685705).
(crbug.com/1032609).
Patch is located at //third_party/r8/local_modifications.diff. Patch is located at //third_party/r8/local_modifications.diff.
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 8c63d06f5..aee9ba39b 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
+import com.android.tools.r8.DexIndexedConsumer.DirectoryConsumer;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
@@ -268,6 +269,15 @@ public final class R8Command extends BaseCompilerCommand {
return self();
}
+ public Builder addFeatureJar(Path inputJarPath, Path outputPath) {
+ addFeatureSplit(splitBuilder ->
+ splitBuilder
+ .addProgramResourceProvider(ArchiveProgramResourceProvider.fromArchive(inputJarPath))
+ .setProgramConsumer(new DirectoryConsumer(outputPath))
+ .build());
+ return self();
+ }
+
/**
* Set a consumer for receiving the proguard seeds information.
*
diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java
index fd4f570ea..66a2e9506 100644
--- a/src/main/java/com/android/tools/r8/R8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/R8CommandParser.java
@@ -25,7 +25,8 @@ public class R8CommandParser extends BaseCompilerCommandParser {
"--main-dex-list",
"--main-dex-list-output",
"--pg-conf",
- "--pg-map-output");
+ "--pg-map-output",
+ "--feature-jar");
public static void main(String[] args) throws CompilationFailedException {
R8Command command = parse(args, Origin.root()).build();
@@ -74,8 +75,11 @@ public class R8CommandParser extends BaseCompilerCommandParser {
" --main-dex-list <file> # List of classes to place in the primary dex file.",
" --main-dex-list-output <file> ",
" # Output the full main-dex list in <file>.",
+ " --feature-jar <file>:<file> ",
+ " # Feature jar <input-file>:<output-dir> files.",
" --version # Print the version of r8.",
" --help # Print this message."));
+
/**
* Parse the R8 command-line.
*
@@ -208,6 +212,11 @@ public class R8CommandParser extends BaseCompilerCommandParser {
builder.setProguardMapOutputPath(Paths.get(nextArg));
} else if (arg.equals("--no-data-resources")) {
state.includeDataResources = false;
+ } else if (arg.equals("--feature-jar")) {
+ String[] argParts = nextArg.split(":");
+ String featureJarInputPath = argParts[0];
+ String featureJarOutputPath = argParts[1];
+ builder.addFeatureJar(Paths.get(featureJarInputPath), Paths.get(featureJarOutputPath));
} else {
if (arg.startsWith("--")) {
builder.error(new StringDiagnostic("Unknown option: " + arg, argsOrigin));
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 595ac28da..e96f06364 100644 index 595ac28da..e96f06364 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java --- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment