[Gradle] Add APIs that allow AGP to configure Kotlin compilation

Add APIs that describe tasks, so that AGP can configure them. This
change all adds support to *Config objects to support configuring
tasks when there is no access to internal KGP objects.

^KT-50869 In Progress
This commit is contained in:
Ivan Gavrilovic
2022-03-23 18:14:47 +00:00
committed by Space
parent 46cb4902e1
commit ca193a89d2
25 changed files with 1125 additions and 365 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import java.io.File
@@ -73,6 +74,44 @@ open class CompilerPluginConfig {
fun addPluginArgument(pluginId: String, option: SubpluginOption) {
optionsByPluginId.getOrPut(pluginId) { mutableListOf() }.add(option)
}
@Input
fun getAsTaskInputArgs(): Map<String, String> {
val result = mutableMapOf<String, String>()
optionsByPluginId.forEach { (id, subpluginOptions) ->
result += computeForSubpluginId(id, subpluginOptions)
}
return result
}
private fun computeForSubpluginId(subpluginId: String, subpluginOptions: List<SubpluginOption>): Map<String, String> {
// There might be several options with the same key. We group them together
// and add an index to the Gradle input property name to resolve possible duplication:
val result = mutableMapOf<String, String>()
val pluginOptionsGrouped = subpluginOptions.groupBy { it.key }
for ((optionKey, optionsGroup) in pluginOptionsGrouped) {
optionsGroup.forEachIndexed { index, option ->
val indexSuffix = if (optionsGroup.size > 1) ".$index" else ""
when (option) {
is InternalSubpluginOption -> return@forEachIndexed
is CompositeSubpluginOption -> {
val subpluginIdWithWrapperKey = "$subpluginId.$optionKey$indexSuffix"
result += computeForSubpluginId(subpluginIdWithWrapperKey, option.originalOptions)
}
is FilesSubpluginOption -> when (option.kind) {
FilesOptionKind.INTERNAL -> Unit
}.run { /* exhaustive when */ }
else -> {
result["$subpluginId." + option.key + indexSuffix] = option.value
}
}
}
}
return result
}
}
/**
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.KaptExtensionConfig
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtensionConfig
import org.jetbrains.kotlin.gradle.tasks.KaptGenerateStubs
import org.jetbrains.kotlin.gradle.tasks.Kapt
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
/** An API used by third-party plugins to integration with the Kotlin Gradle plugin. */
interface KotlinJvmFactory {
/** Instance of DSL object that should be used to configure KAPT stub generation and annotation processing tasks.*/
val kaptExtension: KaptExtensionConfig
/** Instance of DSL object that should be used to configure Kotlin compilation pipeline. */
val kotlinExtension: KotlinTopLevelExtensionConfig
/** Gets the current version of the Kotlin Gradle plugin. */
val pluginVersion: String
/** Creates instance of DSL object that should be used to configure JVM/android specific compilation. */
fun createKotlinJvmOptions(): KotlinJvmOptions
/** Creates a Kotlin compile task. */
fun registerKotlinJvmCompileTask(taskName: String): TaskProvider<out KotlinJvmCompile>
/** Creates a stub generation task which creates Java sources stubs from Kotlin sources. */
fun registerKaptGenerateStubsTask(taskName: String): TaskProvider<out KaptGenerateStubs>
/** Creates a KAPT task which runs annotation processing. */
fun registerKaptTask(taskName: String): TaskProvider<out Kapt>
/** Adds a compiler plugin dependency to this project. This can be e.g a Maven coordinate or a project included in the build. */
fun addCompilerPluginDependency(dependency: Provider<Any>)
/** Returns a [FileCollection] that contains all compiler plugins classpath for this project. */
fun getCompilerPlugins(): FileCollection
}
@@ -0,0 +1,160 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.Task
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.work.Incremental
import org.gradle.work.NormalizeLineEndings
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.plugin.CompilerPluginConfig
interface KotlinCompileTool : PatternFilterable, Task {
@get:InputFiles
@get:SkipWhenEmpty
@get:NormalizeLineEndings
@get:IgnoreEmptyDirectories
@get:PathSensitive(PathSensitivity.RELATIVE)
val sources: FileCollection
/**
* Sets sources for this task.
* The given sources object is evaluated as per [org.gradle.api.Project.files].
*/
fun source(vararg sources: Any)
/**
* Sets sources for this task.
* The given sources object is evaluated as per [org.gradle.api.Project.files].
*/
fun setSource(vararg sources: Any)
@get:Classpath
@get:NormalizeLineEndings
@get:Incremental
val libraries: ConfigurableFileCollection
@get:OutputDirectory
val destinationDirectory: DirectoryProperty
}
interface BaseKotlinCompile : KotlinCompileTool {
@get:Internal
val friendPaths: ConfigurableFileCollection
@get:NormalizeLineEndings
@get:Classpath
val pluginClasspath: ConfigurableFileCollection
@get:Input
val moduleName: Property<String>
@get:Internal
val sourceSetName: Property<String>
@get:Input
val multiPlatformEnabled: Property<Boolean>
@get:Input
val useModuleDetection: Property<Boolean>
@get:Nested
val pluginOptions: ListProperty<CompilerPluginConfig>
}
interface KotlinJvmCompile : BaseKotlinCompile, KotlinCompile<KotlinJvmOptions> {
// JVM specific
@get:Internal("Takes part in compiler args.")
val parentKotlinOptions: Property<KotlinJvmOptions>
}
interface KaptGenerateStubs : KotlinJvmCompile {
@get:OutputDirectory
val stubsDir: DirectoryProperty
@get:Internal("Not an input, just passed as kapt args. ")
val kaptClasspath: ConfigurableFileCollection
}
interface BaseKapt : Task {
//part of kaptClasspath consisting from external artifacts only
//basically kaptClasspath = kaptExternalClasspath + artifacts built locally
@get:NormalizeLineEndings
@get:Classpath
val kaptExternalClasspath: ConfigurableFileCollection
@get:Internal
val kaptClasspathConfigurationNames: ListProperty<String>
/**
* Output directory that contains caches necessary to support incremental annotation processing.
*/
@get:LocalState
val incAptCache: DirectoryProperty
@get:OutputDirectory
val classesDir: DirectoryProperty
@get:OutputDirectory
val destinationDir: DirectoryProperty
/** Used in the model builder only. */
@get:OutputDirectory
val kotlinSourcesDestinationDir: DirectoryProperty
@get:Nested
val annotationProcessorOptionProviders: MutableList<Any>
@get:Internal
val stubsDir: DirectoryProperty
@get:NormalizeLineEndings
@get:Classpath
val kaptClasspath: ConfigurableFileCollection
@get:Internal
val compiledSources: ConfigurableFileCollection
@get:Internal("Task implementation adds correct input annotation.")
val classpath: ConfigurableFileCollection
/** Needed for the model builder. */
@get:Internal
val sourceSetName: Property<String>
@get:InputFiles
@get:NormalizeLineEndings
@get:IgnoreEmptyDirectories
@get:Incremental
@get:PathSensitive(PathSensitivity.RELATIVE)
val source: ConfigurableFileCollection
@get:Input
val includeCompileClasspath: Property<Boolean>
@get:Internal("Used to compute javac option.")
val defaultJavaSourceCompatibility: Property<String>
}
interface Kapt : BaseKapt {
@get:Input
val addJdkClassesToClasspath: Property<Boolean>
@get:NormalizeLineEndings
@get:Classpath
val kaptJars: ConfigurableFileCollection
}