Attempt to make loading of compiler plugins from kotlin-platform-native Gradle plugin

Moved SubpluginEnviroment to separate file and made public some methods
KotlinNativeCompile task now extends AbstractCompile so it could be passed to SubpluginEnviroment.loadSubplugins
KotlinNativeBasePlugin now declares kotlinCompilerPluginClasspath configuration
This commit is contained in:
Leonid Startsev
2018-08-10 19:26:02 +03:00
parent 494828f4cf
commit 0ac969a617
4 changed files with 102 additions and 76 deletions
@@ -22,7 +22,6 @@ import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.jvm.tasks.Jar
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
@@ -42,7 +41,7 @@ import java.util.*
import java.util.concurrent.Callable
import java.util.jar.Manifest
internal const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath"
internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
val KOTLIN_DSL_NAME = "kotlin"
val KOTLIN_JS_DSL_NAME = "kotlin2js"
@@ -172,7 +171,7 @@ internal class Kotlin2JvmSourceSetProcessor(
project.afterEvaluate { project ->
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, null, null, kotlinCompilation
)
@@ -270,7 +269,7 @@ internal class Kotlin2JsSourceSetProcessor(
kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath
val outputDir = kotlinTask.outputFile.parentFile
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, null, null, null, kotlinCompilation)
@@ -321,7 +320,7 @@ internal class KotlinCommonSourceSetProcessor(
}
project.afterEvaluate { project ->
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, null, null, null, kotlinCompilation
)
@@ -678,7 +677,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
)
}
val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
forEachVariant(project) { variant ->
val compilation = kotlinAndroidTarget.compilations.getByName(getVariantName(variant))
@@ -827,74 +826,6 @@ private fun SourceSet.clearJavaSrcDirs() {
java.setSrcDirs(emptyList<File>())
}
private fun loadSubplugins(project: Project, kotlinPluginVersion: String): SubpluginEnvironment =
try {
val klass = KotlinGradleSubplugin::class.java
val buildscriptClassloader = project.buildscript.classLoader
val klassFromBuildscript = try {
buildscriptClassloader.loadClass(klass.canonicalName)
} catch (e: ClassNotFoundException) {
null
}
val classloader = if (klass == klassFromBuildscript) {
buildscriptClassloader
} else {
klass.classLoader
}
val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, classloader)
.map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin<AbstractCompile>) }
SubpluginEnvironment(subplugins, kotlinPluginVersion)
} catch (e: NoClassDefFoundError) {
// Skip plugin loading if KotlinGradleSubplugin is not defined.
// It is true now for tests in kotlin-gradle-plugin-core.
project.logger.error("Could not load subplugins", e)
SubpluginEnvironment(listOf(), kotlinPluginVersion)
}
internal class SubpluginEnvironment(
private val subplugins: List<KotlinGradleSubplugin<AbstractCompile>>,
private val kotlinPluginVersion: String
) {
fun <C: CommonCompilerArguments> addSubpluginOptions(
project: Project,
kotlinTask: AbstractKotlinCompile<C>,
javaTask: AbstractCompile?,
variantData: Any?,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>?,
kotlinCompilation: KotlinCompilation?
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> {
val pluginOptions = kotlinTask.pluginOptions
val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) }
for (subplugin in appliedSubplugins) {
if (!subplugin.isApplicable(project, kotlinTask)) continue
val pluginId = subplugin.getCompilerPluginId()
project.logger.kotlinDebug { "Loading subplugin $pluginId" }
val artifact = subplugin.getPluginArtifact()
val artifactVersion = artifact.version ?: kotlinPluginVersion
val mavenCoordinate = "${artifact.groupId}:${artifact.artifactId}:$artifactVersion"
project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$PLUGIN_CLASSPATH_CONFIGURATION_NAME' configuration" }
project.dependencies.add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, mavenCoordinate)
val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation)
val subpluginId = subplugin.getCompilerPluginId()
kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
for (option in subpluginOptions) {
pluginOptions.addPluginArgument(subpluginId, option)
}
project.logger.kotlinDebug("Subplugin $pluginId loaded")
}
return appliedSubplugins
}
}
internal fun Task.registerSubpluginOptionsAsInputs(subpluginId: String, subpluginOptions: List<SubpluginOption>) {
// 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:
@@ -148,7 +148,7 @@ open class KotlinMultiplatformPluginWrapper @Inject constructor(
fun Project.getKotlinPluginVersion(): String? =
plugins.asSequence().mapNotNull { (it as? KotlinBasePluginWrapper)?.kotlinPluginVersion }.firstOrNull()
private fun Any.loadKotlinVersionFromResource(log: Logger): String {
fun Plugin<*>.loadKotlinVersionFromResource(log: Logger): String {
log.kotlinDebug("Loading version information")
val props = Properties()
val propFileName = "project.properties"
@@ -0,0 +1,95 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
import java.util.*
class SubpluginEnvironment(
private val subplugins: List<KotlinGradleSubplugin<AbstractCompile>>,
private val kotlinPluginVersion: String
) {
companion object {
fun loadSubplugins(project: Project, kotlinPluginVersion: String): SubpluginEnvironment =
try {
val klass = KotlinGradleSubplugin::class.java
val buildscriptClassloader = project.buildscript.classLoader
val klassFromBuildscript = try {
buildscriptClassloader.loadClass(klass.canonicalName)
} catch (e: ClassNotFoundException) {
null
}
val classloader = if (klass == klassFromBuildscript) {
buildscriptClassloader
} else {
klass.classLoader
}
val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, classloader)
.map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin<AbstractCompile>) }
SubpluginEnvironment(subplugins, kotlinPluginVersion)
} catch (e: NoClassDefFoundError) {
// Skip plugin loading if KotlinGradleSubplugin is not defined.
// It is true now for tests in kotlin-gradle-plugin-core.
project.logger.error("Could not load subplugins", e)
SubpluginEnvironment(listOf(), kotlinPluginVersion)
}
}
fun <C : CommonCompilerArguments> addSubpluginOptions(
project: Project,
kotlinTask: AbstractKotlinCompile<C>,
javaTask: AbstractCompile? = null,
variantData: Any? = null,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>? = null,
kotlinCompilation: KotlinCompilation? = null
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> = addSubpluginOptions(
project,
kotlinTask,
kotlinTask.pluginOptions,
javaTask,
variantData,
androidProjectHandler,
kotlinCompilation
)
fun <C : CommonCompilerArguments> addSubpluginOptions(
project: Project,
kotlinTask: AbstractCompile,
pluginOptions: CompilerPluginOptions,
javaTask: AbstractCompile? = null,
variantData: Any? = null,
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>? = null,
kotlinCompilation: KotlinCompilation? = null
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> {
val appliedSubplugins = subplugins.filter { it.isApplicable(project, kotlinTask) }
for (subplugin in appliedSubplugins) {
if (!subplugin.isApplicable(project, kotlinTask)) continue
val pluginId = subplugin.getCompilerPluginId()
project.logger.kotlinDebug { "Loading subplugin $pluginId" }
val artifact = subplugin.getPluginArtifact()
val artifactVersion = artifact.version ?: kotlinPluginVersion
val mavenCoordinate = "${artifact.groupId}:${artifact.artifactId}:$artifactVersion"
project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$PLUGIN_CLASSPATH_CONFIGURATION_NAME' configuration" }
project.dependencies.add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, mavenCoordinate)
val subpluginOptions =
subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation)
val subpluginId = subplugin.getCompilerPluginId()
kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
for (option in subpluginOptions) {
pluginOptions.addPluginArgument(subpluginId, option)
}
project.logger.kotlinDebug("Subplugin $pluginId loaded")
}
return appliedSubplugins
}
}
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.gradle.tasks
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
import java.io.File
internal class CompilerPluginOptions {
class CompilerPluginOptions {
private val mutableArguments = arrayListOf<String>()
internal val subpluginOptionsByPluginId =