blob: 34798e4dfb609978fd29d8675d72ac8654050a12 [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.compatproguard;
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Output;
import com.android.tools.r8.Version;
import com.android.tools.r8.errors.CompilationError;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
/**
* Proguard + dx compatibility interface for r8.
*
* This should become a mostly drop-in replacement for uses of Proguard followed by dx for
* use with the Android Platform build.
*
* It accepts all Proguard flags supported by r8, except -outjars.
*
* It accepts a few dx flags which are known to be used in the Android Platform build.
*
* The flag -outjars does not make sense as r8 (like Proguard + dx) produces Dex output.
* For output use --output as for R8 proper.
*/
public class CompatProguard {
public static class CompatProguardOptions {
public final String output;
public final int minApi;
public final boolean forceProguardCompatibility;
public final boolean multiDex;
public final List<String> proguardConfig;
CompatProguardOptions(List<String> proguardConfig, String output, int minApi,
boolean multiDex, boolean forceProguardCompatibility) {
this.output = output;
this.minApi = minApi;
this.forceProguardCompatibility = forceProguardCompatibility;
this.multiDex = multiDex;
this.proguardConfig = proguardConfig;
}
public static CompatProguardOptions parse(String[] args) throws CompilationException {
String output = null;
int minApi = 1;
boolean forceProguardCompatibility = false;
boolean multiDex = false;
ImmutableList.Builder<String> builder = ImmutableList.builder();
if (args.length > 0) {
StringBuilder currentLine = new StringBuilder(args[0]);
for (int i = 1; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == '-') {
if (arg.equals("--min-api")) {
minApi = Integer.valueOf(args[++i]);
} else if (arg.equals("--force-proguard-compatibility")) {
forceProguardCompatibility = true;
} else if (arg.equals("--output")) {
output = args[++i];
} else if (arg.equals("--multi-dex")) {
multiDex = true;
} else if (arg.equals("-outjars")) {
throw new CompilationException(
"Proguard argument -outjar is not supported. Use R8 compatible --output flag");
} else {
builder.add(currentLine.toString());
currentLine = new StringBuilder(arg);
}
} else {
currentLine.append(' ').append(arg);
}
}
builder.add(currentLine.toString());
}
return new CompatProguardOptions(builder.build(), output, minApi, multiDex,
forceProguardCompatibility);
}
}
private static void run(String[] args) throws IOException, CompilationException {
if (args.length == 0) {
Version.printToolVersion("CompatProguard");
return;
}
System.out.println("CompatProguard " + String.join(" ", args));
// Run R8 passing all the options from the command line as a Proguard configuration.
CompatProguardOptions options = CompatProguardOptions.parse(args);
R8Command.Builder builder =
new CompatProguardCommandBuilder(options.forceProguardCompatibility);
builder.setOutputPath(Paths.get(options.output))
.addProguardConfiguration(options.proguardConfig)
.setMinApiLevel(options.minApi);
R8Output result = R8.run(builder.build());
if (!options.multiDex) {
if (result.getDexResources().size() > 1) {
throw new CompilationError(
"Compilation result could not fit into a single dex file. "
+ "Reduce the input-program size or run with --multi-dex enabled");
}
}
}
public static void main(String[] args) throws IOException {
try {
run(args);
} catch (CompilationException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}