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:
committed by
Alexey Tsvetkov
parent
a5620454fa
commit
eb71dee9cc
@@ -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"
|
||||
|
||||
+74
@@ -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
|
||||
}
|
||||
}
|
||||
+168
-145
@@ -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) {
|
||||
|
||||
+82
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user