Started wiring up library and jar dependencies.
Adam Murdoch [Thu, 13 Sep 2012 02:17:05 +0000 (12:17 +1000)]
Changed the AndroidLibraryPlugin to publish both library variants.

Changed the AndroidPlugin to unzip incoming library bundles and
provide the appropriate AndroidDependency implementations.

Lots of things not finished yet:

* Does not work for libraries published to a Maven repository.
* Creates a flattened list of library dependencies, rather than a graph.
* Jar dependencies are not wired up.
* Only implemented for applications, not libraries or test apps.
* Does not include variant specific dependencies.
* Needs some more work to better wire up the task dependencies.

Change-Id: I20f5c298ca051c203828c4076e2693aef47ace70

gradle/src/main/groovy/com/android/build/gradle/AndroidLibraryPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/AndroidPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/PrepareDependenciesTask.groovy [new file with mode: 0644]
gradle/src/main/groovy/com/android/build/gradle/internal/AndroidDependencyImpl.groovy [new file with mode: 0644]
testapps/applibtest/app/build.gradle

index c376e62..894fda0 100644 (file)
@@ -53,6 +53,10 @@ class AndroidLibraryPlugin extends AndroidBasePlugin implements Plugin<Project>
         project.tasks.assemble.dependsOn debugBuildTypeData.assembleTask
         project.tasks.assemble.dependsOn releaseBuildTypeData.assembleTask
 
+        project.configurations.add(BuildType.DEBUG)
+        def releaseConfig = project.configurations.add(BuildType.RELEASE)
+        project.configurations["default"].extendsFrom(releaseConfig)
+
         project.afterEvaluate {
             createAndroidTasks()
         }
@@ -127,6 +131,8 @@ class AndroidLibraryPlugin extends AndroidBasePlugin implements Plugin<Project>
         bundle.baseName = "${project.archivesBaseName}-${variant.baseName}"
         bundle.from(project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}"))
 
+        project.artifacts.add(buildTypeData.buildType.name, bundle)
+
         buildTypeData.assembleTask.dependsOn bundle
         variant.assembleTask = bundle
 
index 9fa9c93..ca1235b 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.android.build.gradle
 
+import com.android.build.gradle.internal.AndroidDependencyImpl
 import com.android.build.gradle.internal.BuildTypeData
 import com.android.build.gradle.internal.BuildTypeDsl
 import com.android.build.gradle.internal.ProductFlavorData
@@ -27,6 +28,7 @@ import com.android.builder.VariantConfiguration
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.Task
+import org.gradle.api.artifacts.ProjectDependency
 import org.gradle.api.plugins.BasePlugin
 
 class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
@@ -140,8 +142,6 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
             def variantConfig = new VariantConfiguration(
                     defaultConfigData.productFlavor, defaultConfigData.androidSourceSet,
                     buildTypeData.buildType, buildTypeData.androidSourceSet)
-            // TODO: add actual dependencies
-            variantConfig.setAndroidDependencies(null)
 
             boolean isTestedVariant = (buildTypeData == testData)
 
@@ -190,9 +190,6 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
             variantConfig.addProductFlavor(productFlavorData.productFlavor,
                     productFlavorData.androidSourceSet)
 
-            // TODO: add actual dependencies
-            variantConfig.setAndroidDependencies(null)
-
             boolean isTestedVariant = (buildTypeData == testData)
 
             ProductionAppVariant productionAppVariant = addVariant(variantConfig, null,
@@ -235,8 +232,12 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
 
         def variant = new ProductionAppVariant(variantConfig)
 
+        def prepareDependenciesTask = createPrepareDependenciesTask(variant)
+
         // Add a task to process the manifest(s)
-        ProcessManifestTask processManifestTask = createProcessManifestTask(variant, "manifests")
+        def processManifestTask = createProcessManifestTask(variant, "manifests")
+        // TODO - move this
+        processManifestTask.dependsOn prepareDependenciesTask
 
         // Add a task to crunch resource files
         def crunchTask = createCrunchResTask(variant)
@@ -248,6 +249,8 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
         def processResources = createProcessResTask(variant, processManifestTask, crunchTask)
 
         def compileAidl = createAidlTask(variant)
+        // TODO - move this
+        compileAidl.dependsOn prepareDependenciesTask
 
         // Add a compile task
         createCompileTask(variant, null/*testedVariant*/, processResources, generateBuildConfigTask,
@@ -265,4 +268,39 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
     String getTarget() {
         return extension.target;
     }
+
+    PrepareDependenciesTask createPrepareDependenciesTask(ProductionAppVariant variant) {
+        // TODO - include variant specific dependencies too
+        def compileClasspath = project.configurations.compile
+
+        // TODO - need to sort out ordering here
+        compileClasspath.allDependencies.withType(ProjectDependency).each { dep ->
+            project.evaluationDependsOn(dep.dependencyProject.path)
+        }
+
+        def prepareDependenciesTask = project.tasks.add("prepare${variant.name}Dependencies", PrepareDependenciesTask)
+
+        // TODO - should be able to infer this
+        prepareDependenciesTask.dependsOn compileClasspath
+
+        // TODO - defer downloading until required
+        // TODO - build the library dependency graph
+        List<File> jars = []
+        List<AndroidDependencyImpl> bundles = []
+        compileClasspath.resolvedConfiguration.resolvedArtifacts.each { artifact ->
+            if (artifact.type == 'alb') {
+                def explodedDir = project.file("$project.buildDir/exploded-bundles/$artifact.file.name")
+                bundles << new AndroidDependencyImpl(explodedDir)
+                prepareDependenciesTask.add(artifact.file, explodedDir)
+            } else {
+                jars << artifact.file
+            }
+        }
+
+        variant.config.androidDependencies = bundles
+
+        // TODO - attach jars
+
+        return prepareDependenciesTask
+    }
 }
diff --git a/gradle/src/main/groovy/com/android/build/gradle/PrepareDependenciesTask.groovy b/gradle/src/main/groovy/com/android/build/gradle/PrepareDependenciesTask.groovy
new file mode 100644 (file)
index 0000000..70a984a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectories
+import org.gradle.api.tasks.TaskAction
+
+class PrepareDependenciesTask extends DefaultTask {
+    final Map<File, File> bundles = [:]
+
+    void add(File bundle, File explodedDir) {
+        bundles[bundle] = explodedDir
+    }
+
+    @InputFiles
+    Iterable<File> getBundles() {
+        return bundles.keySet()
+    }
+
+
+    @OutputDirectories
+    Iterable<File> getExplodedBundles() {
+        return bundles.values()
+    }
+
+    @TaskAction
+    def prepare() {
+        bundles.each { bundle, explodedDir ->
+            project.copy {
+                from project.zipTree(bundle)
+                into explodedDir
+            }
+        }
+    }
+}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidDependencyImpl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidDependencyImpl.groovy
new file mode 100644 (file)
index 0000000..a38896c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.internal
+
+import com.android.builder.AndroidDependency
+
+class AndroidDependencyImpl implements AndroidDependency {
+    private final File explodedBundle
+
+    AndroidDependencyImpl(File explodedBundle) {
+        this.explodedBundle = explodedBundle
+    }
+
+    @Override
+    File getJarFile() {
+        return new File(explodedBundle, "classes.jar")
+    }
+
+    @Override
+    File getManifest() {
+        return new File(explodedBundle, "AndroidManifest.xml")
+    }
+
+    @Override
+    List<AndroidDependency> getDependencies() {
+        return []
+    }
+
+    @Override
+    File getAidlFolder() {
+        return new File(explodedBundle, "aidl")
+    }
+
+    @Override
+    File getResFolder() {
+        return new File(explodedBundle, "res")
+    }
+
+    @Override
+    File getAssetsFolder() {
+        // TODO - implement
+        return null;
+    }
+
+    @Override
+    File getJniFolder() {
+        // TODO - implement
+        return null
+    }
+
+    @Override
+    File getLintJar() {
+        // TODO - implement
+        return null
+    }
+
+    @Override
+    File getProguardRules() {
+        // TODO - implement
+        return null
+    }
+}
+
+
+
index 1faee70..abc0dbd 100644 (file)
@@ -1,8 +1,12 @@
 apply plugin: 'android'
 
+android {
+    target = "android-15"
+}
+
 //
 // A basic Android application split over a library and a main project.
 //
 dependencies {
-//    compile project(':lib')
+    compile project(':lib')
 }