Reland "Enable outputting of -keep,allowobfuscation in printuses"
This reverts commit e1f1d5a01e8b52cb8855c2d93d9e672dafd59e7e.
Change-Id: If5e5ff3c266aa07d7085e4f001cfd7adf7be24a7
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 654c144..3df6fdb 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -51,23 +51,25 @@
public class PrintUses {
private static final String USAGE =
- "Arguments: [--keeprules] <rt.jar> <r8.jar> <sample.jar>\n"
+ "Arguments: [--keeprules, --keeprules-allowobfuscation] <rt.jar> <r8.jar> <sample.jar>\n"
+ "\n"
+ "PrintUses prints the classes, interfaces, methods and fields used by <sample.jar>,\n"
+ "restricted to classes and interfaces in <r8.jar> that are not in <sample.jar>.\n"
+ "<rt.jar> and <r8.jar> should point to libraries used by <sample.jar>.\n"
+ "\n"
+ "The output is in the same format as what is printed when specifying -printseeds in\n"
- + "a ProGuard configuration file. Use --keeprules for outputting proguard keep rules. "
- + "See also the "
+ + "a ProGuard configuration file. Use --keeprules or --keeprules-allowobfuscation for "
+ + "outputting proguard keep rules. See also the "
+ PrintSeeds.class.getSimpleName()
+ " program in R8.";
private final Set<String> descriptors;
private final Printer printer;
+ private final boolean allowObfuscation;
private Set<DexType> types = Sets.newIdentityHashSet();
private Map<DexType, Set<DexMethod>> methods = Maps.newIdentityHashMap();
private Map<DexType, Set<DexField>> fields = Maps.newIdentityHashMap();
+ private Set<DexType> noObfuscationTypes = Sets.newIdentityHashSet();
private final DexApplication application;
private final AppInfoWithSubtyping appInfo;
private int errors;
@@ -162,6 +164,12 @@
private void addType(DexType type) {
if (isTargetType(type) && types.add(type)) {
+ DexClass clazz = appInfo.definitionFor(type);
+ if (clazz == null
+ || clazz.accessFlags.isVisibilityDependingOnPackage()
+ || !allowObfuscation) {
+ noObfuscationTypes.add(type);
+ }
methods.put(type, Sets.newIdentityHashSet());
fields.put(type, Sets.newIdentityHashSet());
}
@@ -183,6 +191,10 @@
addType(field.holder);
Set<DexField> typeFields = fields.get(field.holder);
if (typeFields != null) {
+ assert baseField != null;
+ if (!allowObfuscation || baseField.accessFlags.isVisibilityDependingOnPackage()) {
+ noObfuscationTypes.add(field.holder);
+ }
typeFields.add(field);
}
}
@@ -195,6 +207,11 @@
addType(method.proto.returnType);
Set<DexMethod> typeMethods = methods.get(method.holder);
if (typeMethods != null) {
+ DexEncodedMethod encodedMethod = appInfo.definitionFor(method);
+ assert encodedMethod != null;
+ if (!allowObfuscation || encodedMethod.accessFlags.isVisibilityDependingOnPackage()) {
+ noObfuscationTypes.add(method.holder);
+ }
typeMethods.add(method);
}
}
@@ -264,21 +281,31 @@
}
int argumentIndex = 0;
boolean printKeep = false;
- if (args[0].equals("--keeprules")) {
+ boolean allowObfuscation = false;
+ if (args[0].equals("--keeprules") || args[0].equals("--keeprules-allowobfuscation")) {
printKeep = true;
argumentIndex++;
+ allowObfuscation = args[0].equals("--keeprules-allowobfuscation");
+ // Make sure there is only one argument that mentions --keeprules
+ for (int i = 1; i < args.length; i++) {
+ if (args[i].startsWith("-keeprules")) {
+ System.out.println("Use either --keeprules or --keeprules-allowobfuscation, not both.");
+ System.out.println(USAGE.replace("\n", System.lineSeparator()));
+ return;
+ }
+ }
}
AndroidApp.Builder builder = AndroidApp.builder();
Path rtJar = Paths.get(args[argumentIndex++]);
builder.addLibraryFile(rtJar);
Path r8Jar = Paths.get(args[argumentIndex++]);
builder.addLibraryFile(r8Jar);
- Path sampleJar = Paths.get(args[argumentIndex++]);
+ Path sampleJar = Paths.get(args[argumentIndex]);
builder.addProgramFile(sampleJar);
Set<String> descriptors = new HashSet<>(getDescriptors(r8Jar));
descriptors.removeAll(getDescriptors(sampleJar));
Printer printer = printKeep ? new KeepPrinter() : new DefaultPrinter();
- PrintUses printUses = new PrintUses(descriptors, builder.build(), printer);
+ PrintUses printUses = new PrintUses(descriptors, builder.build(), printer, allowObfuscation);
printUses.analyze();
printUses.print();
if (printUses.errors > 0) {
@@ -291,10 +318,12 @@
return new ArchiveClassFileProvider(path).getClassDescriptors();
}
- private PrintUses(Set<String> descriptors, AndroidApp inputApp, Printer printer)
+ private PrintUses(
+ Set<String> descriptors, AndroidApp inputApp, Printer printer, boolean allowObfuscation)
throws Exception {
this.descriptors = descriptors;
this.printer = printer;
+ this.allowObfuscation = allowObfuscation;
InternalOptions options = new InternalOptions();
application =
new ApplicationReader(inputApp, options, new Timing("PrintUses")).read().toDirect();
@@ -314,7 +343,7 @@
}
private void print() {
- errors = printer.print(application, types, methods, fields);
+ errors = printer.print(application, types, noObfuscationTypes, methods, fields);
}
private abstract static class Printer {
@@ -359,13 +388,14 @@
}
}
- abstract void printTypeHeader(DexClass dexClass);
+ abstract void printTypeHeader(DexClass dexClass, boolean allowObfuscation);
abstract void printTypeFooter();
int print(
DexApplication application,
Set<DexType> types,
+ Set<DexType> noObfuscationTypes,
Map<DexType, Set<DexMethod>> methods,
Map<DexType, Set<DexField>> fields) {
int errors = 0;
@@ -378,7 +408,7 @@
errors++;
continue;
}
- printTypeHeader(dexClass);
+ printTypeHeader(dexClass, !noObfuscationTypes.contains(type));
List<DexEncodedMethod> methodDefinitions = new ArrayList<>(methods.size());
for (DexMethod method : methods.get(type)) {
DexEncodedMethod encodedMethod = dexClass.lookupMethod(method);
@@ -426,7 +456,7 @@
}
@Override
- void printTypeHeader(DexClass dexClass) {
+ void printTypeHeader(DexClass dexClass, boolean allowObfuscation) {
appendLine(dexClass.type.toSourceString());
}
@@ -447,13 +477,14 @@
private static class KeepPrinter extends Printer {
@Override
- public void printTypeHeader(DexClass dexClass) {
+ public void printTypeHeader(DexClass dexClass, boolean allowObfuscation) {
+ append(allowObfuscation ? "-keep,allowobfuscation" : "-keep");
if (dexClass.isInterface()) {
- append("-keep interface " + dexClass.type.toSourceString() + " {\n");
+ append(" interface " + dexClass.type.toSourceString() + " {\n");
} else if (dexClass.accessFlags.isEnum()) {
- append("-keep enum " + dexClass.type.toSourceString() + " {\n");
+ append(" enum " + dexClass.type.toSourceString() + " {\n");
} else {
- append("-keep class " + dexClass.type.toSourceString() + " {\n");
+ append(" class " + dexClass.type.toSourceString() + " {\n");
}
}