| // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8; |
| |
| import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException; |
| |
| import com.android.tools.r8.dex.ApplicationReader; |
| import com.android.tools.r8.graph.AppInfoWithClassHierarchy; |
| import com.android.tools.r8.graph.AppServices; |
| import com.android.tools.r8.graph.AppView; |
| import com.android.tools.r8.graph.DirectMappedDexApplication; |
| import com.android.tools.r8.graph.SubtypingInfo; |
| import com.android.tools.r8.shaking.AppInfoWithLiveness; |
| import com.android.tools.r8.shaking.Enqueuer; |
| import com.android.tools.r8.shaking.EnqueuerFactory; |
| import com.android.tools.r8.shaking.RootSetBuilder; |
| import com.android.tools.r8.shaking.RootSetBuilder.RootSet; |
| import com.android.tools.r8.utils.ExceptionUtils; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.android.tools.r8.utils.ThreadUtils; |
| import com.android.tools.r8.utils.Timing; |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.ExecutorService; |
| |
| /** |
| * PrintSeeds prints the classes, interfaces, methods and fields selected by a given ProGuard |
| * configuration <pg-conf.txt> when compiling a given program <r8.jar> alongside a given |
| * library <rt.jar>. |
| * |
| * <p>The output format is identical to what is printed when {@code -printseeds} is specified in |
| * <pg-conf.txt>, but running PrintSeeds can be faster than running R8 with {@code |
| * -printseeds}. See also the {@link PrintUses} program in R8. |
| */ |
| public class PrintSeeds { |
| |
| private static final String USAGE = |
| "Arguments: <rt.jar> <r8.jar> <pg-conf.txt>\n" |
| + "\n" |
| + "PrintSeeds prints the classes, interfaces, methods and fields selected by\n" |
| + "<pg-conf.txt> when compiling <r8.jar> alongside <rt.jar>.\n" |
| + "\n" |
| + "The output format is identical to what is printed when -printseeds is specified in\n" |
| + "<pg-conf.txt>, but running PrintSeeds can be faster than running R8 with \n" |
| + "-printseeds. See also the " |
| + PrintUses.class.getSimpleName() |
| + " program in R8."; |
| |
| public static void main(String[] args) throws Exception { |
| if (args.length != 3) { |
| System.out.println(USAGE.replace("\n", System.lineSeparator())); |
| System.exit(1); |
| } |
| Path rtJar = Paths.get(args[0]); |
| Path r8Jar = Paths.get(args[1]); |
| Path pgConf = Paths.get(args[2]); |
| R8Command command = |
| R8Command.builder() |
| .addLibraryFiles(rtJar) |
| .addProgramFiles(r8Jar) |
| .addProguardConfigurationFiles(pgConf) |
| .setProgramConsumer(ClassFileConsumer.emptyConsumer()) |
| .build(); |
| Set<String> descriptors = new ArchiveClassFileProvider(r8Jar).getClassDescriptors(); |
| InternalOptions options = command.getInternalOptions(); |
| ExecutorService executorService = ThreadUtils.getExecutorService(options); |
| ExceptionUtils.withR8CompilationHandler( |
| command.getReporter(), |
| () -> { |
| try { |
| run(command, descriptors, options, executorService); |
| } finally { |
| executorService.shutdown(); |
| } |
| }); |
| } |
| |
| private static void run( |
| R8Command command, Set<String> descriptors, InternalOptions options, ExecutorService executor) |
| throws IOException { |
| assert !options.forceProguardCompatibility; |
| Timing timing = new Timing("PrintSeeds"); |
| try { |
| DirectMappedDexApplication application = |
| new ApplicationReader(command.getInputApp(), options, timing).read(executor).toDirect(); |
| AppView<? extends AppInfoWithClassHierarchy> appView = |
| AppView.createForR8(new AppInfoWithClassHierarchy(application), options); |
| appView.setAppServices(AppServices.builder(appView).build()); |
| SubtypingInfo subtypingInfo = new SubtypingInfo(application.allClasses(), application); |
| RootSet rootSet = |
| new RootSetBuilder(appView, subtypingInfo, options.getProguardConfiguration().getRules()) |
| .run(executor); |
| Enqueuer enqueuer = EnqueuerFactory.createForInitialTreeShaking(appView, subtypingInfo); |
| AppInfoWithLiveness appInfo = |
| enqueuer.traceApplication( |
| rootSet, options.getProguardConfiguration().getDontWarnPatterns(), executor, timing); |
| RootSetBuilder.writeSeeds( |
| appInfo, System.out, type -> descriptors.contains(type.toDescriptorString())); |
| } catch (ExecutionException e) { |
| throw unwrapExecutionException(e); |
| } |
| } |
| } |