blob: dbfe6b776c97ef10f1bfeb57aba86ef6ae651122 [file] [log] [blame]
// 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 com.android.tools.r8.AssertionsConfiguration.AssertionTransformation;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.StringDiagnostic;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
public class BaseCompilerCommandParser<
C extends BaseCompilerCommand, B extends BaseCompilerCommand.Builder<C, B>> {
static final Iterable<String> ASSERTIONS_USAGE_MESSAGE =
Arrays.asList(
" --force-enable-assertions[:[<class name>|<package name>...]]",
" --force-ea[:[<class name>|<package name>...]]",
" # Forcefully enable javac generated assertion code.",
" --force-disable-assertions[:[<class name>|<package name>...]]",
" --force-da[:[<class name>|<package name>...]]",
" # Forcefully disable javac generated assertion code. This",
" # is the default handling of javac assertion code when",
" # generating DEX file format.",
" --force-passthrough-assertions[:[<class name>|<package name>...]]",
" --force-pa[:[<class name>|<package name>...]]",
" # Don't change javac generated assertion code. This",
" # is the default handling of javac assertion code when",
" # generating class file format.");
void parseMinApi(B builder, String minApiString, Origin origin) {
int minApi;
try {
minApi = Integer.parseInt(minApiString);
} catch (NumberFormatException e) {
builder.error(new StringDiagnostic("Invalid argument to --min-api: " + minApiString, origin));
return;
}
if (minApi < 1) {
builder.error(new StringDiagnostic("Invalid argument to --min-api: " + minApiString, origin));
return;
}
builder.setMinApiLevel(minApi);
}
private static String PACKAGE_ASSERTION_POSTFIX = "...";
private void addAssertionTransformation(
B builder, AssertionTransformation transformation, String scope) {
if (scope == null) {
builder.addAssertionsConfiguration(
b -> b.setTransformation(transformation).setScopeAll().build());
} else {
assert scope.length() > 0;
if (scope.endsWith(PACKAGE_ASSERTION_POSTFIX)) {
builder.addAssertionsConfiguration(
b ->
b.setTransformation(transformation)
.setScopePackage(
scope.substring(0, scope.length() - PACKAGE_ASSERTION_POSTFIX.length()))
.build());
} else {
builder.addAssertionsConfiguration(
b -> b.setTransformation(transformation).setScopeClass(scope).build());
}
}
}
boolean tryParseAssertionArgument(B builder, String arg, Origin origin) {
String FORCE_ENABLE_ASSERTIONS = "--force-enable-assertions";
String FORCE_EA = "--force-ea";
String FORCE_DISABLE_ASSERTIONS = "--force-disable-assertions";
String FORCE_DA = "--force-da";
String FORCE_PASSTHROUGH_ASSERTIONS = "--force-passthrough-assertions";
String FORCE_PA = "--force-pa";
AssertionTransformation transformation = null;
String remaining = null;
if (arg.startsWith(FORCE_ENABLE_ASSERTIONS)) {
transformation = AssertionTransformation.ENABLE;
remaining = arg.substring(FORCE_ENABLE_ASSERTIONS.length());
} else if (arg.startsWith(FORCE_EA)) {
transformation = AssertionTransformation.ENABLE;
remaining = arg.substring(FORCE_EA.length());
} else if (arg.startsWith(FORCE_DISABLE_ASSERTIONS)) {
transformation = AssertionTransformation.DISABLE;
remaining = arg.substring(FORCE_DISABLE_ASSERTIONS.length());
} else if (arg.startsWith(FORCE_DA)) {
transformation = AssertionTransformation.DISABLE;
remaining = arg.substring(FORCE_DA.length());
} else if (arg.startsWith(FORCE_PASSTHROUGH_ASSERTIONS)) {
transformation = AssertionTransformation.PASSTHROUGH;
remaining = arg.substring(FORCE_PASSTHROUGH_ASSERTIONS.length());
} else if (arg.startsWith(FORCE_PA)) {
transformation = AssertionTransformation.PASSTHROUGH;
remaining = arg.substring(FORCE_PA.length());
}
if (transformation != null) {
if (remaining.length() == 0) {
addAssertionTransformation(builder, transformation, null);
return true;
} else {
if (remaining.length() == 1 || remaining.charAt(0) != ':') {
return false;
}
String classOrPackageScope = remaining.substring(1);
if (classOrPackageScope.contains(";")
|| classOrPackageScope.contains("[")
|| classOrPackageScope.contains("/")) {
builder.error(
new StringDiagnostic("Illegal assertion scope: " + classOrPackageScope, origin));
}
addAssertionTransformation(builder, transformation, remaining.substring(1));
return true;
}
} else {
return false;
}
}
/**
* This method must match the lookup in
* {@link com.android.tools.r8.JdkClassFileProvider#fromJdkHome}.
*/
private static boolean isJdkHome(Path home) {
Path jrtFsJar = home.resolve("lib").resolve("jrt-fs.jar");
if (Files.exists(jrtFsJar)) {
return true;
}
// JDK has rt.jar in jre/lib/rt.jar.
Path rtJar = home.resolve("jre").resolve("lib").resolve("rt.jar");
if (Files.exists(rtJar)) {
return true;
}
// JRE has rt.jar in lib/rt.jar.
rtJar = home.resolve("lib").resolve("rt.jar");
if (Files.exists(rtJar)) {
return true;
}
return false;
}
static void addLibraryArgument(BaseCommand.Builder builder, Origin origin, String arg) {
Path path = Paths.get(arg);
if (isJdkHome(path)) {
try {
builder
.addLibraryResourceProvider(JdkClassFileProvider.fromJdkHome(path));
} catch (IOException e) {
builder.error(new ExceptionDiagnostic(e, origin));
}
} else {
builder.addLibraryFiles(path);
}
}
}