Add prototype against the new AGP API

* Add a separate Gradle source set, that is compiled against the new
  versions of AGP and Gradle

* Separate the public AGP API usages from the old internal API usages
  in KotlinPlugin.kt -- see AbstractAndroidProjectHandler

* Implement Android25ProjectHandler with the new AGP API, wired it
  to KotlinAndroidPlugin through reflection

(cherry picked from commit e6dbf54)

(cherry picked from commit 88e3d4b)
This commit is contained in:
Sergey Igushkin
2017-05-05 19:17:26 +03:00
committed by Alexey Tsvetkov
parent a5620454fa
commit eb71dee9cc
4 changed files with 344 additions and 145 deletions
@@ -19,6 +19,13 @@ repositories {
jcenter()
mavenLocal()
maven { url 'http://repository.jetbrains.com/utils/' }
// todo: remove this once the AGP artifacts get published
maven { url project.property("googlePreviewRepositoryPath") } // path to the local unpacked preview repo
}
configurations {
agp25CompileOnly
}
dependencies {
@@ -37,6 +44,10 @@ dependencies {
compileOnly 'org.codehaus.groovy:groovy-all:2.3.9'
compileOnly 'org.jetbrains.kotlin:gradle-api:2.2'
agp25CompileOnly 'com.android.tools.build:gradle:2.4.0-dev'
agp25CompileOnly 'org.codehaus.groovy:groovy-all:2.3.9'
agp25CompileOnly gradleApi()
testCompile "org.jetbrains.kotlin:kotlin-build-common-test:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
@@ -54,12 +65,21 @@ sourceSets.main.compileClasspath += files(groovyClassesDir)
compileGroovy.classpath = sourceSets.main.compileClasspath - files(groovyClassesDir)
sourceSets.main.java.srcDirs += sourceSets.main.kotlin.srcDirs
sourceSets {
agp25 {
compileClasspath += configurations.compile + configurations.agp25CompileOnly + sourceSets.main.output
}
}
processResources {
expand(project.properties)
}
jar.dependsOn agp25Classes
jar {
from compileGroovy.destinationDir
from sourceSets.agp25.output.classesDir
}
test.executable = "${JDK_18}/bin/java"
@@ -0,0 +1,74 @@
package org.jetbrains.kotlin.gradle.plugin
import com.android.build.gradle.*
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.api.SourceKind
import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.api.UnitTestVariant
import com.android.builder.model.SourceProvider
import org.gradle.api.Project
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.File
@Suppress("unused")
class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools)
: AbstractAndroidProjectHandler<BaseVariant>(kotlinConfigurationTools) {
override fun forEachVariant(project: Project, action: (BaseVariant) -> Unit) {
project.plugins.all { plugin ->
val androidExtension = project.extensions.getByName("android")
var testedExtension: TestedExtension? = null
when (plugin.javaClass) {
AppPlugin::class.java -> {
(androidExtension as AppExtension).applicationVariants.all(action)
testedExtension = androidExtension
}
LibraryPlugin::class.java -> {
(androidExtension as LibraryExtension).libraryVariants.all(action)
testedExtension = androidExtension
}
TestPlugin::class.java -> {
(androidExtension as TestExtension).applicationVariants.all(action)
}
}
testedExtension?.apply {
testVariants.all(action)
unitTestVariants.all(action)
}
}
}
override fun getSourceProviders(variantData: BaseVariant): Iterable<SourceProvider> =
variantData.sourceSets
override fun getAllJavaSources(variantData: BaseVariant): Iterable<File> =
variantData.getSourceFolders(SourceKind.JAVA).map { it.dir }
override fun getVariantName(variant: BaseVariant): String = variant.name
override fun checkVariant(variant: BaseVariant) = Unit
override fun getTestedVariantData(variantData: BaseVariant): BaseVariant? = when (variantData) {
is TestVariant -> variantData.testedVariant
is UnitTestVariant -> variantData.testedVariant as? BaseVariant
else -> null
}
override fun getJavaTask(variantData: BaseVariant): AbstractCompile? =
@Suppress("DEPRECATION") // There is always a Java compile task -- the deprecation was for Jack
variantData.javaCompile
override fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariant, javaSourceDirectory: File) =
variantData.addJavaSourceFoldersToModel(javaSourceDirectory)
override fun configureMultiProjectIc(project: Project,
variantData: BaseVariant,
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?) {
//todo: No easy solution because of the absence of the output information in library modules
// Though it is affordable not to implement this for the first previews, because the impact is tolerable
// to some degree -- the dependent projects will rebuild non-incrementally when a library project changes
}
}
@@ -4,14 +4,12 @@ import com.android.build.gradle.BaseExtension
import com.android.build.gradle.BasePlugin
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.BaseVariantOutputData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.builder.model.SourceProvider
import groovy.lang.Closure
import org.apache.tools.ant.util.ReflectUtil.newInstance
import org.gradle.api.InvalidUserDataException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.ProjectConfigurationException
import org.gradle.api.artifacts.Configuration
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
@@ -33,7 +31,6 @@ import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion
import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper
import java.io.File
import java.net.URL
import java.util.*
@@ -339,11 +336,7 @@ internal open class KotlinAndroidPlugin(
private val kotlinGradleBuildServices: KotlinGradleBuildServices
) : Plugin<Project> {
private val log = Logging.getLogger(this.javaClass)
override fun apply(project: Project) {
val ext = project.extensions.getByName("android") as BaseExtension
val version = loadAndroidPluginVersion()
if (version != null) {
val minimalVersion = "1.1.0"
@@ -352,15 +345,80 @@ internal open class KotlinAndroidPlugin(
}
}
val kotlinTools = KotlinConfigurationTools(
kotlinSourceSetProvider,
tasksProvider,
kotlinPluginVersion,
kotlinGradleBuildServices)
val legacyVersionThreshold = "2.4.0"
val variantProcessor = if (compareVersionNumbers(version, legacyVersionThreshold) < 0)
LegacyAndroidAndroidProjectHandler(kotlinTools)
else
newInstance(
Class.forName("org.jetbrains.kotlin.gradle.plugin.Android25ProjectHandler"),
arrayOf(kotlinTools.javaClass), arrayOf(kotlinTools)) as AbstractAndroidProjectHandler<*>
variantProcessor.handleProject(project)
}
}
class KotlinConfigurationTools internal constructor(val kotlinSourceSetProvider: KotlinSourceSetProvider,
val kotlinTasksProvider: KotlinTasksProvider,
val kotlinPluginVersion: String,
val kotlinGradleBuildServices: KotlinGradleBuildServices)
/** Part of Android configuration, that works only with the old public API.
* @see [LegacyAndroidAndroidProjectHandler] that is implemented with the old internal API and [AndroidGradle25VariantProcessor] that works
* with the new public API */
abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationTools: KotlinConfigurationTools) {
protected val artifactDifferenceRegistryProvider get() =
kotlinConfigurationTools.kotlinGradleBuildServices.artifactDifferenceRegistryProvider
private val logger = Logging.getLogger(this.javaClass)
private fun Project.tryGetSingleArtifact(variantData: BaseVariantData<*>): File? {
val log = logger
log.kotlinDebug { "Trying to determine single artifact for project $path" }
val outputs = variantData.outputs
if (outputs.size != 1) {
log.kotlinDebug { "Output count != 1 for variant: ${outputs.map { it.outputFile.relativeTo(rootDir).path }.joinToString()}" }
return null
}
return variantData.outputs.first().outputFile
}
protected abstract fun forEachVariant(project: Project, action: (V) -> Unit): Unit
protected abstract fun getSourceProviders(variantData: V): Iterable<SourceProvider>
protected abstract fun getAllJavaSources(variantData: V): Iterable<File>
protected abstract fun getVariantName(variant: V): String
protected abstract fun checkVariant(variant: V): Unit
protected abstract fun getTestedVariantData(variantData: V): V?
protected abstract fun getJavaTask(variantData: V): AbstractCompile?
protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: V, javaSourceDirectory: File): Unit
protected abstract fun configureMultiProjectIc(project: Project,
variantData: V,
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?)
fun handleProject(project: Project) {
val ext = project.extensions.getByName("android") as BaseExtension
val aptConfigurations = hashMapOf<String, Configuration>()
ext.sourceSets.all { sourceSet ->
log.kotlinDebug("Creating KotlinSourceSet for source set $sourceSet")
val kotlinSourceSet = kotlinSourceSetProvider.create(sourceSet.name)
logger.kotlinDebug("Creating KotlinSourceSet for source set $sourceSet")
val kotlinSourceSet = kotlinConfigurationTools.kotlinSourceSetProvider.create(sourceSet.name)
kotlinSourceSet.kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin")))
sourceSet.addConvention(KOTLIN_DSL_NAME, kotlinSourceSet)
aptConfigurations.put(sourceSet.name, project.createAptConfiguration(sourceSet.name, kotlinPluginVersion))
aptConfigurations.put(sourceSet.name, project.createAptConfiguration(sourceSet.name, kotlinConfigurationTools.kotlinPluginVersion))
}
val kotlinOptions = KotlinJvmOptionsImpl()
@@ -372,164 +430,129 @@ internal open class KotlinAndroidPlugin(
project.afterEvaluate { project ->
if (project != null) {
val plugin = (project.plugins.findPlugin("android")
?: project.plugins.findPlugin("android-library")
?: project.plugins.findPlugin("com.android.test")) as BasePlugin
?: project.plugins.findPlugin("android-library")
?: project.plugins.findPlugin("com.android.test")) as BasePlugin
val subpluginEnvironment = loadSubplugins(project)
val variantManager = AndroidGradleWrapper.getVariantDataManager(plugin)
processVariantData(variantManager.variantDataList, project,
ext, plugin, aptConfigurations, kotlinOptions)
forEachVariant(project) {
processVariant(it, project, ext, plugin, aptConfigurations, kotlinOptions,
kotlinConfigurationTools.kotlinTasksProvider, subpluginEnvironment)
}
}
}
}
private fun getTestedVariantData(variantData: BaseVariantData<*>): BaseVariantData<*>? =
((variantData as? TestVariantData)?.testedVariantData as? BaseVariantData<*>)
private fun processVariant(variantData: V,
project: Project,
androidExt: BaseExtension,
androidPlugin: BasePlugin,
aptConfigurations: Map<String, Configuration>,
rootKotlinOptions: KotlinJvmOptionsImpl,
tasksProvider: KotlinTasksProvider, subpluginEnvironment: SubpluginEnvironment) {
private fun processVariantData(
variantDataList: List<BaseVariantData<out BaseVariantOutputData>>,
project: Project,
androidExt: BaseExtension,
androidPlugin: BasePlugin,
aptConfigurations: Map<String, Configuration>,
rootKotlinOptions: KotlinJvmOptionsImpl
) {
val logger = project.logger
val subpluginEnvironment = loadSubplugins(project)
checkVariant(variantData)
for (variantData in variantDataList) {
if (AndroidGradleWrapper.isJackEnabled(variantData)) {
throw ProjectConfigurationException(
"Kotlin Gradle plugin does not support the deprecated Jack toolchain.\n" +
"Disable Jack or revert to Kotlin Gradle plugin version 1.1.1.", null)
val variantDataName = getVariantName(variantData)
logger.kotlinDebug("Process variant [$variantDataName]")
val testedVariantData = getTestedVariantData(variantData)
val isAndroidTestVariant = variantDataName.endsWith("androidTest", ignoreCase = true) &&
testedVariantData != null
val javaTask = getJavaTask(variantData)
if (javaTask == null) {
logger.info("KOTLIN: javaTask is missing for $variantDataName, so Kotlin files won't be compiled for it")
return
}
val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin"
// todo: Investigate possibility of creating and configuring kotlinTask before evaluation
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName, variantDataName)
kotlinTask.parentKotlinOptionsImpl = rootKotlinOptions
// store kotlin classes in separate directory. They will serve as class-path to java compiler
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
kotlinTask.description = "Compiles the $variantDataName kotlin."
kotlinTask.setDependsOn(javaTask.dependsOn)
val isKapt3Enabled = Kapt3GradleSubplugin.isEnabled(project)
val aptFiles = arrayListOf<File>()
if (!isKapt3Enabled) {
var hasAnyKaptDependency: Boolean = false
for (provider in getSourceProviders(variantData)) {
val aptConfiguration = aptConfigurations[(provider as AndroidSourceSet).name]
// Ignore if there's only an annotation processor wrapper in dependencies (added by default)
if (aptConfiguration != null && aptConfiguration.allDependencies.size > 1) {
javaTask.dependsOn(aptConfiguration.buildDependencies)
aptFiles.addAll(aptConfiguration.resolve())
hasAnyKaptDependency = true
}
}
val variantDataName = variantData.name
logger.kotlinDebug("Process variant [$variantDataName]")
val testedVariantData = getTestedVariantData(variantData)
val isAndroidTestVariant = variantDataName.endsWith("androidTest", ignoreCase = true) &&
testedVariantData != null
val javaTask = AndroidGradleWrapper.getJavaTask(variantData)
if (javaTask == null) {
logger.info("KOTLIN: javaTask is missing for $variantDataName, so Kotlin files won't be compiled for it")
continue
}
val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin"
// todo: Investigate possibility of creating and configuring kotlinTask before evaluation
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName, variantData.name)
kotlinTask.parentKotlinOptionsImpl = rootKotlinOptions
// store kotlin classes in separate directory. They will serve as class-path to java compiler
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
kotlinTask.description = "Compiles the $variantDataName kotlin."
kotlinTask.setDependsOn(javaTask.dependsOn)
val isKapt3Enabled = Kapt3GradleSubplugin.isEnabled(project)
val aptFiles = arrayListOf<File>()
if (!isKapt3Enabled) {
var hasAnyKaptDependency: Boolean = false
for (provider in variantData.sourceProviders) {
val aptConfiguration = aptConfigurations[(provider as AndroidSourceSet).name]
// Ignore if there's only an annotation processor wrapper in dependencies (added by default)
if (aptConfiguration != null && aptConfiguration.allDependencies.size > 1) {
javaTask.dependsOn(aptConfiguration.buildDependencies)
aptFiles.addAll(aptConfiguration.resolve())
hasAnyKaptDependency = true
}
}
if (!hasAnyKaptDependency) {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
} else {
if (!hasAnyKaptDependency) {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, variantData, null)
kotlinTask.mapClasspath {
javaTask.classpath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
}
var kotlinAfterJavaTask: KotlinCompile? = null
if (javaTask is JavaCompile && aptFiles.isNotEmpty() && !isKapt3Enabled) {
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(variantDataName)
variantData.addJavaSourceFoldersToModel(aptOutputDir)
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName,
aptFiles.toSet(), aptOutputDir, aptWorkingDir, variantData)
kotlinAfterJavaTask = project.initKapt(kotlinTask, javaTask, kaptManager,
variantDataName, rootKotlinOptions, subpluginEnvironment, tasksProvider)
}
for (task in listOfNotNull(kotlinTask, kotlinAfterJavaTask)) {
configureSources(task, variantData)
}
if (isAndroidTestVariant) {
// Android Gradle plugin bypasses the Gradle finalizedBy for its tasks in some cases, and
// the Kotlin classes may not be copied for the tested variant. Make sure they are.
kotlinTask.dependsOn(syncOutputTaskName(testedVariantData!!.name))
}
appliedPlugins
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
.forEach { configureSources(it, variantData) }
configureJavaTask(kotlinTask, javaTask, logger)
createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, variantDataName)
if ((kotlinAfterJavaTask ?: kotlinTask).incremental) {
val artifactFile = project.tryGetSingleArtifact(variantData)
val artifactDifferenceRegistryProvider = ArtifactDifferenceRegistryProviderAndroidWrapper(
kotlinGradleBuildServices.artifactDifferenceRegistryProvider,
{ AndroidGradleWrapper.getJarToAarMapping(variantData) }
)
configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask,
artifactDifferenceRegistryProvider, artifactFile)
}
} else {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, variantData, null)
kotlinTask.mapClasspath {
javaTask.classpath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
}
var kotlinAfterJavaTask: KotlinCompile? = null
if (javaTask is JavaCompile && aptFiles.isNotEmpty() && !isKapt3Enabled) {
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(variantDataName)
addJavaSourceDirectoryToVariantModel(variantData, aptOutputDir)
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName,
aptFiles.toSet(), aptOutputDir, aptWorkingDir, variantData)
kotlinAfterJavaTask = project.initKapt(kotlinTask, javaTask, kaptManager,
variantDataName, rootKotlinOptions, subpluginEnvironment, tasksProvider)
}
for (task in listOfNotNull(kotlinTask, kotlinAfterJavaTask)) {
configureSources(task, variantData)
}
if (isAndroidTestVariant) {
// Android Gradle plugin bypasses the Gradle finalizedBy for its tasks in some cases, and
// the Kotlin classes may not be copied for the tested variant. Make sure they are.
kotlinTask.dependsOn(syncOutputTaskName(getVariantName(testedVariantData!!)))
}
appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
.forEach { configureSources(it, variantData) }
//todo Wire tasks and classpaths with the new API
configureJavaTask(kotlinTask, javaTask, logger)
createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, variantDataName)
configureMultiProjectIc(project, variantData, javaTask, kotlinTask, kotlinAfterJavaTask)
}
private fun configureSources(compileTask: AbstractCompile,
variantData: BaseVariantData<out BaseVariantOutputData>) {
private fun configureSources(compileTask: AbstractCompile, variantData: V) {
val logger = compileTask.project.logger
for (provider in variantData.sourceProviders) {
for (provider in getSourceProviders(variantData)) {
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
compileTask.source(kotlinSourceSet.kotlin)
}
for (javaSrcDir in AndroidGradleWrapper.getJavaSources(variantData)) {
for (javaSrcDir in getAllJavaSources(variantData)) {
compileTask.source(javaSrcDir)
logger.kotlinDebug("Source directory $javaSrcDir was added to kotlin source for ${compileTask.name}")
}
}
private fun Project.tryGetSingleArtifact(variantData: BaseVariantData<*>): File? {
val log = logger
log.kotlinDebug { "Trying to determine single artifact for project $path" }
val outputs = variantData.outputs
if (outputs.size != 1) {
log.kotlinDebug { "Output count != 1 for variant: ${outputs.map { it.outputFile.relativeTo(rootDir).path }.joinToString() }" }
return null
}
return variantData.outputs.first().outputFile
}
private val BaseVariantData<*>.sourceProviders: List<SourceProvider>
get() = variantConfiguration.sortedSourceProviders
}
private fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractCompile, logger: Logger) {
@@ -0,0 +1,82 @@
package org.jetbrains.kotlin.gradle.plugin
import com.android.build.gradle.BasePlugin
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.BaseVariantOutputData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.builder.model.SourceProvider
import org.gradle.api.Project
import org.gradle.api.ProjectConfigurationException
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper
import java.io.File
internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools)
: AbstractAndroidProjectHandler<BaseVariantData<out BaseVariantOutputData>>(kotlinConfigurationTools) {
override fun getSourceProviders(variantData: BaseVariantData<out BaseVariantOutputData>): Iterable<SourceProvider> =
variantData.sourceProviders
override fun getAllJavaSources(variantData: BaseVariantData<out BaseVariantOutputData>): Iterable<File> =
AndroidGradleWrapper.getJavaSources(variantData)
override fun forEachVariant(project: Project, action: (BaseVariantData<out BaseVariantOutputData>) -> Unit) {
val plugin = (project.plugins.findPlugin("android")
?: project.plugins.findPlugin("android-library")
?: project.plugins.findPlugin("com.android.test")) as BasePlugin
val variantManager = AndroidGradleWrapper.getVariantDataManager(plugin)
variantManager.variantDataList.forEach(action)
}
override fun getVariantName(variant: BaseVariantData<out BaseVariantOutputData>): String = variant.name
override fun checkVariant(variant: BaseVariantData<out BaseVariantOutputData>): Unit {
if (AndroidGradleWrapper.isJackEnabled(variant)) {
throw ProjectConfigurationException(
"Kotlin Gradle plugin does not support the deprecated Jack toolchain.\n" +
"Disable Jack or revert to Kotlin Gradle plugin version 1.1.1.", null)
}
}
override fun getJavaTask(variantData: BaseVariantData<out BaseVariantOutputData>): AbstractCompile? =
AndroidGradleWrapper.getJavaTask(variantData)
override fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariantData<out BaseVariantOutputData>,
javaSourceDirectory: File) =
variantData.addJavaSourceFoldersToModel(javaSourceDirectory)
override fun configureMultiProjectIc(project: Project, variantData: BaseVariantData<out BaseVariantOutputData>, javaTask: AbstractCompile, kotlinTask: KotlinCompile, kotlinAfterJavaTask: KotlinCompile?) {
if ((kotlinAfterJavaTask ?: kotlinTask).incremental) {
val artifactFile = project.tryGetSingleArtifact(variantData)
val artifactDifferenceRegistryProvider = ArtifactDifferenceRegistryProviderAndroidWrapper(
artifactDifferenceRegistryProvider,
{ AndroidGradleWrapper.getJarToAarMapping(variantData) }
)
configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask,
artifactDifferenceRegistryProvider, artifactFile)
}
}
override fun getTestedVariantData(variantData: BaseVariantData<*>): BaseVariantData<*>? =
((variantData as? TestVariantData)?.testedVariantData as? BaseVariantData<*>)
private fun Project.tryGetSingleArtifact(variantData: BaseVariantData<*>): File? {
val log = logger
log.kotlinDebug { "Trying to determine single artifact for project $path" }
val outputs = variantData.outputs
if (outputs.size != 1) {
log.kotlinDebug { "Output count != 1 for variant: ${outputs.map { it.outputFile.relativeTo(rootDir).path }.joinToString()}" }
return null
}
return variantData.outputs.first().outputFile
}
private val BaseVariantData<*>.sourceProviders: List<SourceProvider>
get() = variantConfiguration.sortedSourceProviders
}