aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@google.com>2013-11-08 11:42:32 -0800
committerXavier Ducrohet <xav@google.com>2013-11-08 18:48:17 -0800
commit042fb560b33ecfd6d183c7a61d346c2972873099 (patch)
tree446d8480484b606be0d5daacda11c3d3ae25e29a
parent2fd034b23391883949f190be1ee2bd0ad4d5afcf (diff)
downloadbuild-042fb560b33ecfd6d183c7a61d346c2972873099.tar.gz
Move to Proguard 4.10
Change-Id: I9410c371627faca9cb76df2b5306c37dc41dd2fb
-rw-r--r--builder/src/main/java/com/android/builder/AndroidBuilder.java97
-rw-r--r--builder/src/main/java/com/android/builder/DexOptions.java2
-rw-r--r--gradle/build.gradle4
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy80
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/dsl/DexOptionsImpl.groovy26
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/tasks/Dex.groovy24
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/tasks/PreDex.groovy102
7 files changed, 269 insertions, 66 deletions
diff --git a/builder/src/main/java/com/android/builder/AndroidBuilder.java b/builder/src/main/java/com/android/builder/AndroidBuilder.java
index e6b78a3..9a6fa79 100644
--- a/builder/src/main/java/com/android/builder/AndroidBuilder.java
+++ b/builder/src/main/java/com/android/builder/AndroidBuilder.java
@@ -83,7 +83,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* {@link #processTestManifest(String, int, int, String, String, Boolean, Boolean, java.util.List, String)}
* {@link #processResources(java.io.File, java.io.File, java.io.File, java.util.List, String, String, String, String, String, com.android.builder.VariantConfiguration.Type, boolean, com.android.builder.model.AaptOptions)}
* {@link #compileAllAidlFiles(java.util.List, java.io.File, java.util.List, com.android.builder.compiling.DependencyFileProcessor)}
- * {@link #convertByteCode(Iterable, Iterable, File, String, DexOptions, boolean)}
+ * {@link #convertByteCode(Iterable, Iterable, File, DexOptions, boolean)}
* {@link #packageApk(String, String, java.util.List, String, String, boolean, SigningConfig, String)}
*
* Java compilation is not handled but the builder provides the bootclasspath with
@@ -926,8 +926,8 @@ public class AndroidBuilder {
/**
* Converts the bytecode to Dalvik format
- * @param classesLocation the location of the compiler output
- * @param libraries the list of libraries
+ * @param inputs the input files
+ * @param preDexedLibraries the list of pre-dexed libraries
* @param outDexFile the location of the output classes.dex file
* @param dexOptions dex options
* @param incremental true if it should attempt incremental dex if applicable
@@ -937,14 +937,13 @@ public class AndroidBuilder {
* @throws LoggedErrorException
*/
public void convertByteCode(
- @NonNull Iterable<File> classesLocation,
- @NonNull Iterable<File> libraries,
- @Nullable File proguardFile,
- @NonNull String outDexFile,
+ @NonNull Iterable<File> inputs,
+ @NonNull Iterable<File> preDexedLibraries,
+ @NonNull File outDexFile,
@NonNull DexOptions dexOptions,
boolean incremental) throws IOException, InterruptedException, LoggedErrorException {
- checkNotNull(classesLocation, "classesLocation cannot be null.");
- checkNotNull(libraries, "libraries cannot be null.");
+ checkNotNull(inputs, "inputs cannot be null.");
+ checkNotNull(preDexedLibraries, "preDexedLibraries cannot be null.");
checkNotNull(outDexFile, "outDexFile cannot be null.");
checkNotNull(dexOptions, "dexOptions cannot be null.");
@@ -972,45 +971,99 @@ public class AndroidBuilder {
command.add("--core-library");
}
+ if (dexOptions.getJumboMode()) {
+ command.add("--force-jumbo");
+ }
+
if (incremental) {
command.add("--incremental");
command.add("--no-strict");
}
command.add("--output");
- command.add(outDexFile);
+ command.add(outDexFile.getAbsolutePath());
- // clean up and add class inputs
- List<String> classesList = Lists.newArrayList();
- for (File f : classesLocation) {
+ // clean up input list
+ List<String> inputList = Lists.newArrayList();
+ for (File f : inputs) {
if (f != null && f.exists()) {
- classesList.add(f.getAbsolutePath());
+ inputList.add(f.getAbsolutePath());
}
}
- if (!classesList.isEmpty()) {
- mLogger.verbose("Dex class inputs: " + classesList);
- command.addAll(classesList);
+ if (!inputList.isEmpty()) {
+ mLogger.verbose("Dex inputs: " + inputList);
+ command.addAll(inputList);
}
// clean up and add library inputs.
List<String> libraryList = Lists.newArrayList();
- for (File f : libraries) {
+ for (File f : preDexedLibraries) {
if (f != null && f.exists()) {
libraryList.add(f.getAbsolutePath());
}
}
if (!libraryList.isEmpty()) {
- mLogger.verbose("Dex library inputs: " + libraryList);
+ mLogger.verbose("Dex pre-dexed inputs: " + libraryList);
command.addAll(libraryList);
}
- if (proguardFile != null && proguardFile.exists()) {
- mLogger.verbose("ProGuarded inputs " + proguardFile);
- command.add(proguardFile.getAbsolutePath());
+ mCmdLineRunner.runCmdLine(command, null);
+ }
+
+ /**
+ * Converts the bytecode to Dalvik format
+ * @param inputFile the input file
+ * @param outFile the location of the output classes.dex file
+ * @param dexOptions dex options
+ *
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws LoggedErrorException
+ */
+ public void preDexLibrary(
+ @NonNull File inputFile,
+ @NonNull File outFile,
+ @NonNull DexOptions dexOptions)
+ throws IOException, InterruptedException, LoggedErrorException {
+ checkNotNull(inputFile, "inputFile cannot be null.");
+ checkNotNull(outFile, "outFile cannot be null.");
+ checkNotNull(dexOptions, "dexOptions cannot be null.");
+
+ // launch dx: create the command line
+ ArrayList<String> command = Lists.newArrayList();
+
+ String dx = mBuildTools.getPath(BuildToolInfo.PathId.DX);
+ if (dx == null || !new File(dx).isFile()) {
+ throw new IllegalStateException("dx is missing");
+ }
+
+ command.add(dx);
+
+ if (dexOptions.getJavaMaxHeapSize() != null) {
+ command.add("-JXmx" + dexOptions.getJavaMaxHeapSize());
+ }
+
+ command.add("--dex");
+
+ if (mVerboseExec) {
+ command.add("--verbose");
+ }
+
+ if (dexOptions.isCoreLibrary()) {
+ command.add("--core-library");
}
+ if (dexOptions.getJumboMode()) {
+ command.add("--force-jumbo");
+ }
+
+ command.add("--output");
+ command.add(outFile.getAbsolutePath());
+
+ command.add(inputFile.getAbsolutePath());
+
mCmdLineRunner.runCmdLine(command, null);
}
diff --git a/builder/src/main/java/com/android/builder/DexOptions.java b/builder/src/main/java/com/android/builder/DexOptions.java
index 966d081..1db13be 100644
--- a/builder/src/main/java/com/android/builder/DexOptions.java
+++ b/builder/src/main/java/com/android/builder/DexOptions.java
@@ -20,5 +20,7 @@ public interface DexOptions {
boolean isCoreLibrary();
boolean getIncremental();
+ boolean getPreDexLibraries();
+ boolean getJumboMode();
String getJavaMaxHeapSize();
}
diff --git a/gradle/build.gradle b/gradle/build.gradle
index c1c22bc..f83bc7a 100644
--- a/gradle/build.gradle
+++ b/gradle/build.gradle
@@ -34,7 +34,7 @@ dependencies {
compile "com.android.tools:common:$project.ext.baseAndroidVersion"
compile "com.android.tools.lint:lint:$project.ext.baseAndroidVersion"
- compile 'net.sf.proguard:proguard-gradle:4.9'
+ compile 'net.sf.proguard:proguard-gradle:4.10'
testCompile 'junit:junit:3.8.1'
@@ -57,7 +57,7 @@ configurations{
}
dependencies{
- provided 'net.sf.proguard:proguard-gradle:4.9'
+ provided 'net.sf.proguard:proguard-gradle:4.10'
}
//Include provided for compilation
diff --git a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
index 6f8e9c6..36482e5 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
@@ -57,6 +57,7 @@ import com.android.build.gradle.tasks.Lint
import com.android.build.gradle.tasks.MergeAssets
import com.android.build.gradle.tasks.MergeResources
import com.android.build.gradle.tasks.PackageApplication
+import com.android.build.gradle.tasks.PreDex
import com.android.build.gradle.tasks.ProcessAndroidResources
import com.android.build.gradle.tasks.ProcessAppManifest
import com.android.build.gradle.tasks.ProcessTestManifest
@@ -1096,40 +1097,72 @@ public abstract class BasePlugin {
VariantConfiguration variantConfig = variantData.variantConfiguration
- Closure libraryClosure = { project.files(variantConfig.packagedJars) }
- Closure sourceClosure = { variantData.javaCompileTask.outputs.files }
- Closure proguardFileClosure = { }
+ boolean runProguard = !(variantData instanceof TestVariantData) && variantConfig.buildType.runProguard
- if (!(variantData instanceof TestVariantData) && variantConfig.buildType.runProguard) {
- libraryClosure = { Collections.emptyList() }
- sourceClosure = { Collections.emptyList() }
-
- File outFile = createProguardTasks(variantData, variantConfig)
- proguardFileClosure = { outFile }
- }
-
- // Add a dex task
- def dexTaskName = "dex${variantData.name}"
- def dexTask = project.tasks.create(dexTaskName, Dex)
+ // common dex task configuration
+ String dexTaskName = "dex${variantData.name}"
+ Dex dexTask = project.tasks.create(dexTaskName, Dex)
variantData.dexTask = dexTask
- if (variantData.proguardTask != null) {
- dexTask.dependsOn variantData.proguardTask
- } else {
- dexTask.dependsOn variantData.javaCompileTask
- }
dexTask.plugin = this
dexTask.variant = variantData
- dexTask.conventionMapping.libraries = libraryClosure
- dexTask.conventionMapping.sourceFiles = sourceClosure
- dexTask.conventionMapping.proguardedJar = proguardFileClosure
dexTask.conventionMapping.outputFile = {
project.file(
"${project.buildDir}/libs/${project.archivesBaseName}-${variantData.baseName}.dex")
}
dexTask.dexOptions = extension.dexOptions
+ if (runProguard) {
+
+ // first proguard task.
+ File outFile = createProguardTasks(variantData, variantConfig)
+
+ // then dexing task
+ dexTask.dependsOn variantData.proguardTask
+ dexTask.conventionMapping.inputFiles = { project.files(outFile) }
+ dexTask.conventionMapping.preDexedLibraries = { Collections.emptyList() }
+
+ } else {
+
+ // if required, pre-dexing task.
+ PreDex preDexTask = null;
+ boolean runPreDex = extension.dexOptions.preDexLibraries
+ if (runPreDex) {
+ def preDexTaskName = "preDex${variantData.name}"
+ preDexTask = project.tasks.create(preDexTaskName, PreDex)
+
+ preDexTask.dependsOn variantData.javaCompileTask
+ preDexTask.plugin = this
+ preDexTask.dexOptions = extension.dexOptions
+
+ preDexTask.conventionMapping.inputFiles = {
+ project.files(variantConfig.packagedJars)
+ }
+ preDexTask.conventionMapping.outputFolder = {
+ project.file(
+ "${project.buildDir}/pre-dexed/${variantData.dirName}")
+ }
+ }
+
+ // then dexing task
+ dexTask.dependsOn variantData.javaCompileTask
+ if (runPreDex) {
+ dexTask.dependsOn preDexTask
+ }
+
+ dexTask.conventionMapping.inputFiles = { variantData.javaCompileTask.outputs.files }
+ if (runPreDex) {
+ dexTask.conventionMapping.preDexedLibraries = {
+ project.fileTree(preDexTask.outputFolder).files
+ }
+ } else {
+ dexTask.conventionMapping.preDexedLibraries = {
+ project.files(variantConfig.packagedJars)
+ }
+ }
+ }
+
// Add a task to generate application package
def packageApp = project.tasks.create("package${variantData.name}", PackageApplication)
variantData.packageApplicationTask = packageApp
@@ -1144,13 +1177,10 @@ public abstract class BasePlugin {
variantData.processResourcesTask.packageOutputFile
}
packageApp.conventionMapping.dexFile = { dexTask.outputFile }
-
packageApp.conventionMapping.packagedJars = { config.packagedJars }
-
packageApp.conventionMapping.javaResourceDir = {
getOptionalDir(variantData.processJavaResources.destinationDir)
}
-
packageApp.conventionMapping.jniDebugBuild = { config.buildType.jniDebugBuild }
SigningConfigDsl sc = (SigningConfigDsl) config.signingConfig
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/DexOptionsImpl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/DexOptionsImpl.groovy
index 899337a..767b9d3 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/DexOptionsImpl.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/DexOptionsImpl.groovy
@@ -26,7 +26,13 @@ public class DexOptionsImpl implements DexOptions {
private boolean coreLibraryFlag
@Input
- private boolean isIncrementalFlag = true
+ private boolean isIncrementalFlag = false
+
+ @Input
+ private boolean isPreDexLibrariesFlag = true
+
+ @Input
+ private boolean isJumboModeFlag = false
@Input
@Optional
@@ -50,6 +56,24 @@ public class DexOptionsImpl implements DexOptions {
return isIncrementalFlag
}
+ @Override
+ boolean getPreDexLibraries() {
+ return isPreDexLibrariesFlag
+ }
+
+ void setPreDexLibraries(boolean flag) {
+ isPreDexLibrariesFlag = flag
+ }
+
+ public void setJumboMode(boolean flag) {
+ isJumboModeFlag = flag
+ }
+
+ @Override
+ boolean getJumboMode() {
+ return isJumboModeFlag
+ }
+
public void setJavaMaxHeapSize(String theJavaMaxHeapSize) {
if (theJavaMaxHeapSize.matches("\\d+[kKmMgGtT]?")) {
javaMaxHeapSize = theJavaMaxHeapSize
diff --git a/gradle/src/main/groovy/com/android/build/gradle/tasks/Dex.groovy b/gradle/src/main/groovy/com/android/build/gradle/tasks/Dex.groovy
index 3db6c45..c74cdb3 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/tasks/Dex.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/tasks/Dex.groovy
@@ -14,14 +14,11 @@
* limitations under the License.
*/
package com.android.build.gradle.tasks
-
import com.android.build.gradle.internal.dsl.DexOptionsImpl
import com.android.build.gradle.internal.tasks.IncrementalTask
import com.android.ide.common.res2.FileStatus
-import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Nested
-import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
public class Dex extends IncrementalTask {
@@ -34,13 +31,10 @@ public class Dex extends IncrementalTask {
// ----- PRIVATE TASK API -----
@InputFiles
- Iterable<File> sourceFiles
+ Iterable<File> inputFiles
@InputFiles
- Iterable<File> libraries
-
- @InputFile @Optional
- File proguardedJar
+ Iterable<File> preDexedLibraries
@Nested
DexOptionsImpl dexOptions
@@ -48,10 +42,9 @@ public class Dex extends IncrementalTask {
@Override
protected void doFullTaskAction() {
getBuilder().convertByteCode(
- getSourceFiles(),
- getLibraries(),
- getProguardedJar(),
- getOutputFile().absolutePath,
+ getInputFiles(),
+ getPreDexedLibraries(),
+ getOutputFile(),
getDexOptions(),
false)
}
@@ -59,10 +52,9 @@ public class Dex extends IncrementalTask {
@Override
protected void doIncrementalTaskAction(Map<File, FileStatus> changedInputs) {
getBuilder().convertByteCode(
- getSourceFiles(),
- getLibraries(),
- getProguardedJar(),
- getOutputFile().absolutePath,
+ getInputFiles(),
+ getPreDexedLibraries(),
+ getOutputFile(),
getDexOptions(),
true)
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/tasks/PreDex.groovy b/gradle/src/main/groovy/com/android/build/gradle/tasks/PreDex.groovy
new file mode 100644
index 0000000..b0aa26d
--- /dev/null
+++ b/gradle/src/main/groovy/com/android/build/gradle/tasks/PreDex.groovy
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.build.gradle.tasks
+import com.android.SdkConstants
+import com.android.annotations.NonNull
+import com.android.build.gradle.internal.dsl.DexOptionsImpl
+import com.android.build.gradle.internal.tasks.BaseTask
+import com.android.builder.AndroidBuilder
+import com.android.builder.DexOptions
+import com.google.common.hash.HashCode
+import com.google.common.hash.HashFunction
+import com.google.common.hash.Hashing
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Nested
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.incremental.IncrementalTaskInputs
+
+public class PreDex extends BaseTask {
+
+ // ----- PUBLIC TASK API -----
+
+ // ----- PRIVATE TASK API -----
+
+ // this is used automatically by Gradle, even though nothing
+ // in the class uses it.
+ @SuppressWarnings("GroovyUnusedDeclaration")
+ @InputFiles
+ Iterable<File> inputFiles
+
+ @OutputDirectory
+ File outputFolder
+
+ @Nested
+ DexOptionsImpl dexOptions
+
+ @TaskAction
+ void taskAction(IncrementalTaskInputs taskInputs) {
+ final File outFolder = getOutputFolder()
+ final DexOptions options = getDexOptions()
+
+ // if we are not in incremental mode, then outOfDate will contain
+ // all th files, but first we need to delete the previous output
+ if (!taskInputs.isIncremental()) {
+ emptyFolder(outFolder)
+ }
+
+ AndroidBuilder builder = getBuilder()
+
+ taskInputs.outOfDate { change ->
+ //noinspection GroovyAssignabilityCheck
+ File preDexedFile = getDexFileName(outFolder, change.file)
+ //noinspection GroovyAssignabilityCheck
+ builder.preDexLibrary(change.file, preDexedFile, options)
+ }
+
+ taskInputs.removed { change ->
+ //noinspection GroovyAssignabilityCheck
+ File preDexedFile = getDexFileName(outFolder, change.file)
+ preDexedFile.delete()
+ }
+ }
+
+ /**
+ * Returns a unique File for the pre-dexed library, even
+ * if there are 2 libraries with the same file names (but different
+ * paths)
+ *
+ * @param outFolder
+ * @param inputFile the library
+ * @return
+ */
+ @NonNull
+ private static File getDexFileName(@NonNull File outFolder, @NonNull File inputFile) {
+ // get the filename
+ String name = inputFile.getName();
+ // remove the extension
+ int pos = name.lastIndexOf('.');
+ if (pos != -1) {
+ name = name.substring(0, pos);
+ }
+
+ // add a hash of the original file path
+ HashFunction hashFunction = Hashing.md5();
+ HashCode hashCode = hashFunction.hashString(inputFile.getAbsolutePath());
+
+ return new File(outFolder, name + "-" + hashCode.toString() + SdkConstants.DOT_JAR);
+ }
+}