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,121 +292,89 @@ 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 kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName)
if (kotlinOptions != null) {
kotlinTask.setProperty("kotlinOptions", kotlinOptions)
}
val kotlinTaskName = "compile${variantName.capitalize()}Kotlin" // store kotlin classes in separate directory. They will serve as class-path to java compiler
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName) val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantDataName}")
if (kotlinOptions != null) { kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir)
kotlinTask.setProperty("kotlinOptions", kotlinOptions) kotlinTask.setDestinationDir(javaTask.getDestinationDir())
kotlinTask.setDescription("Compiles the ${variantDataName} kotlin.")
kotlinTask.setClasspath(javaTask.getClasspath())
kotlinTask.setDependsOn(javaTask.getDependsOn())
fun SourceDirectorySet.addSourceDirectories(additionalSourceFiles: Collection<File>) {
for (dir in additionalSourceFiles) {
this.srcDir(dir)
logger.debug("Source directory ${dir.getAbsolutePath()} was added to kotlin source for $kotlinTaskName")
} }
}
// store kotlin classes in separate directory. They will serve as class-path to java compiler fun configureDefaultSourceSet() {
val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantName}") val defaultSourceSet = variantData.getVariantConfiguration().getDefaultSourceSet()
kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir) val kotlinSourceDirectorySet = getExtension<KotlinSourceSet>(defaultSourceSet, "kotlin").getKotlin()
kotlinTask.setDestinationDir(javaTask.getDestinationDir()) // getJavaSources should return the Java sources used for compilation
kotlinTask.setDescription("Compiles the ${variantName} kotlin.") // We want to collect only generated files, like R-class output dir
kotlinTask.setClasspath(javaTask.getClasspath()) // Actual java sources will be collected later
kotlinTask.setDependsOn(javaTask.getDependsOn()) val additionalSourceFiles = variantData.getJavaSources().filterIsInstance(javaClass<File>())
kotlinSourceDirectorySet.addSourceDirectories(additionalSourceFiles)
}
fun processSourceSet(javaSourceSet: AndroidSourceSet): SourceDirectorySet { configureDefaultSourceSet()
val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(javaSourceSet)
val kotlinSourceSet = getExtension<KotlinSourceSet>(javaSourceSet, "kotlin")
val kotlinSDS = kotlinSourceSet.getKotlin()
for (dir in javaSrcDirs) {
kotlinSDS.srcDir(dir)
}
kotlinTask.source(kotlinSDS)
return kotlinSDS
}
if (variant is TestVariant) { // getSortedSourceProviders should return only actual java sources, generated sources should be collected earlier
processSourceSet(testSourceSet) val providers = variantData.getVariantConfiguration().getSortedSourceProviders()
} else { for (provider in providers) {
processSourceSet(mainSourceSet) val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(provider as AndroidSourceSet)
} val kotlinSourceSet = getExtension<KotlinSourceSet>(provider, "kotlin")
val kotlinSourceDirectorySet = kotlinSourceSet.getKotlin()
kotlinTask.source(kotlinSourceDirectorySet)
if (buildTypeSourceSet != null) { kotlinSourceDirectorySet.addSourceDirectories(javaSrcDirs)
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) { subpluginEnvironment.addSubpluginArguments(project, kotlinTask)
for (flavourName in AndroidGradleWrapper.getProductFlavorsNames(variant)) {
val defaultFlavourSourceSetName = flavourName + buildTypeSourceSetName.capitalize()
val defaultFlavourSourceSet = sourceSets.findByName(defaultFlavourSourceSetName)
if (defaultFlavourSourceSet != null) {
processSourceSet(defaultFlavourSourceSet)
}
val flavourSourceSet = sourceSets.findByName(flavourName) kotlinTask doFirst {
if (flavourSourceSet != null) { val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
processSourceSet(flavourSourceSet) val fullClasspath = (javaTask.getClasspath() + androidRT) - project.files(kotlinTask.property("kotlinDestinationDir"))
} (it as AbstractCompile).setClasspath(fullClasspath)
} }
}
subpluginEnvironment.addSubpluginArguments(project, kotlinTask) javaTask.dependsOn(kotlinTaskName)
kotlinTask doFirst { javaTask doFirst {
var plugin = project.getPlugins().findPlugin("android") javaTask.setClasspath(javaTask.getClasspath() + project.files(kotlinTask.property("kotlinDestinationDir")))
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"))
(it as AbstractCompile).setClasspath(fullClasspath)
}
javaTask.dependsOn(kotlinTaskName)
javaTask doFirst {
javaTask.setClasspath(javaTask.getClasspath() + project.files(kotlinTask.property("kotlinDestinationDir")))
}
} }
} }
} }