blob: 85bc30552a5cebc36d54d765e785e2e9ff8715bb [file] [log] [blame]
Søren Gjessec4e5e932017-09-04 17:01:23 +02001// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4package com.android.tools.r8;
5
Ian Zernybbb59cc2018-12-21 14:23:58 +01006import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
Søren Gjessec4e5e932017-09-04 17:01:23 +02007import com.android.tools.r8.graph.DexItemFactory;
Yohann Rousself17d02d2017-11-29 18:08:09 +01008import com.android.tools.r8.origin.CommandLineOrigin;
Yohann Roussel73df5e62017-11-20 14:06:32 +01009import com.android.tools.r8.origin.Origin;
Søren Gjessec4e5e932017-09-04 17:01:23 +020010import com.android.tools.r8.shaking.ProguardConfigurationParser;
11import com.android.tools.r8.shaking.ProguardConfigurationRule;
12import com.android.tools.r8.shaking.ProguardConfigurationSource;
13import com.android.tools.r8.shaking.ProguardConfigurationSourceFile;
14import com.android.tools.r8.shaking.ProguardConfigurationSourceStrings;
Søren Gjessec4e5e932017-09-04 17:01:23 +020015import com.android.tools.r8.utils.AndroidApp;
16import com.android.tools.r8.utils.InternalOptions;
Morten Krogh-Jespersen3639d3a2021-03-03 19:23:21 +010017import com.android.tools.r8.utils.JoiningStringConsumer;
Yohann Roussel9a8d4372017-11-21 14:36:44 +010018import com.android.tools.r8.utils.Reporter;
19import com.android.tools.r8.utils.StringDiagnostic;
Søren Gjessec4e5e932017-09-04 17:01:23 +020020import com.google.common.collect.ImmutableList;
Søren Gjessec4e5e932017-09-04 17:01:23 +020021import java.nio.file.Path;
22import java.nio.file.Paths;
23import java.util.ArrayList;
24import java.util.List;
25
Tamas Kenez111a47b2018-12-17 15:31:55 +010026@Keep
Søren Gjessec4e5e932017-09-04 17:01:23 +020027public class GenerateMainDexListCommand extends BaseCommand {
28
Morten Krogh-Jespersen3ebe2162019-01-10 11:04:46 +010029 private final List<ProguardConfigurationRule> mainDexKeepRules;
Ian Zerny7c5c4f72017-12-06 13:37:07 +010030 private final StringConsumer mainDexListConsumer;
Ian Zerny6375a9e2018-12-14 13:52:48 +010031 private final GraphConsumer mainDexKeptGraphConsumer;
Søren Gjessec4e5e932017-09-04 17:01:23 +020032 private final DexItemFactory factory;
Søren Gjessec25649a2018-02-01 12:41:28 +010033 private final Reporter reporter;
Søren Gjessec4e5e932017-09-04 17:01:23 +020034
Tamas Kenez111a47b2018-12-17 15:31:55 +010035 @Keep
Søren Gjessec4e5e932017-09-04 17:01:23 +020036 public static class Builder extends BaseCommand.Builder<GenerateMainDexListCommand, Builder> {
37
38 private final DexItemFactory factory = new DexItemFactory();
39 private final List<ProguardConfigurationSource> mainDexRules = new ArrayList<>();
Søren Gjesseb8307362018-01-22 17:30:46 +010040 private StringConsumer mainDexListConsumer = null;
Ian Zerny6375a9e2018-12-14 13:52:48 +010041 private GraphConsumer mainDexKeptGraphConsumer = null;
Søren Gjessec4e5e932017-09-04 17:01:23 +020042
Søren Gjessec25649a2018-02-01 12:41:28 +010043 private Builder() {
44 }
45
46 private Builder(DiagnosticsHandler diagnosticsHandler) {
47 super(diagnosticsHandler);
48 }
49
50
Søren Gjessec4e5e932017-09-04 17:01:23 +020051 @Override
52 GenerateMainDexListCommand.Builder self() {
53 return this;
54 }
55
56 /**
57 * Add proguard configuration file resources for automatic main dex list calculation.
58 */
59 public GenerateMainDexListCommand.Builder addMainDexRulesFiles(Path... paths) {
Yohann Roussel11efcc02017-12-01 12:04:36 +010060 guard(() -> {
61 for (Path path : paths) {
62 mainDexRules.add(new ProguardConfigurationSourceFile(path));
63 }
64 });
Søren Gjessec4e5e932017-09-04 17:01:23 +020065 return self();
66 }
67
68 /**
69 * Add proguard configuration file resources for automatic main dex list calculation.
70 */
71 public GenerateMainDexListCommand.Builder addMainDexRulesFiles(List<Path> paths) {
Yohann Roussel11efcc02017-12-01 12:04:36 +010072 guard(() -> {
73 for (Path path : paths) {
74 mainDexRules.add(new ProguardConfigurationSourceFile(path));
75 }
76 });
Søren Gjessec4e5e932017-09-04 17:01:23 +020077 return self();
78 }
79
80 /**
81 * Add proguard configuration for automatic main dex list calculation.
82 */
Yohann Roussel73df5e62017-11-20 14:06:32 +010083 public GenerateMainDexListCommand.Builder addMainDexRules(List<String> lines, Origin origin) {
Yohann Roussel11efcc02017-12-01 12:04:36 +010084 guard(() -> mainDexRules.add(
85 new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin)));
Søren Gjessec4e5e932017-09-04 17:01:23 +020086 return self();
87 }
88
89 /**
Søren Gjessec4e5e932017-09-04 17:01:23 +020090 * Set the output file for the main-dex list.
91 *
92 * If the file exists it will be overwritten.
93 */
94 public GenerateMainDexListCommand.Builder setMainDexListOutputPath(Path mainDexListOutputPath) {
Søren Gjesseb8307362018-01-22 17:30:46 +010095 mainDexListConsumer = new StringConsumer.FileConsumer(mainDexListOutputPath);
Søren Gjessec4e5e932017-09-04 17:01:23 +020096 return self();
97 }
98
Søren Gjesseb8307362018-01-22 17:30:46 +010099 public GenerateMainDexListCommand.Builder setMainDexListConsumer(
100 StringConsumer mainDexListConsumer) {
101 this.mainDexListConsumer = mainDexListConsumer;
102 return self();
103 }
Søren Gjessec4e5e932017-09-04 17:01:23 +0200104
105 @Override
Yohann Rousself17d02d2017-11-29 18:08:09 +0100106 protected GenerateMainDexListCommand makeCommand() {
Søren Gjessec4e5e932017-09-04 17:01:23 +0200107 // If printing versions ignore everything else.
108 if (isPrintHelp() || isPrintVersion()) {
109 return new GenerateMainDexListCommand(isPrintHelp(), isPrintVersion());
110 }
111
Ian Zerny99683a32021-01-12 19:11:56 +0100112 List<ProguardConfigurationRule> mainDexKeepRules =
113 ProguardConfigurationParser.parse(mainDexRules, factory, getReporter());
Søren Gjessec4e5e932017-09-04 17:01:23 +0200114
115 return new GenerateMainDexListCommand(
Ian Zerny6375a9e2018-12-14 13:52:48 +0100116 factory,
117 getAppBuilder().build(),
118 mainDexKeepRules,
Morten Krogh-Jespersen3639d3a2021-03-03 19:23:21 +0100119 new JoiningStringConsumer(mainDexListConsumer, "\n"),
Ian Zerny6375a9e2018-12-14 13:52:48 +0100120 mainDexKeptGraphConsumer,
121 getReporter());
122 }
123
124 public GenerateMainDexListCommand.Builder setMainDexKeptGraphConsumer(
125 GraphConsumer graphConsumer) {
126 this.mainDexKeptGraphConsumer = graphConsumer;
127 return self();
Søren Gjessec4e5e932017-09-04 17:01:23 +0200128 }
129 }
130
131 static final String USAGE_MESSAGE = String.join("\n", ImmutableList.of(
132 "Usage: maindex [options] <input-files>",
133 " where <input-files> are JAR files",
134 " and options are:",
Søren Gjesseb8307362018-01-22 17:30:46 +0100135 " --lib <file> # Add <file> as a library resource.",
Søren Gjessec4e5e932017-09-04 17:01:23 +0200136 " --main-dex-rules <file> # Proguard keep rules for classes to place in the",
137 " # primary dex file.",
138 " --main-dex-list <file> # List of classes to place in the primary dex file.",
139 " --main-dex-list-output <file> # Output the full main-dex list in <file>.",
140 " --version # Print the version.",
141 " --help # Print this message."));
142
143
144 public static GenerateMainDexListCommand.Builder builder() {
145 return new GenerateMainDexListCommand.Builder();
146 }
147
Søren Gjessec25649a2018-02-01 12:41:28 +0100148 public static GenerateMainDexListCommand.Builder builder(DiagnosticsHandler diagnosticsHandler) {
149 return new GenerateMainDexListCommand.Builder(diagnosticsHandler);
150 }
151
Yohann Rousself17d02d2017-11-29 18:08:09 +0100152 public static GenerateMainDexListCommand.Builder parse(String[] args) {
Søren Gjessec4e5e932017-09-04 17:01:23 +0200153 GenerateMainDexListCommand.Builder builder = builder();
154 parse(args, builder);
155 return builder;
156 }
157
Søren Gjesseb8307362018-01-22 17:30:46 +0100158 public StringConsumer getMainDexListConsumer() {
159 return mainDexListConsumer;
160 }
161
Søren Gjessedf81e4a2018-08-17 09:11:21 +0200162 Reporter getReporter() {
163 return reporter;
164 }
165
Yohann Rousself17d02d2017-11-29 18:08:09 +0100166 private static void parse(String[] args, GenerateMainDexListCommand.Builder builder) {
Søren Gjessec4e5e932017-09-04 17:01:23 +0200167 for (int i = 0; i < args.length; i++) {
168 String arg = args[i].trim();
169 if (arg.length() == 0) {
170 continue;
171 } else if (arg.equals("--help")) {
172 builder.setPrintHelp(true);
173 } else if (arg.equals("--version")) {
174 builder.setPrintVersion(true);
Søren Gjesseb8307362018-01-22 17:30:46 +0100175 } else if (arg.equals("--lib")) {
176 builder.addLibraryFiles(Paths.get(args[++i]));
Søren Gjessec4e5e932017-09-04 17:01:23 +0200177 } else if (arg.equals("--main-dex-rules")) {
178 builder.addMainDexRulesFiles(Paths.get(args[++i]));
179 } else if (arg.equals("--main-dex-list")) {
180 builder.addMainDexListFiles(Paths.get(args[++i]));
181 } else if (arg.equals("--main-dex-list-output")) {
182 builder.setMainDexListOutputPath(Paths.get(args[++i]));
183 } else {
184 if (arg.startsWith("--")) {
Yohann Rousself17d02d2017-11-29 18:08:09 +0100185 builder.getReporter().error(new StringDiagnostic("Unknown option: " + arg,
186 CommandLineOrigin.INSTANCE));
Søren Gjessec4e5e932017-09-04 17:01:23 +0200187 }
188 builder.addProgramFiles(Paths.get(arg));
189 }
190 }
191 }
192
193 private GenerateMainDexListCommand(
194 DexItemFactory factory,
195 AndroidApp inputApp,
Morten Krogh-Jespersen3ebe2162019-01-10 11:04:46 +0100196 List<ProguardConfigurationRule> mainDexKeepRules,
Søren Gjessec25649a2018-02-01 12:41:28 +0100197 StringConsumer mainDexListConsumer,
Ian Zerny6375a9e2018-12-14 13:52:48 +0100198 GraphConsumer mainDexKeptGraphConsumer,
Søren Gjessec25649a2018-02-01 12:41:28 +0100199 Reporter reporter) {
Søren Gjessec4e5e932017-09-04 17:01:23 +0200200 super(inputApp);
201 this.factory = factory;
202 this.mainDexKeepRules = mainDexKeepRules;
Ian Zerny7c5c4f72017-12-06 13:37:07 +0100203 this.mainDexListConsumer = mainDexListConsumer;
Ian Zerny6375a9e2018-12-14 13:52:48 +0100204 this.mainDexKeptGraphConsumer = mainDexKeptGraphConsumer;
Søren Gjessec25649a2018-02-01 12:41:28 +0100205 this.reporter = reporter;
Søren Gjessec4e5e932017-09-04 17:01:23 +0200206 }
207
208 private GenerateMainDexListCommand(boolean printHelp, boolean printVersion) {
209 super(printHelp, printVersion);
210 this.factory = new DexItemFactory();
211 this.mainDexKeepRules = ImmutableList.of();
Ian Zerny7c5c4f72017-12-06 13:37:07 +0100212 this.mainDexListConsumer = null;
Ian Zerny6375a9e2018-12-14 13:52:48 +0100213 this.mainDexKeptGraphConsumer = null;
Morten Krogh-Jespersenff59ed32018-10-08 15:15:57 +0200214 this.reporter = new Reporter();
Søren Gjessec4e5e932017-09-04 17:01:23 +0200215 }
216
217 @Override
218 InternalOptions getInternalOptions() {
Søren Gjessec25649a2018-02-01 12:41:28 +0100219 InternalOptions internal = new InternalOptions(factory, reporter);
Ian Zernye8639dd2020-09-21 08:46:41 +0200220 internal.programConsumer = DexIndexedConsumer.emptyConsumer();
Søren Gjessec4e5e932017-09-04 17:01:23 +0200221 internal.mainDexKeepRules = mainDexKeepRules;
Ian Zerny7c5c4f72017-12-06 13:37:07 +0100222 internal.mainDexListConsumer = mainDexListConsumer;
Ian Zerny6375a9e2018-12-14 13:52:48 +0100223 internal.mainDexKeptGraphConsumer = mainDexKeptGraphConsumer;
Søren Gjessec4e5e932017-09-04 17:01:23 +0200224 internal.minimalMainDex = internal.debug;
Jake Wharton5828ede2019-06-25 10:42:28 -0400225 internal.enableEnumValueOptimization = false;
Søren Gjesse37c4f6e2018-02-12 13:41:13 +0100226 internal.enableInlining = false;
Søren Gjessec4e5e932017-09-04 17:01:23 +0200227 return internal;
228 }
229}
230