kotlin-android plugin: use VariantDataList instead of list of Variant.

Support junit tests
Fix sourceRoot dependencies for productFlavors
#KT-7065 Fixed
#KT-7506 Fixed
This commit is contained in:
Natalia Ukhorskaya
2015-04-23 16:27:34 +03:00
parent cb85da3162
commit 88e9439d25
@@ -24,6 +24,9 @@ import com.android.build.gradle.BasePlugin
import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.api.LibraryVariant
import com.android.build.gradle.api.ApkVariant import com.android.build.gradle.api.ApkVariant
import com.android.build.gradle.api.TestVariant import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.BaseVariantOutputData
import com.android.builder.core.VariantType
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.ConfigurationContainer import org.gradle.api.artifacts.ConfigurationContainer
@@ -35,6 +38,7 @@ import org.gradle.api.file.SourceDirectorySet
import kotlin.properties.Delegates import kotlin.properties.Delegates
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import groovy.lang.Closure import groovy.lang.Closure
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import java.util.ServiceLoader import java.util.ServiceLoader
import org.gradle.api.logging.* import org.gradle.api.logging.*
@@ -288,112 +292,81 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t
project afterEvaluate { project -> project afterEvaluate { project ->
if (project != null) { if (project != null) {
val testVariants = AndroidGradleWrapper.getTestVariants(ext) val plugin = (project.getPlugins().findPlugin("android")
processVariants(testVariants, project, ext) ?: project.getPlugins().findPlugin("android-library")) as BasePlugin
if (ext is AppExtension) {
val appVariants = ext.getApplicationVariants()!!
processVariants(appVariants, project, ext)
}
if (ext is LibraryExtension) { processVariantData(plugin.getVariantManager().getVariantDataList(), project, ext, plugin)
val libVariants = ext.getLibraryVariants()!!
processVariants(libVariants, project, ext)
}
} }
} }
project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler, project).resolveKotlinPluginDependency("kotlin-android-sdk-annotations")) project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler, project).resolveKotlinPluginDependency("kotlin-android-sdk-annotations"))
} }
private fun processVariants(variants: DefaultDomainObjectSet<out BaseVariant>, project: Project, androidExt: BaseExtension): Unit { private fun processVariantData(
variantDataList: List<BaseVariantData<out BaseVariantOutputData>>,
project: Project,
androidExt: BaseExtension,
androidPlugin: BasePlugin
) {
val logger = project.getLogger() val logger = project.getLogger()
val kotlinOptions = getExtension<Any?>(androidExt, "kotlinOptions") val kotlinOptions = getExtension<Any?>(androidExt, "kotlinOptions")
val sourceSets = androidExt.getSourceSets()
//TODO: change to BuilderConstants.MAIN - it was relocated in 0.11 plugin
val mainSourceSet = sourceSets.getByName("main")
val testSourceSet = try {
sourceSets.getByName("instrumentTest")
} catch (e: UnknownDomainObjectException) {
sourceSets.getByName("androidTest")
}
val subpluginEnvironment = loadSubplugins(project, logger) val subpluginEnvironment = loadSubplugins(project, logger)
for (variant in variants) { for (variantData in variantDataList) {
if (variant is LibraryVariant || variant is ApkVariant) { val variantDataName = variantData.getName()
val buildTypeSourceSetName = AndroidGradleWrapper.getVariantName(variant) logger.debug("Process variant [$variantDataName]")
logger.debug("Variant build type is [$buildTypeSourceSetName]") val javaTask = variantData.javaCompileTask
val buildTypeSourceSet = sourceSets.findByName(buildTypeSourceSetName)
val javaTask = variant.getJavaCompile()!! val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin"
val variantName = variant.getName()
val kotlinTaskName = "compile${variantName.capitalize()}Kotlin"
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName) val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName)
if (kotlinOptions != null) { if (kotlinOptions != null) {
kotlinTask.setProperty("kotlinOptions", kotlinOptions) kotlinTask.setProperty("kotlinOptions", kotlinOptions)
} }
// store kotlin classes in separate directory. They will serve as class-path to java compiler // store kotlin classes in separate directory. They will serve as class-path to java compiler
val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantName}") val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantDataName}")
kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir) kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir)
kotlinTask.setDestinationDir(javaTask.getDestinationDir()) kotlinTask.setDestinationDir(javaTask.getDestinationDir())
kotlinTask.setDescription("Compiles the ${variantName} kotlin.") kotlinTask.setDescription("Compiles the ${variantDataName} kotlin.")
kotlinTask.setClasspath(javaTask.getClasspath()) kotlinTask.setClasspath(javaTask.getClasspath())
kotlinTask.setDependsOn(javaTask.getDependsOn()) kotlinTask.setDependsOn(javaTask.getDependsOn())
fun processSourceSet(javaSourceSet: AndroidSourceSet): SourceDirectorySet { fun SourceDirectorySet.addSourceDirectories(additionalSourceFiles: Collection<File>) {
val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(javaSourceSet) for (dir in additionalSourceFiles) {
val kotlinSourceSet = getExtension<KotlinSourceSet>(javaSourceSet, "kotlin") this.srcDir(dir)
val kotlinSDS = kotlinSourceSet.getKotlin() logger.debug("Source directory ${dir.getAbsolutePath()} was added to kotlin source for $kotlinTaskName")
for (dir in javaSrcDirs) {
kotlinSDS.srcDir(dir)
} }
kotlinTask.source(kotlinSDS)
return kotlinSDS
} }
if (variant is TestVariant) { fun configureDefaultSourceSet() {
processSourceSet(testSourceSet) val defaultSourceSet = variantData.getVariantConfiguration().getDefaultSourceSet()
} else { val kotlinSourceDirectorySet = getExtension<KotlinSourceSet>(defaultSourceSet, "kotlin").getKotlin()
processSourceSet(mainSourceSet) // getJavaSources should return the Java sources used for compilation
// We want to collect only generated files, like R-class output dir
// Actual java sources will be collected later
val additionalSourceFiles = variantData.getJavaSources().filterIsInstance(javaClass<File>())
kotlinSourceDirectorySet.addSourceDirectories(additionalSourceFiles)
} }
if (buildTypeSourceSet != null) { configureDefaultSourceSet()
val variantSourceDirectorySet = processSourceSet(buildTypeSourceSet)
for (resourceFolder in AndroidGradleWrapper.getRClassFolder(variant)) {
variantSourceDirectorySet.srcDir(resourceFolder)
}
variantSourceDirectorySet.srcDir(variant.getGenerateBuildConfig()?.getSourceOutputDir())
variantSourceDirectorySet.srcDir(variant.getAidlCompile().getSourceOutputDir())
variantSourceDirectorySet.srcDir(variant.getRenderscriptCompile().getSourceOutputDir())
}
if (variant is ApkVariant) { // getSortedSourceProviders should return only actual java sources, generated sources should be collected earlier
for (flavourName in AndroidGradleWrapper.getProductFlavorsNames(variant)) { val providers = variantData.getVariantConfiguration().getSortedSourceProviders()
val defaultFlavourSourceSetName = flavourName + buildTypeSourceSetName.capitalize() for (provider in providers) {
val defaultFlavourSourceSet = sourceSets.findByName(defaultFlavourSourceSetName) val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(provider as AndroidSourceSet)
if (defaultFlavourSourceSet != null) { val kotlinSourceSet = getExtension<KotlinSourceSet>(provider, "kotlin")
processSourceSet(defaultFlavourSourceSet) val kotlinSourceDirectorySet = kotlinSourceSet.getKotlin()
} kotlinTask.source(kotlinSourceDirectorySet)
val flavourSourceSet = sourceSets.findByName(flavourName) kotlinSourceDirectorySet.addSourceDirectories(javaSrcDirs)
if (flavourSourceSet != null) {
processSourceSet(flavourSourceSet)
}
}
} }
subpluginEnvironment.addSubpluginArguments(project, kotlinTask) subpluginEnvironment.addSubpluginArguments(project, kotlinTask)
kotlinTask doFirst { kotlinTask doFirst {
var plugin = project.getPlugins().findPlugin("android") val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
if (null == plugin) {
plugin = project.getPlugins().findPlugin("android-library")
}
val basePlugin: BasePlugin = plugin as BasePlugin
val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(basePlugin, androidExt))
val fullClasspath = (javaTask.getClasspath() + androidRT) - project.files(kotlinTask.property("kotlinDestinationDir")) val fullClasspath = (javaTask.getClasspath() + androidRT) - project.files(kotlinTask.property("kotlinDestinationDir"))
(it as AbstractCompile).setClasspath(fullClasspath) (it as AbstractCompile).setClasspath(fullClasspath)
} }
@@ -405,7 +378,6 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t
} }
} }
} }
}
fun <T> getExtension(obj: Any, extensionName: String): T { fun <T> getExtension(obj: Any, extensionName: String): T {
if (obj is ExtensionAware) { if (obj is ExtensionAware) {