| // Copyright (c) 2019, 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.dex.Marker.Tool; | |
| import com.android.tools.r8.graph.AppInfo; | |
| import com.android.tools.r8.graph.AppView; | |
| import com.android.tools.r8.graph.DexApplication; | |
| import com.android.tools.r8.graph.GraphLense; | |
| import com.android.tools.r8.ir.conversion.IRConverter; | |
| import com.android.tools.r8.ir.desugar.PrefixRewritingMapper; | |
| import com.android.tools.r8.jar.CfApplicationWriter; | |
| import com.android.tools.r8.naming.PrefixRewritingNamingLens; | |
| import com.android.tools.r8.shaking.AnnotationRemover; | |
| import com.android.tools.r8.shaking.L8TreePruner; | |
| import com.android.tools.r8.utils.AndroidApp; | |
| import com.android.tools.r8.utils.ExceptionUtils; | |
| import com.android.tools.r8.utils.InternalOptions; | |
| import com.android.tools.r8.utils.StringDiagnostic; | |
| import com.android.tools.r8.utils.ThreadUtils; | |
| import com.android.tools.r8.utils.Timing; | |
| import java.io.IOException; | |
| import java.util.concurrent.ExecutionException; | |
| import java.util.concurrent.ExecutorService; | |
| /** | |
| * The L8 compiler. | |
| */ | |
| @Keep | |
| public class L8 { | |
| /** | |
| * Main API entry for the L8 compiler. | |
| * | |
| * @param command L8 command. | |
| */ | |
| public static void run(L8Command command) throws CompilationFailedException { | |
| runForTesting( | |
| command.getInputApp(), | |
| command.getInternalOptions(), | |
| command.isShrinking(), | |
| command.getD8Command(), | |
| command.getR8Command()); | |
| } | |
| /** | |
| * Main API entry for the L8 compiler. | |
| * | |
| * @param command L8 command. | |
| * @param executor executor service from which to get threads for multi-threaded processing. | |
| */ | |
| public static void run(L8Command command, ExecutorService executor) | |
| throws CompilationFailedException { | |
| run( | |
| command.getInputApp(), | |
| command.getInternalOptions(), | |
| command.isShrinking(), | |
| command.getD8Command(), | |
| command.getR8Command(), | |
| executor); | |
| } | |
| static void runForTesting( | |
| AndroidApp app, | |
| InternalOptions options, | |
| boolean shrink, | |
| D8Command d8Command, | |
| R8Command r8Command) | |
| throws CompilationFailedException { | |
| ExecutorService executorService = ThreadUtils.getExecutorService(options); | |
| run(app, options, shrink, d8Command, r8Command, executorService); | |
| } | |
| private static void run( | |
| AndroidApp app, | |
| InternalOptions options, | |
| boolean shrink, | |
| D8Command d8Command, | |
| R8Command r8Command, | |
| ExecutorService executorService) | |
| throws CompilationFailedException { | |
| try { | |
| ExceptionUtils.withD8CompilationHandler( | |
| options.reporter, | |
| () -> { | |
| desugar(app, options, executorService); | |
| }); | |
| if (shrink) { | |
| options.reporter.warning( | |
| new StringDiagnostic("Shrinking of desugared library is work in progress.")); | |
| R8.run(r8Command, executorService); | |
| } else { | |
| D8.run(d8Command, executorService); | |
| } | |
| } finally { | |
| executorService.shutdown(); | |
| } | |
| } | |
| private static void desugar( | |
| AndroidApp inputApp, InternalOptions options, ExecutorService executor) throws IOException { | |
| Timing timing = new Timing("L8 desugaring"); | |
| try { | |
| // Disable global optimizations. | |
| options.disableGlobalOptimizations(); | |
| DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor); | |
| PrefixRewritingMapper rewritePrefix = | |
| options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options.itemFactory); | |
| app = new L8TreePruner(options).prune(app, rewritePrefix); | |
| if (app.classes().size() == 0) { | |
| // TODO(b/134732760): report error instead of fatalError. | |
| throw options.reporter.fatalError("Empty desugared library."); | |
| } | |
| AppInfo appInfo = new AppInfo(app); | |
| AppView<?> appView = AppView.createForL8(appInfo, options, rewritePrefix); | |
| IRConverter converter = new IRConverter(appView, timing); | |
| if (!options.testing.disableL8AnnotationRemoval) { | |
| AnnotationRemover.clearAnnotations(appView); | |
| } | |
| app = converter.convert(app, executor); | |
| assert appView.appInfo() == appInfo; | |
| new CfApplicationWriter( | |
| app, | |
| appView, | |
| options, | |
| options.getMarker(Tool.L8), | |
| GraphLense.getIdentityLense(), | |
| PrefixRewritingNamingLens.createPrefixRewritingNamingLens(options, rewritePrefix), | |
| null) | |
| .write(options.getClassFileConsumer(), executor); | |
| options.printWarnings(); | |
| } catch (ExecutionException e) { | |
| throw unwrapExecutionException(e); | |
| } finally { | |
| options.signalFinishedToConsumers(); | |
| // Dump timings. | |
| if (options.printTimes) { | |
| timing.report(); | |
| } | |
| } | |
| } | |
| } |