Support compile config for flavors and build types.
[android/platform/tools/build.git] / gradle / src / main / groovy / com / android / build / gradle / LibraryPlugin.groovy
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.build.gradle
17
18 import com.android.build.gradle.internal.BuildTypeData
19 import com.android.build.gradle.internal.ConfigurationDependencies
20 import com.android.build.gradle.internal.ProductFlavorData
21 import com.android.build.gradle.internal.ProductionAppVariant
22 import com.android.build.gradle.internal.TestAppVariant
23 import com.android.builder.AndroidDependency
24 import com.android.builder.BuildType
25 import com.android.builder.BundleDependency
26 import com.android.builder.JarDependency
27 import com.android.builder.VariantConfiguration
28 import org.gradle.api.Plugin
29 import org.gradle.api.Project
30 import org.gradle.api.internal.project.ProjectInternal
31 import org.gradle.api.plugins.MavenPlugin
32 import org.gradle.api.tasks.Copy
33 import org.gradle.api.tasks.bundling.Jar
34 import org.gradle.api.tasks.bundling.Zip
35
36 class LibraryPlugin extends BasePlugin implements Plugin<Project> {
37
38     private final static String DIR_BUNDLES = "bundles";
39
40     LibraryExtension extension
41     BuildTypeData debugBuildTypeData
42     BuildTypeData releaseBuildTypeData
43
44     @Override
45     void apply(Project project) {
46         super.apply(project)
47
48         extension = project.extensions.create('android', LibraryExtension,
49                 (ProjectInternal) project)
50         setDefaultConfig(extension.defaultConfig, extension.sourceSetsContainer)
51
52         // create the source sets for the build type.
53         // the ones for the main product flavors are handled by the base plugin.
54         def debugSourceSet = extension.sourceSetsContainer.create(BuildType.DEBUG)
55         def releaseSourceSet = extension.sourceSetsContainer.create(BuildType.RELEASE)
56
57         debugBuildTypeData = new BuildTypeData(extension.debug, debugSourceSet, project)
58         releaseBuildTypeData = new BuildTypeData(extension.release, releaseSourceSet, project)
59         project.tasks.assemble.dependsOn debugBuildTypeData.assembleTask
60         project.tasks.assemble.dependsOn releaseBuildTypeData.assembleTask
61
62         createConfigurations()
63
64         project.afterEvaluate {
65             createAndroidTasks()
66         }
67     }
68
69     void createConfigurations() {
70         def debugConfig = project.configurations.add(BuildType.DEBUG)
71         def releaseConfig = project.configurations.add(BuildType.RELEASE)
72         debugConfig.extendsFrom(project.configurations["package"])
73         releaseConfig.extendsFrom(project.configurations["package"])
74         project.configurations["default"].extendsFrom(releaseConfig)
75
76         // Adjust the pom scope mappings
77         // TODO - this should be part of JavaBase plugin. Fix this in Gradle
78         project.plugins.withType(MavenPlugin) {
79             project.conf2ScopeMappings.addMapping(300, project.configurations.compile, "runtime")
80             project.conf2ScopeMappings.addMapping(300, project.configurations["package"], "runtime")
81             project.conf2ScopeMappings.addMapping(300, releaseConfig, "runtime")
82         }
83     }
84
85     void createAndroidTasks() {
86         // resolve dependencies for all config
87         List<ConfigurationDependencies> dependencies = []
88         dependencies.add(debugBuildTypeData)
89         dependencies.add(releaseBuildTypeData)
90         resolveDependencies(dependencies)
91
92         ProductionAppVariant testedVariant = createLibraryTasks(debugBuildTypeData)
93         createLibraryTasks(releaseBuildTypeData)
94         createTestTasks(testedVariant)
95         createDependencyReportTask()
96     }
97
98     ProductionAppVariant createLibraryTasks(BuildTypeData buildTypeData) {
99         ProductFlavorData defaultConfigData = getDefaultConfigData();
100
101         List<ConfigurationDependencies> configDependencies = []
102         configDependencies.add(defaultConfigData)
103         configDependencies.add(buildTypeData)
104
105         // list of dependency to set on the variantConfig
106         List<JarDependency> jars = []
107         jars.addAll(defaultConfigData.jars)
108         jars.addAll(buildTypeData.jars)
109
110         // the order of the libraries is important. In descending order:
111         // build types, defaultConfig.
112         List<AndroidDependency> libs = []
113         libs.addAll(buildTypeData.libraries)
114         libs.addAll(defaultConfigData.libraries)
115
116         def variantConfig = new VariantConfiguration(
117                 defaultConfigData.productFlavor, defaultConfigData.sourceSet,
118                 buildTypeData.buildType, buildTypeData.sourceSet,
119                 VariantConfiguration.Type.LIBRARY)
120
121         variantConfig.setJarDependencies(jars)
122         variantConfig.setAndroidDependencies(libs)
123
124         ProductionAppVariant variant = new ProductionAppVariant(variantConfig)
125         variants.add(variant)
126
127         def prepareDependenciesTask = createPrepareDependenciesTask(variant, configDependencies)
128
129         // Add a task to process the manifest(s)
130         ProcessManifestTask processManifestTask = createProcessManifestTask(variant, DIR_BUNDLES)
131         // TODO - move this
132         processManifestTask.dependsOn prepareDependenciesTask
133
134         // Add a task to create the BuildConfig class
135         def generateBuildConfigTask = createBuildConfigTask(variant, null)
136
137         // Add a task to generate resource source files
138         def processResources = createProcessResTask(variant, processManifestTask,
139                 null /*crunchTask*/)
140
141         // process java resources
142         createProcessJavaResTask(variant)
143
144         def compileAidl = createAidlTask(variant)
145         // TODO - move this
146         compileAidl.dependsOn prepareDependenciesTask
147
148         // Add a compile task
149         createCompileTask(variant, null/*testedVariant*/, processResources, generateBuildConfigTask,
150                 compileAidl)
151
152         // jar the classes.
153         Jar jar = project.tasks.add("package${buildTypeData.buildType.name.capitalize()}Jar", Jar);
154         jar.dependsOn variant.compileTask, variant.processJavaResources
155         jar.from(variant.compileTask.outputs);
156         jar.from(variant.processJavaResources.destinationDir)
157
158         jar.destinationDir = project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}")
159         jar.archiveName = "classes.jar"
160         String packageName = variantConfig.getPackageFromManifest().replace('.', '/');
161         jar.exclude(packageName + "/R.class")
162         jar.exclude(packageName + "/R\$*.class")
163
164         // package the android resources into the bundle folder
165         Copy packageRes = project.tasks.add("package${variant.name}Res", Copy)
166         // packageRes from 3 sources. the order is important to make sure the override works well.
167         // TODO: fix the case of values -- need to merge the XML!
168         packageRes.from(defaultConfigData.sourceSet.resources.directory,
169                 buildTypeData.sourceSet.resources.directory)
170         packageRes.into(project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}/res"))
171
172         // package the aidl files into the bundle folder
173         Copy packageAidl = project.tasks.add("package${variant.name}Aidl", Copy)
174         // packageAidl from 3 sources. the order is important to make sure the override works well.
175         packageAidl.from(defaultConfigData.sourceSet.aidl.directory,
176                 buildTypeData.sourceSet.aidl.directory)
177         packageAidl.into(project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}/aidl"))
178
179         // package the R symbol test file into the bundle folder
180         Copy packageSymbol = project.tasks.add("package${variant.name}Symbols", Copy)
181         packageSymbol.dependsOn processResources
182         packageSymbol.from(processResources.textSymbolDir)
183         packageSymbol.into(project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}"))
184
185         Zip bundle = project.tasks.add("bundle${variant.name}", Zip)
186         bundle.dependsOn jar, packageRes, packageAidl, packageSymbol
187         bundle.setDescription("Assembles a bundle containing the library in ${variant.name}.");
188         bundle.destinationDir = project.file("$project.buildDir/libs")
189         bundle.extension = "alb"
190         if (variant.baseName != BuildType.RELEASE) {
191             bundle.classifier = variant.baseName
192         }
193         bundle.from(project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}"))
194
195         project.artifacts.add(buildTypeData.buildType.name, bundle)
196
197         buildTypeData.assembleTask.dependsOn bundle
198         variant.assembleTask = bundle
199
200         // configure the variant to be testable.
201         variantConfig.output = new BundleDependency(
202                 project.file("$project.buildDir/$DIR_BUNDLES/${variant.dirName}"),
203                 variant.getName()) {
204
205             @Override
206             List<AndroidDependency> getDependencies() {
207                 return variantConfig.directLibraries
208             }
209         };
210
211         return variant
212     }
213
214     void createTestTasks(ProductionAppVariant testedVariant) {
215         ProductFlavorData defaultConfigData = getDefaultConfigData();
216
217         List<ConfigurationDependencies> configDependencies = []
218         configDependencies.add(defaultConfigData.testConfigDependencies)
219
220         // list of dependency to set on the variantConfig
221         List<JarDependency> jars = []
222         jars.addAll(defaultConfigData.testConfigDependencies.jars)
223
224         // the order of the libraries is important. In descending order:
225         // build types, defaultConfig.
226         List<AndroidDependency> libs = []
227         libs.addAll(defaultConfigData.testConfigDependencies.libraries)
228
229         def testVariantConfig = new VariantConfiguration(
230                 defaultConfigData.productFlavor, defaultConfigData.testSourceSet,
231                 debugBuildTypeData.buildType, null,
232                 VariantConfiguration.Type.TEST, testedVariant.config)
233
234         testVariantConfig.setJarDependencies(jars)
235         testVariantConfig.setAndroidDependencies(libs)
236
237         def testVariant = new TestAppVariant(testVariantConfig,)
238         variants.add(testVariant)
239         createTestTasks(testVariant, testedVariant, configDependencies)
240     }
241
242     @Override
243     String getTarget() {
244         return extension.target
245     }
246
247     protected String getManifestOutDir() {
248         return DIR_BUNDLES
249     }
250 }