blob: 3b23ef5a1bf592e70e58b697c9456d164546db4c [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 com.android.tools.r8.errors.DexFileOverflowDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
/** Immutable command structure for an invocation of the {@link L8} libray compiler. */
@Keep
public final class L8Command extends BaseCompilerCommand {
private static class DefaultL8DiagnosticsHandler implements DiagnosticsHandler {
@Override
public void error(Diagnostic error) {
if (error instanceof DexFileOverflowDiagnostic) {
DexFileOverflowDiagnostic overflowDiagnostic = (DexFileOverflowDiagnostic) error;
DiagnosticsHandler.super.error(
new StringDiagnostic(
overflowDiagnostic.getDiagnosticMessage()
+ ". Library too large. L8 can only produce a single .dex file"));
return;
}
DiagnosticsHandler.super.error(error);
}
}
/**
* Builder for constructing a L8Command.
*
* <p>A builder is obtained by calling {@link L8Command#builder}.
*/
@Keep
public static class Builder extends BaseCompilerCommand.Builder<L8Command, Builder> {
private Builder() {
this(new DefaultL8DiagnosticsHandler());
}
private Builder(DiagnosticsHandler diagnosticsHandler) {
super(diagnosticsHandler);
}
/** Add dex program-data. */
@Override
public Builder addDexProgramData(byte[] data, Origin origin) {
guard(() -> getAppBuilder().addDexProgramData(data, origin));
return self();
}
@Override
Builder self() {
return this;
}
@Override
CompilationMode defaultCompilationMode() {
return CompilationMode.DEBUG;
}
@Override
void validate() {
Reporter reporter = getReporter();
if (getSpecialLibraryConfiguration() == null) {
reporter.error("L8 requires a special library configuration");
} else if (!getSpecialLibraryConfiguration().equals("default")) {
reporter.error("L8 currently requires the special library configuration to be \"default\"");
}
if (getProgramConsumer() instanceof ClassFileConsumer) {
reporter.error("L8 does not support compiling to Java class files");
}
if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
reporter.error("L8 does not support compiling to dex per class");
}
if (getAppBuilder().hasMainDexList()) {
reporter.error("L8 does not support a main dex list");
} else if (getMainDexListConsumer() != null) {
reporter.error("L8 does not support generating a main dex list");
}
super.validate();
}
@Override
L8Command makeCommand() {
if (isPrintHelp() || isPrintVersion()) {
return new L8Command(isPrintHelp(), isPrintVersion());
}
return new L8Command(
getAppBuilder().build(),
getMode(),
getProgramConsumer(),
getMainDexListConsumer(),
getMinApiLevel(),
getReporter(),
getSpecialLibraryConfiguration());
}
}
public static Builder builder() {
return new Builder();
}
public static Builder builder(DiagnosticsHandler diagnosticsHandler) {
return new Builder(diagnosticsHandler);
}
private L8Command(
AndroidApp inputApp,
CompilationMode mode,
ProgramConsumer programConsumer,
StringConsumer mainDexListConsumer,
int minApiLevel,
Reporter diagnosticsHandler,
String specialLibraryConfiguration) {
super(
inputApp,
mode,
programConsumer,
mainDexListConsumer,
minApiLevel,
diagnosticsHandler,
true,
false,
specialLibraryConfiguration,
false,
(name, checksum) -> true);
}
private L8Command(boolean printHelp, boolean printVersion) {
super(printHelp, printVersion);
}
private void configureLibraryDesugaring(InternalOptions options) {
SpecialLibraryConfiguration.configureLibraryDesugaringForLibraryCompilation(options);
}
@Override
InternalOptions getInternalOptions() {
InternalOptions internal = new InternalOptions(new DexItemFactory(), getReporter());
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
internal.programConsumer = getProgramConsumer();
assert internal.mainDexListConsumer == null;
assert !internal.minimalMainDex;
internal.minApiLevel = getMinApiLevel();
assert !internal.intermediate;
assert internal.readCompileTimeAnnotations;
// Assert and fixup defaults.
assert !internal.isShrinking();
assert !internal.isMinifying();
assert !internal.passthroughDexCode;
// Assert some of R8 optimizations are disabled.
assert !internal.enableDynamicTypeOptimization;
assert !internal.enableInlining;
assert !internal.enableClassInlining;
assert !internal.enableHorizontalClassMerging;
assert !internal.enableVerticalClassMerging;
assert !internal.enableClassStaticizer;
assert !internal.enableEnumValueOptimization;
assert !internal.outline.enabled;
assert !internal.enableValuePropagation;
assert !internal.enableLambdaMerging;
assert !internal.enableTreeShakingOfLibraryMethodOverrides;
// TODO(b/137168535) Disable non-null tracking for now.
internal.enableNonNullTracking = false;
assert internal.enableDesugaring;
assert internal.enableInheritanceClassInDexDistributor;
internal.enableInheritanceClassInDexDistributor = false;
// TODO(134732760): This is still work in progress.
assert internal.rewritePrefix.isEmpty();
assert internal.emulateLibraryInterface.isEmpty();
assert internal.retargetCoreLibMember.isEmpty();
assert internal.backportCoreLibraryMembers.isEmpty();
assert internal.dontRewriteInvocations.isEmpty();
assert getSpecialLibraryConfiguration().equals("default");
configureLibraryDesugaring(internal);
return internal;
}
}