blob: d8e8e694c63ecb3bdd7333b3fe8af45bf3d338b9 [file] [log] [blame]
// Copyright (c) 2017, 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.ApplicationWriter;
import com.android.tools.r8.dex.Marker;
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.DexProgramClass;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.naming.NamingLens;
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.InternalOptions.DesugarState;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
public class DexFileMergerHelper {
private final Map<String, Integer> inputOrdering;
private DexFileMergerHelper(Map<String, Integer> inputOrdering) {
this.inputOrdering = inputOrdering;
}
private DexProgramClass keepFirstProgramClassConflictResolver(
DexProgramClass a, DexProgramClass b) {
String aPath = a.getOrigin().parent().part();
String bPath = b.getOrigin().parent().part();
Integer aIndex = inputOrdering.get(aPath);
Integer bIndex = inputOrdering.get(bPath);
if (aIndex == null || bIndex == null) {
StringBuilder builder = new StringBuilder();
builder.append("Class parent paths not found among input paths: ");
if (aIndex == null) {
builder.append(aPath);
}
if (bIndex == null) {
if (aIndex == null) {
builder.append(", ");
}
builder.append(bPath);
}
throw new RuntimeException(builder.toString());
}
return aIndex <= bIndex ? a.get() : b.get();
}
public static void run(
D8Command command, Boolean minimalMainDex, Map<String, Integer> inputOrdering)
throws CompilationFailedException {
InternalOptions options = command.getInternalOptions();
ExceptionUtils.withD8CompilationHandler(
options.reporter,
() -> runInternal(command.getInputApp(), options, minimalMainDex, inputOrdering));
}
private static void runInternal(
AndroidApp inputApp,
InternalOptions options,
Boolean minimalMainDex,
Map<String, Integer> inputOrdering)
throws IOException {
options.desugarState = DesugarState.OFF;
options.enableMainDexListCheck = false;
options.minimalMainDex = minimalMainDex;
assert !options.isMinifying();
options.inlinerOptions().enableInlining = false;
options.outline.enabled = false;
ExecutorService executor = ThreadUtils.getExecutorService(ThreadUtils.NOT_SPECIFIED);
try {
try {
Timing timing = new Timing("DexFileMerger");
ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
DexApplication app =
applicationReader.read(
null,
executor,
new DexFileMergerHelper(inputOrdering)::keepFirstProgramClassConflictResolver);
AppView<AppInfo> appView =
AppView.createForD8(
AppInfo.createInitialAppInfo(app, applicationReader.readMainDexClasses(app)));
D8.optimize(appView, options, timing, executor);
List<Marker> markers = appView.dexItemFactory().extractMarkers();
assert !options.hasMethodsFilter();
ApplicationWriter writer =
new ApplicationWriter(
appView,
markers,
GraphLens.getIdentityLens(),
InitClassLens.getThrowingInstance(),
NamingLens.getIdentityLens());
writer.write(executor);
options.printWarnings();
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
} finally {
options.signalFinishedToConsumers();
}
} finally {
executor.shutdown();
}
}
public static void runD8ForTesting(D8Command command, boolean dontCreateMarkerInD8)
throws CompilationFailedException {
InternalOptions options = command.getInternalOptions();
options.testing.dontCreateMarkerInD8 = dontCreateMarkerInD8;
D8.runForTesting(command.getInputApp(), options);
}
}