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.api.tasks.compile.JavaCompile
import org.gradle.jvm.tasks.Jar import org.gradle.jvm.tasks.Jar
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry 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.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
@@ -42,7 +41,7 @@ import java.util.*
import java.util.concurrent.Callable import java.util.concurrent.Callable
import java.util.jar.Manifest 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" internal const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
val KOTLIN_DSL_NAME = "kotlin" val KOTLIN_DSL_NAME = "kotlin"
val KOTLIN_JS_DSL_NAME = "kotlin2js" val KOTLIN_JS_DSL_NAME = "kotlin2js"
@@ -172,7 +171,7 @@ internal class Kotlin2JvmSourceSetProcessor(
project.afterEvaluate { project -> project.afterEvaluate { project ->
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile } 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( val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, null, null, kotlinCompilation project, kotlinTask, javaTask, null, null, kotlinCompilation
) )
@@ -270,7 +269,7 @@ internal class Kotlin2JsSourceSetProcessor(
kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath
val outputDir = kotlinTask.outputFile.parentFile val outputDir = kotlinTask.outputFile.parentFile
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion) val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions( val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, null, null, null, kotlinCompilation) project, kotlinTask, null, null, null, kotlinCompilation)
@@ -321,7 +320,7 @@ internal class KotlinCommonSourceSetProcessor(
} }
project.afterEvaluate { project -> project.afterEvaluate { project ->
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion) val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions( val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, null, null, null, kotlinCompilation 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 -> forEachVariant(project) { variant ->
val compilation = kotlinAndroidTarget.compilations.getByName(getVariantName(variant)) val compilation = kotlinAndroidTarget.compilations.getByName(getVariantName(variant))
@@ -827,74 +826,6 @@ private fun SourceSet.clearJavaSrcDirs() {
java.setSrcDirs(emptyList<File>()) 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>) { internal fun Task.registerSubpluginOptionsAsInputs(subpluginId: String, subpluginOptions: List<SubpluginOption>) {
// There might be several options with the same key. We group them together // 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: // 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? = fun Project.getKotlinPluginVersion(): String? =
plugins.asSequence().mapNotNull { (it as? KotlinBasePluginWrapper)?.kotlinPluginVersion }.firstOrNull() 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") log.kotlinDebug("Loading version information")
val props = Properties() val props = Properties()
val propFileName = "project.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 org.jetbrains.kotlin.gradle.plugin.SubpluginOption
import java.io.File import java.io.File
internal class CompilerPluginOptions { class CompilerPluginOptions {
private val mutableArguments = arrayListOf<String>() private val mutableArguments = arrayListOf<String>()
internal val subpluginOptionsByPluginId = internal val subpluginOptionsByPluginId =