Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 1 | // 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. |
| 4 | package com.android.tools.r8; |
| 5 | |
Ian Zerny | bbb59cc | 2018-12-21 14:23:58 +0100 | [diff] [blame] | 6 | import com.android.tools.r8.experimental.graphinfo.GraphConsumer; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 7 | import com.android.tools.r8.graph.DexItemFactory; |
Yohann Roussel | f17d02d | 2017-11-29 18:08:09 +0100 | [diff] [blame] | 8 | import com.android.tools.r8.origin.CommandLineOrigin; |
Yohann Roussel | 73df5e6 | 2017-11-20 14:06:32 +0100 | [diff] [blame] | 9 | import com.android.tools.r8.origin.Origin; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 10 | import com.android.tools.r8.shaking.ProguardConfigurationParser; |
| 11 | import com.android.tools.r8.shaking.ProguardConfigurationRule; |
| 12 | import com.android.tools.r8.shaking.ProguardConfigurationSource; |
| 13 | import com.android.tools.r8.shaking.ProguardConfigurationSourceFile; |
| 14 | import com.android.tools.r8.shaking.ProguardConfigurationSourceStrings; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 15 | import com.android.tools.r8.utils.AndroidApp; |
| 16 | import com.android.tools.r8.utils.InternalOptions; |
Morten Krogh-Jespersen | 3639d3a | 2021-03-03 19:23:21 +0100 | [diff] [blame] | 17 | import com.android.tools.r8.utils.JoiningStringConsumer; |
Yohann Roussel | 9a8d437 | 2017-11-21 14:36:44 +0100 | [diff] [blame] | 18 | import com.android.tools.r8.utils.Reporter; |
| 19 | import com.android.tools.r8.utils.StringDiagnostic; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 20 | import com.google.common.collect.ImmutableList; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 21 | import java.nio.file.Path; |
| 22 | import java.nio.file.Paths; |
| 23 | import java.util.ArrayList; |
| 24 | import java.util.List; |
| 25 | |
Tamas Kenez | 111a47b | 2018-12-17 15:31:55 +0100 | [diff] [blame] | 26 | @Keep |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 27 | public class GenerateMainDexListCommand extends BaseCommand { |
| 28 | |
Morten Krogh-Jespersen | 3ebe216 | 2019-01-10 11:04:46 +0100 | [diff] [blame] | 29 | private final List<ProguardConfigurationRule> mainDexKeepRules; |
Ian Zerny | 7c5c4f7 | 2017-12-06 13:37:07 +0100 | [diff] [blame] | 30 | private final StringConsumer mainDexListConsumer; |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 31 | private final GraphConsumer mainDexKeptGraphConsumer; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 32 | private final DexItemFactory factory; |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 33 | private final Reporter reporter; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 34 | |
Tamas Kenez | 111a47b | 2018-12-17 15:31:55 +0100 | [diff] [blame] | 35 | @Keep |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 36 | 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 Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 40 | private StringConsumer mainDexListConsumer = null; |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 41 | private GraphConsumer mainDexKeptGraphConsumer = null; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 42 | |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 43 | private Builder() { |
| 44 | } |
| 45 | |
| 46 | private Builder(DiagnosticsHandler diagnosticsHandler) { |
| 47 | super(diagnosticsHandler); |
| 48 | } |
| 49 | |
| 50 | |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 51 | @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 Roussel | 11efcc0 | 2017-12-01 12:04:36 +0100 | [diff] [blame] | 60 | guard(() -> { |
| 61 | for (Path path : paths) { |
| 62 | mainDexRules.add(new ProguardConfigurationSourceFile(path)); |
| 63 | } |
| 64 | }); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 65 | 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 Roussel | 11efcc0 | 2017-12-01 12:04:36 +0100 | [diff] [blame] | 72 | guard(() -> { |
| 73 | for (Path path : paths) { |
| 74 | mainDexRules.add(new ProguardConfigurationSourceFile(path)); |
| 75 | } |
| 76 | }); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 77 | return self(); |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * Add proguard configuration for automatic main dex list calculation. |
| 82 | */ |
Yohann Roussel | 73df5e6 | 2017-11-20 14:06:32 +0100 | [diff] [blame] | 83 | public GenerateMainDexListCommand.Builder addMainDexRules(List<String> lines, Origin origin) { |
Yohann Roussel | 11efcc0 | 2017-12-01 12:04:36 +0100 | [diff] [blame] | 84 | guard(() -> mainDexRules.add( |
| 85 | new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin))); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 86 | return self(); |
| 87 | } |
| 88 | |
| 89 | /** |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 90 | * 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 Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 95 | mainDexListConsumer = new StringConsumer.FileConsumer(mainDexListOutputPath); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 96 | return self(); |
| 97 | } |
| 98 | |
Søren Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 99 | public GenerateMainDexListCommand.Builder setMainDexListConsumer( |
| 100 | StringConsumer mainDexListConsumer) { |
| 101 | this.mainDexListConsumer = mainDexListConsumer; |
| 102 | return self(); |
| 103 | } |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 104 | |
| 105 | @Override |
Yohann Roussel | f17d02d | 2017-11-29 18:08:09 +0100 | [diff] [blame] | 106 | protected GenerateMainDexListCommand makeCommand() { |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 107 | // If printing versions ignore everything else. |
| 108 | if (isPrintHelp() || isPrintVersion()) { |
| 109 | return new GenerateMainDexListCommand(isPrintHelp(), isPrintVersion()); |
| 110 | } |
| 111 | |
Ian Zerny | 99683a3 | 2021-01-12 19:11:56 +0100 | [diff] [blame] | 112 | List<ProguardConfigurationRule> mainDexKeepRules = |
| 113 | ProguardConfigurationParser.parse(mainDexRules, factory, getReporter()); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 114 | |
| 115 | return new GenerateMainDexListCommand( |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 116 | factory, |
| 117 | getAppBuilder().build(), |
| 118 | mainDexKeepRules, |
Morten Krogh-Jespersen | 3639d3a | 2021-03-03 19:23:21 +0100 | [diff] [blame] | 119 | new JoiningStringConsumer(mainDexListConsumer, "\n"), |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 120 | mainDexKeptGraphConsumer, |
| 121 | getReporter()); |
| 122 | } |
| 123 | |
| 124 | public GenerateMainDexListCommand.Builder setMainDexKeptGraphConsumer( |
| 125 | GraphConsumer graphConsumer) { |
| 126 | this.mainDexKeptGraphConsumer = graphConsumer; |
| 127 | return self(); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 128 | } |
| 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 Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 135 | " --lib <file> # Add <file> as a library resource.", |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 136 | " --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 Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 148 | public static GenerateMainDexListCommand.Builder builder(DiagnosticsHandler diagnosticsHandler) { |
| 149 | return new GenerateMainDexListCommand.Builder(diagnosticsHandler); |
| 150 | } |
| 151 | |
Yohann Roussel | f17d02d | 2017-11-29 18:08:09 +0100 | [diff] [blame] | 152 | public static GenerateMainDexListCommand.Builder parse(String[] args) { |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 153 | GenerateMainDexListCommand.Builder builder = builder(); |
| 154 | parse(args, builder); |
| 155 | return builder; |
| 156 | } |
| 157 | |
Søren Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 158 | public StringConsumer getMainDexListConsumer() { |
| 159 | return mainDexListConsumer; |
| 160 | } |
| 161 | |
Søren Gjesse | df81e4a | 2018-08-17 09:11:21 +0200 | [diff] [blame] | 162 | Reporter getReporter() { |
| 163 | return reporter; |
| 164 | } |
| 165 | |
Yohann Roussel | f17d02d | 2017-11-29 18:08:09 +0100 | [diff] [blame] | 166 | private static void parse(String[] args, GenerateMainDexListCommand.Builder builder) { |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 167 | 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 Gjesse | b830736 | 2018-01-22 17:30:46 +0100 | [diff] [blame] | 175 | } else if (arg.equals("--lib")) { |
| 176 | builder.addLibraryFiles(Paths.get(args[++i])); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 177 | } 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 Roussel | f17d02d | 2017-11-29 18:08:09 +0100 | [diff] [blame] | 185 | builder.getReporter().error(new StringDiagnostic("Unknown option: " + arg, |
| 186 | CommandLineOrigin.INSTANCE)); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 187 | } |
| 188 | builder.addProgramFiles(Paths.get(arg)); |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | private GenerateMainDexListCommand( |
| 194 | DexItemFactory factory, |
| 195 | AndroidApp inputApp, |
Morten Krogh-Jespersen | 3ebe216 | 2019-01-10 11:04:46 +0100 | [diff] [blame] | 196 | List<ProguardConfigurationRule> mainDexKeepRules, |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 197 | StringConsumer mainDexListConsumer, |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 198 | GraphConsumer mainDexKeptGraphConsumer, |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 199 | Reporter reporter) { |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 200 | super(inputApp); |
| 201 | this.factory = factory; |
| 202 | this.mainDexKeepRules = mainDexKeepRules; |
Ian Zerny | 7c5c4f7 | 2017-12-06 13:37:07 +0100 | [diff] [blame] | 203 | this.mainDexListConsumer = mainDexListConsumer; |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 204 | this.mainDexKeptGraphConsumer = mainDexKeptGraphConsumer; |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 205 | this.reporter = reporter; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | private GenerateMainDexListCommand(boolean printHelp, boolean printVersion) { |
| 209 | super(printHelp, printVersion); |
| 210 | this.factory = new DexItemFactory(); |
| 211 | this.mainDexKeepRules = ImmutableList.of(); |
Ian Zerny | 7c5c4f7 | 2017-12-06 13:37:07 +0100 | [diff] [blame] | 212 | this.mainDexListConsumer = null; |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 213 | this.mainDexKeptGraphConsumer = null; |
Morten Krogh-Jespersen | ff59ed3 | 2018-10-08 15:15:57 +0200 | [diff] [blame] | 214 | this.reporter = new Reporter(); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | @Override |
| 218 | InternalOptions getInternalOptions() { |
Søren Gjesse | c25649a | 2018-02-01 12:41:28 +0100 | [diff] [blame] | 219 | InternalOptions internal = new InternalOptions(factory, reporter); |
Ian Zerny | e8639dd | 2020-09-21 08:46:41 +0200 | [diff] [blame] | 220 | internal.programConsumer = DexIndexedConsumer.emptyConsumer(); |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 221 | internal.mainDexKeepRules = mainDexKeepRules; |
Ian Zerny | 7c5c4f7 | 2017-12-06 13:37:07 +0100 | [diff] [blame] | 222 | internal.mainDexListConsumer = mainDexListConsumer; |
Ian Zerny | 6375a9e | 2018-12-14 13:52:48 +0100 | [diff] [blame] | 223 | internal.mainDexKeptGraphConsumer = mainDexKeptGraphConsumer; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 224 | internal.minimalMainDex = internal.debug; |
Jake Wharton | 5828ede | 2019-06-25 10:42:28 -0400 | [diff] [blame] | 225 | internal.enableEnumValueOptimization = false; |
Søren Gjesse | 37c4f6e | 2018-02-12 13:41:13 +0100 | [diff] [blame] | 226 | internal.enableInlining = false; |
Søren Gjesse | c4e5e93 | 2017-09-04 17:01:23 +0200 | [diff] [blame] | 227 | return internal; |
| 228 | } |
| 229 | } |
| 230 | |