Last active
August 29, 2015 14:07
-
-
Save tophyr/6ca3a5eaa68655357565 to your computer and use it in GitHub Desktop.
ButterKnifeProcessor + Optimizing Proguard workaround
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// from <aosp_root>/tools/base/build-system/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy | |
// here just for context, unmodified | |
/** | |
* Creates the proguarding task for the given Variant. | |
* @param variantData the variant data. | |
* @param testedVariantData optional. variant data representing the tested variant, null if the | |
* variant is not a test variant | |
* @return outFile file outputted by proguard | |
*/ | |
@NonNull | |
public File createProguardTasks(@NonNull BaseVariantData variantData, | |
@Nullable BaseVariantData testedVariantData) { | |
VariantConfiguration variantConfig = variantData.variantConfiguration | |
def proguardTask = project.tasks.create( | |
"proguard${variantData.variantConfiguration.fullName.capitalize()}", | |
ProGuardTask) | |
proguardTask.dependsOn variantData.javaCompileTask, variantData.variantDependency.packageConfiguration.buildDependencies | |
if (testedVariantData != null) { | |
proguardTask.dependsOn testedVariantData.obfuscationTask | |
} | |
variantData.obfuscationTask = proguardTask | |
// --- Output File --- | |
File outFile; | |
if (variantData instanceof LibraryVariantData) { | |
outFile = project.file( | |
"${project.buildDir}/${FD_INTERMEDIATES}/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/classes.jar") | |
} else { | |
outFile = project.file( | |
"${project.buildDir}/${FD_INTERMEDIATES}/classes-proguard/${variantData.variantConfiguration.dirName}/classes.jar") | |
} | |
// --- Proguard Config --- | |
if (testedVariantData != null) { | |
// don't remove any code in tested app | |
proguardTask.dontshrink() | |
proguardTask.keepnames("class * extends junit.framework.TestCase") | |
proguardTask.keepclassmembers("class * extends junit.framework.TestCase {\n" + | |
" void test*(...);\n" + | |
"}") | |
// input the mapping from the tested app so that we can deal with obfuscated code | |
proguardTask.applymapping("${project.buildDir}/${FD_OUTPUTS}/proguard/${testedVariantData.variantConfiguration.dirName}/mapping.txt") | |
// for tested app, we only care about their aapt config since the base | |
// configs are the same files anyway. | |
proguardTask.configuration(testedVariantData.processResourcesTask.proguardOutputFile) | |
} | |
// all the config files coming from build type, product flavors. | |
List<Object> proguardFiles = variantConfig.getProguardFiles(true /*includeLibs*/) | |
for (Object proguardFile : proguardFiles) { | |
proguardTask.configuration(proguardFile) | |
} | |
// also the config file output by aapt | |
proguardTask.configuration(variantData.processResourcesTask.proguardOutputFile) | |
// --- InJars / LibraryJars --- | |
if (variantData instanceof LibraryVariantData) { | |
String packageName = variantConfig.getPackageFromManifest() | |
if (packageName == null) { | |
throw new BuildException("Failed to read manifest", null) | |
} | |
packageName = packageName.replace('.', '/'); | |
// injar: the compilation output | |
// exclude R files and such from output | |
String exclude = '!' + packageName + "/R.class" | |
exclude += (', !' + packageName + "/R\$*.class") | |
if (!((LibraryExtension)extension).packageBuildConfig) { | |
exclude += (', !' + packageName + "/Manifest.class") | |
exclude += (', !' + packageName + "/Manifest\$*.class") | |
exclude += (', !' + packageName + "/BuildConfig.class") | |
} | |
proguardTask.injars(variantData.javaCompileTask.destinationDir, filter: exclude) | |
// include R files and such for compilation | |
String include = exclude.replace('!', '') | |
proguardTask.libraryjars(variantData.javaCompileTask.destinationDir, filter: include) | |
// injar: the local dependencies | |
Closure inJars = { | |
Arrays.asList(getLocalJarFileList(variantData.variantDependency)) | |
} | |
proguardTask.injars(inJars, filter: '!META-INF/MANIFEST.MF') | |
// libjar: the library dependencies. In this case we take all the compile-scope | |
// dependencies | |
Closure libJars = { | |
Set<File> compiledJars = androidBuilder.getCompileClasspath(variantConfig) | |
Object[] localJars = getLocalJarFileList(variantData.variantDependency) | |
compiledJars.findAll({ !localJars.contains(it) }) | |
} | |
proguardTask.libraryjars(libJars, filter: '!META-INF/MANIFEST.MF') | |
// ensure local jars keep their package names | |
proguardTask.keeppackagenames() | |
} else { | |
// injar: the compilation output | |
proguardTask.injars(variantData.javaCompileTask.destinationDir) | |
// injar: the packaged dependencies | |
Closure inJars = { | |
androidBuilder.getPackagedJars(variantConfig) | |
} | |
proguardTask.injars(inJars, filter: '!META-INF/MANIFEST.MF') | |
// the provided-only jars as libraries. | |
Closure libJars = { | |
variantData.variantConfiguration.providedOnlyJars | |
} | |
proguardTask.libraryjars(libJars) | |
} | |
// libraryJars: the runtime jars. Do this in doFirst since the boot classpath isn't | |
// available until the SDK is loaded in the prebuild task | |
proguardTask.doFirst { | |
for (String runtimeJar : androidBuilder.getBootClasspath()) { | |
proguardTask.libraryjars(runtimeJar) | |
} | |
} | |
if (testedVariantData != null) { | |
// input the tested app as library | |
proguardTask.libraryjars(testedVariantData.javaCompileTask.destinationDir) | |
// including its dependencies | |
Closure testedPackagedJars = { | |
androidBuilder.getPackagedJars(testedVariantData.variantConfiguration) | |
} | |
proguardTask.libraryjars(testedPackagedJars, filter: '!META-INF/MANIFEST.MF') | |
} | |
// --- Out files --- | |
proguardTask.outjars(outFile) | |
final File proguardOut = project.file( | |
"${project.buildDir}/${FD_OUTPUTS}/proguard/${variantData.variantConfiguration.dirName}") | |
proguardTask.dump(new File(proguardOut, "dump.txt")) | |
proguardTask.printseeds(new File(proguardOut, "seeds.txt")) | |
proguardTask.printusage(new File(proguardOut, "usage.txt")) | |
proguardTask.printmapping(new File(proguardOut, "mapping.txt")) | |
// proguard doesn't verify that the seed/mapping/usage folders exist and will fail | |
// if they don't so create them. | |
proguardTask.doFirst { | |
proguardOut.mkdirs() | |
} | |
return outFile | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
afterEvaluate { | |
android.applicationVariants.all { variant -> | |
def proguardTask = project.tasks.findByName("proguard${variant.name.capitalize()}") | |
if (proguardTask != null) { | |
def inJarField = proguardTask.class.superclass.getDeclaredField('inJarFilters') | |
inJarField.setAccessible(true) | |
filters = inJarField.get(proguardTask) | |
filters.get(1).put('filter', filters.get(1).get('filter') + ',!**ButterKnifeProcessor**') | |
print filters | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// from http://grepcode.com/file/repo1.maven.org/maven2/net.sf.proguard/proguard-gradle/4.10/proguard/gradle/ProGuardTask.java | |
// here just for context, unmodified | |
/** | |
* This Task allows to configure and run ProGuard from Gradle. | |
* | |
* @author Eric Lafortune | |
*/ | |
public class ProGuardTask extends DefaultTask | |
{ | |
// Accumulated input and output, for the sake of Gradle's lazy file | |
// resolution and lazy task execution. | |
private final List inJarFiles = new ArrayList(); | |
private final List inJarFilters = new ArrayList(); | |
private final List outJarFiles = new ArrayList(); | |
private final List outJarFilters = new ArrayList(); | |
private final List inJarCounts = new ArrayList(); | |
private final List libraryJarFiles = new ArrayList(); | |
private final List libraryJarFilters = new ArrayList(); | |
private final List configurationFiles = new ArrayList(); | |
// Accumulated configuration. | |
private final Configuration configuration = new Configuration(); | |
// Field acting as a parameter for the class member specification methods. | |
private ClassSpecification classSpecification; | |
// Gradle task inputs and outputs, because annotations on the List fields | |
// (private or not) don't seem to work. Private methods don't work either, | |
// but package visible or protected methods are ok. | |
@InputFiles | |
protected FileCollection getInJarFiles() throws ParseException | |
{ | |
return getProject().files(inJarFiles); | |
} | |
@Optional @OutputFiles | |
protected FileCollection getOutJarFiles() throws ParseException | |
{ | |
return getProject().files(outJarFiles); | |
} | |
@InputFiles | |
protected FileCollection getLibraryJarFiles() throws ParseException | |
{ | |
return getProject().files(libraryJarFiles); | |
} | |
@InputFiles | |
protected FileCollection getConfigurationFiles() throws ParseException | |
{ | |
return getProject().files(configurationFiles); | |
} | |
// Gradle task settings corresponding to all ProGuard options. | |
public void configuration(Object configurationFiles) | |
throws ParseException, IOException | |
{ | |
// Just collect the arguments, so they can be resolved lazily. | |
this.configurationFiles.add(configurationFiles); | |
} | |
public void injars(Object inJarFiles) | |
throws ParseException | |
{ | |
injars(null, inJarFiles); | |
} | |
public void injars(Map filterArgs, Object inJarFiles) | |
throws ParseException | |
{ | |
// Just collect the arguments, so they can be resolved lazily. | |
this.inJarFiles.add(inJarFiles); | |
this.inJarFilters.add(filterArgs); | |
} | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment