blob: 50a4a7072d4bea7987845a127b72766d181d73ff [file] [log] [blame]
// 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.L8Command.USAGE_MESSAGE;
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.AppInfoWithClassHierarchy;
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.origin.CommandLineOrigin;
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.SelfRetraceTest;
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) {
R8.run(r8Command);
} else {
D8.run(d8Command, executorService);
}
} finally {
executorService.shutdown();
}
}
private static void desugar(
AndroidApp inputApp, InternalOptions options, ExecutorService executor) throws IOException {
Timing timing = Timing.create("L8 desugaring", options);
try {
// Disable global optimizations.
options.disableGlobalOptimizations();
// Since L8 Cf representation is temporary, just disable long running back-end optimizations
// on it.
options.enableLoadStoreOptimization = false;
DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
PrefixRewritingMapper rewritePrefix =
options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options);
app = new L8TreePruner(options).prune(app, rewritePrefix);
AppInfo appInfo = new AppInfoWithClassHierarchy(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(appView),
null)
.write(options.getClassFileConsumer(), executor);
options.printWarnings();
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
} finally {
options.signalFinishedToConsumers();
// Dump timings.
if (options.printTimes) {
timing.report();
}
}
}
private static void run(String[] args) throws CompilationFailedException {
L8Command command = L8Command.parse(args, CommandLineOrigin.INSTANCE).build();
if (command.isPrintHelp()) {
SelfRetraceTest.test();
System.out.println(USAGE_MESSAGE);
return;
}
if (command.isPrintVersion()) {
System.out.println("L8 " + Version.getVersionString());
return;
}
run(command);
}
/**
* Command-line entry to L8.
*
* <p>See {@link L8Command#USAGE_MESSAGE} or run {@code l8 --help} for usage information.
*/
public static void main(String[] args) {
if (args.length == 0) {
System.err.println(USAGE_MESSAGE);
System.exit(ExceptionUtils.STATUS_ERROR);
}
ExceptionUtils.withMainProgramHandler(() -> run(args));
}
}