Make sure the build detects changes in config classes.
Xavier Ducrohet [Fri, 31 Aug 2012 01:04:46 +0000 (18:04 -0700)]
aapt and dex option classes use the @Input and the
tasks using them put @Nested on them.

The ProductFlavor and the Build Type classes are now
Serializable and they are passed as @Input args to
all classes that need them.

Any change in those objects will properly trigger
a recompilation.

Change-Id: I42fb3f6c5870505b984ff777befee255f03ebd1d

12 files changed:
builder/src/main/java/com/android/builder/BuildType.java
builder/src/main/java/com/android/builder/ProductFlavor.java
builder/src/main/java/com/android/builder/VariantConfiguration.java
gradle/src/main/groovy/com/android/build/gradle/AndroidBasePlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/AndroidPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/BaseAndroidTask.groovy
gradle/src/main/groovy/com/android/build/gradle/Dex.groovy
gradle/src/main/groovy/com/android/build/gradle/GenerateBuildConfigTask.groovy
gradle/src/main/groovy/com/android/build/gradle/ProcessResources.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/AaptOptionsImpl.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/ApplicationVariant.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/DexOptionsImpl.groovy

index 51e5679..561d713 100644 (file)
@@ -19,7 +19,12 @@ package com.android.builder;
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
 
-public class BuildType {
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BuildType implements Serializable {
+    private static final long serialVersionUID = 1L;
 
     public final static String DEBUG = "debug";
     public final static String RELEASE = "release";
@@ -30,6 +35,8 @@ public class BuildType {
     private boolean mDebugSigned;
     private String mPackageNameSuffix = null;
     private boolean mRunProguard = false;
+    private boolean mBuildConfigDebug;
+    private final List<String> mBuildConfigLines = new ArrayList<String>();
 
     private boolean mZipAlign = true;
 
@@ -47,12 +54,14 @@ public class BuildType {
         mDebugJniBuild = true;
         mDebugSigned = true;
         mZipAlign = false;
+        mBuildConfigDebug = true;
     }
 
     private void initRelease() {
         mDebuggable = false;
         mDebugJniBuild = false;
         mDebugSigned = false;
+        mBuildConfigDebug = false;
     }
 
     public String getName() {
@@ -107,6 +116,54 @@ public class BuildType {
         return mZipAlign;
     }
 
+    public void setBuildConfigLines(List<String> lines) {
+        mBuildConfigLines.addAll(lines);
+    }
+
+    public List<String> getBuildConfigLines() {
+        return mBuildConfigLines;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BuildType buildType = (BuildType) o;
+
+        if (mBuildConfigDebug != buildType.mBuildConfigDebug) return false;
+        if (mDebugJniBuild != buildType.mDebugJniBuild) return false;
+        if (mDebugSigned != buildType.mDebugSigned) return false;
+        if (mDebuggable != buildType.mDebuggable) return false;
+        if (mRunProguard != buildType.mRunProguard) return false;
+        if (mZipAlign != buildType.mZipAlign) return false;
+        if (mBuildConfigLines != null ?
+                !mBuildConfigLines.equals(buildType.mBuildConfigLines) :
+                buildType.mBuildConfigLines != null)
+            return false;
+        if (mName != null ? !mName.equals(buildType.mName) : buildType.mName != null) return false;
+        if (mPackageNameSuffix != null ?
+                !mPackageNameSuffix.equals(buildType.mPackageNameSuffix) :
+                buildType.mPackageNameSuffix != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mName != null ? mName.hashCode() : 0;
+        result = 31 * result + (mDebuggable ? 1 : 0);
+        result = 31 * result + (mDebugJniBuild ? 1 : 0);
+        result = 31 * result + (mDebugSigned ? 1 : 0);
+        result = 31 * result + (mPackageNameSuffix != null ? mPackageNameSuffix.hashCode() : 0);
+        result = 31 * result + (mRunProguard ? 1 : 0);
+        result = 31 * result + (mBuildConfigDebug ? 1 : 0);
+        result = 31 * result + (mBuildConfigLines != null ? mBuildConfigLines.hashCode() : 0);
+        result = 31 * result + (mZipAlign ? 1 : 0);
+        return result;
+    }
+
     @Override
     public String toString() {
         return "BuildType{" +
@@ -119,9 +176,4 @@ public class BuildType {
                 ", zipAlign=" + mZipAlign +
                 '}';
     }
-
-
-    /*
-Buildconfig: DEBUG flag + other custom properties?
-    */
 }
index 4ada56a..fd72ad8 100644 (file)
@@ -18,7 +18,12 @@ package com.android.builder;
 
 import com.android.annotations.NonNull;
 
-public class ProductFlavor {
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProductFlavor implements Serializable {
+    private static final long serialVersionUID = 1L;
 
     private final String mName;
     private int mMinSdkVersion = -1;
@@ -34,6 +39,8 @@ public class ProductFlavor {
     private String mSigningKeyAlias = null;
     private String mSigningKeyPassword = null;
 
+    private final List<String> mBuildConfigLines = new ArrayList<String>();
+
     public ProductFlavor(String name) {
         mName = name;
     }
@@ -137,6 +144,14 @@ public class ProductFlavor {
                 mSigningKeyPassword != null;
     }
 
+    public void setBuildConfigLines(List<String> lines) {
+        mBuildConfigLines.addAll(lines);
+    }
+
+    public List<String> getBuildConfigLines() {
+        return mBuildConfigLines;
+    }
+
     /**
      * Merges the flavor on top of a base platform and returns a new object with the result.
      * @param base the flavor to merge on top of
@@ -176,6 +191,76 @@ public class ProductFlavor {
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ProductFlavor that = (ProductFlavor) o;
+
+        if (mMinSdkVersion != that.mMinSdkVersion) return false;
+        if (mTargetSdkVersion != that.mTargetSdkVersion) return false;
+        if (mVersionCode != that.mVersionCode) return false;
+        if (mBuildConfigLines != null ?
+                !mBuildConfigLines.equals(that.mBuildConfigLines) :
+                that.mBuildConfigLines != null)
+            return false;
+        if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false;
+        if (mPackageName != null ?
+                !mPackageName.equals(that.mPackageName) :
+                that.mPackageName != null)
+            return false;
+        if (mSigningKeyAlias != null ?
+                !mSigningKeyAlias.equals(that.mSigningKeyAlias) :
+                that.mSigningKeyAlias != null)
+            return false;
+        if (mSigningKeyPassword != null ?
+                !mSigningKeyPassword.equals(that.mSigningKeyPassword) :
+                that.mSigningKeyPassword != null)
+            return false;
+        if (mSigningStoreLocation != null ?
+                !mSigningStoreLocation.equals(that.mSigningStoreLocation) :
+                that.mSigningStoreLocation != null)
+            return false;
+        if (mSigningStorePassword != null ?
+                !mSigningStorePassword.equals(that.mSigningStorePassword) :
+                that.mSigningStorePassword != null)
+            return false;
+        if (mTestInstrumentationRunner != null ?
+                !mTestInstrumentationRunner.equals(that.mTestInstrumentationRunner) :
+                that.mTestInstrumentationRunner != null)
+            return false;
+        if (mTestPackageName != null ?
+                !mTestPackageName.equals(that.mTestPackageName) : that.mTestPackageName != null)
+            return false;
+        if (mVersionName != null ?
+                !mVersionName.equals(that.mVersionName) : that.mVersionName != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mName != null ? mName.hashCode() : 0;
+        result = 31 * result + mMinSdkVersion;
+        result = 31 * result + mTargetSdkVersion;
+        result = 31 * result + mVersionCode;
+        result = 31 * result + (mVersionName != null ? mVersionName.hashCode() : 0);
+        result = 31 * result + (mPackageName != null ? mPackageName.hashCode() : 0);
+        result = 31 * result + (mTestPackageName != null ? mTestPackageName.hashCode() : 0);
+        result = 31 * result + (mTestInstrumentationRunner != null ?
+                mTestInstrumentationRunner.hashCode() : 0);
+        result = 31 * result + (mSigningStoreLocation != null ?
+                mSigningStoreLocation.hashCode() : 0);
+        result = 31 * result + (mSigningStorePassword != null ?
+                mSigningStorePassword.hashCode() : 0);
+        result = 31 * result + (mSigningKeyAlias != null ? mSigningKeyAlias.hashCode() : 0);
+        result = 31 * result + (mSigningKeyPassword != null ? mSigningKeyPassword.hashCode() : 0);
+        result = 31 * result + (mBuildConfigLines != null ? mBuildConfigLines.hashCode() : 0);
+        return result;
+    }
+
+    @Override
     public String toString() {
         return "ProductFlavor{" +
                 "name='" + mName + '\'' +
index 159bd18..31f17b7 100644 (file)
@@ -386,6 +386,22 @@ public class VariantConfiguration {
     }
 
     /**
+     * Returns a list of object that represents the configuration. This can be used to compare
+     * 2 different list of config objects to know whether the build is up to date or not.
+     * @return
+     */
+    public Iterable<Object> getConfigObjects() {
+        List<Object> list = new ArrayList<Object>();
+        list.add(mDefaultConfig);
+        list.add(mBuildType);
+        list.addAll(mFlavorConfigs);
+        // TODO: figure out the deps in here.
+//        list.addAll(mFlatLibraryProjects);
+
+        return list;
+    }
+
+    /**
      * Returns the dynamic list of resource folders based on the configuration, its dependencies,
      * as well as tested config if applicable (test of a library).
      * @return a list of input resource folders.
index 10c9635..fb22009 100644 (file)
@@ -165,6 +165,7 @@ abstract class AndroidBasePlugin {
                 ProcessManifest)
         processManifestTask.plugin = this
         processManifestTask.variant = variant
+        processManifestTask.configObjects = variant.configObjects
         processManifestTask.conventionMapping.processedManifest = {
             project.file(
                     "$project.buildDir/${manifestOurDir}/$variant.dirName/AndroidManifest.xml")
@@ -177,6 +178,7 @@ abstract class AndroidBasePlugin {
         def crunchTask = project.tasks.add("crunch${variant.name}Res", CrunchResources)
         crunchTask.plugin = this
         crunchTask.variant = variant
+        crunchTask.configObjects = variant.configObjects
         crunchTask.conventionMapping.resDirectories = { variant.config.resourceInputs }
         crunchTask.conventionMapping.outputDir = {
             project.file("$project.buildDir/res/$variant.dirName")
@@ -195,6 +197,7 @@ abstract class AndroidBasePlugin {
         }
         generateBuildConfigTask.plugin = this
         generateBuildConfigTask.variant = variant
+        generateBuildConfigTask.configObjects = variant.configObjects
         generateBuildConfigTask.conventionMapping.sourceOutputDir = {
             project.file("$project.buildDir/source/${variant.dirName}")
         }
@@ -208,6 +211,7 @@ abstract class AndroidBasePlugin {
         processResources.dependsOn processManifestTask
         processResources.plugin = this
         processResources.variant = variant
+        processResources.configObjects = variant.configObjects
         processResources.conventionMapping.manifestFile = { processManifestTask.processedManifest }
         // TODO: unify with generateBuilderConfig somehow?
         processResources.conventionMapping.sourceOutputDir = {
@@ -340,6 +344,7 @@ abstract class AndroidBasePlugin {
         packageApp.dependsOn variant.resourcePackage, dexTask
         packageApp.plugin = this
         packageApp.variant = variant
+        packageApp.configObjects = variant.configObjects
 
         def signedApk = variant.isSigned()
 
index ddb04a9..0efd852 100644 (file)
@@ -26,7 +26,6 @@ import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.Task
 import org.gradle.api.plugins.BasePlugin
-import org.gradle.internal.reflect.Instantiator
 
 class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
     private final Map<String, BuildTypeData> buildTypes = [:]
@@ -39,10 +38,7 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
         super.apply(project)
 
         def buildTypes = project.container(BuildType)
-        // TODO - do the decoration by default
-        def productFlavors = project.container(ProductFlavor) { name ->
-            project.services.get(Instantiator).newInstance(ProductFlavor, name)
-        }
+        def productFlavors = project.container(ProductFlavor)
 
         extension = project.extensions.create('android', AndroidExtension,
                 buildTypes, productFlavors)
index fd5a585..94cba8e 100644 (file)
@@ -18,12 +18,17 @@ package com.android.build.gradle
 import com.android.build.gradle.internal.ApplicationVariant
 import com.android.builder.AndroidBuilder
 import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
 
 abstract class BaseAndroidTask extends DefaultTask {
 
     AndroidBasePlugin plugin
     ApplicationVariant variant
 
+    @Input @Optional
+    Iterable<Object> configObjects
+
     protected AndroidBuilder getBuilder() {
         AndroidBuilder androidBuilder = plugin.getAndroidBuilder(variant);
 
index 510129b..ea52fce 100644 (file)
@@ -16,8 +16,8 @@
 package com.android.build.gradle
 
 import com.android.builder.DexOptions
-import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Nested
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 
@@ -31,7 +31,7 @@ class Dex extends BaseAndroidTask {
     @InputFiles
     Iterable<File> libraries
 
-    @Input
+    @Nested
     DexOptions dexOptions
 
     @TaskAction
index 1913e78..178f514 100644 (file)
@@ -31,6 +31,6 @@ class GenerateBuildConfigTask extends BaseAndroidTask {
     @TaskAction
     void generate() {
         getBuilder().generateBuildConfig(getSourceOutputDir().absolutePath,
-                optionalJavaLines);
+                getOptionalJavaLines());
     }
 }
index 11126c9..ca72ade 100644 (file)
 package com.android.build.gradle
 
 import com.android.build.gradle.internal.AaptOptionsImpl
-import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputDirectory
 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.OutputDirectory
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
-import org.gradle.api.tasks.InputFiles
 
 class ProcessResources extends BaseAndroidTask {
 
@@ -45,7 +45,7 @@ class ProcessResources extends BaseAndroidTask {
     @OutputFile @Optional
     File proguardFile
 
-    @Input
+    @Nested
     AaptOptionsImpl aaptOptions
 
     @TaskAction
index 4a22d9f..49f3ea2 100644 (file)
@@ -18,11 +18,14 @@ package com.android.build.gradle.internal;
 
 
 import com.android.builder.AaptOptions
+import org.gradle.api.tasks.Input
 
-public class AaptOptionsImpl implements AaptOptions, Serializable {
-    private static final long serialVersionUID = 1L
+public class AaptOptionsImpl implements AaptOptions {
 
+    @Input
     private String ignoreAssetsPattern
+
+    @Input
     private List<String> noCompressList
 
     public void ignoreAssetsPattern(String ignoreAssetsPattern) {
index 54b3039..673a0d4 100644 (file)
@@ -31,17 +31,27 @@ public abstract class ApplicationVariant {
     FileCollection packagedClasspath
     FileCollection resourcePackage
     Compile compileTask
+    Iterable<Object> configObjects
 
     ApplicationVariant(VariantConfiguration config) {
         this.config = config
     }
 
+    Iterable<Object> getConfigObjects() {
+        if (configObjects == null) {
+            configObjects = config.configObjects
+        }
+
+        return configObjects
+    }
+
     abstract String getDescription()
 
     abstract String getDirName()
 
     abstract String getBaseName()
 
+
     abstract boolean getZipAlign()
 
     abstract boolean isSigned()
index 83dfbc4..bc28079 100644 (file)
@@ -18,6 +18,5 @@ package com.android.build.gradle.internal
 
 import com.android.builder.DexOptions;
 
-public class DexOptionsImpl implements DexOptions, Serializable {
-    private static final long serialVersionUID = 1L
+public class DexOptionsImpl implements DexOptions {
 }