Add plugin for JVM ABI classes generation
#KT-25128 Fixed ABI class generation is implemented as a compiler plugin. Command-line usage: 1. Add a path to 'jvm-abi-gen.jar' to the plguin classpath argument (`-Xplugin`). By default the jar is located at 'kotlinc/lib/jvm-abi-gen.jar' in the kotlinc distribution archive. 2. Specify an output directory for ABI classes via `-Pplugin:org.jetbrains.kotlin.jvm.abi:outputDir=<DIR>`.
This commit is contained in:
@@ -480,6 +480,7 @@ tasks {
|
||||
":compiler:container:test",
|
||||
":compiler:tests-java8:test",
|
||||
":compiler:tests-spec:remoteRunTests")
|
||||
dependsOn(":plugins:jvm-abi-gen:test")
|
||||
}
|
||||
|
||||
create("jsCompilerTest") {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
description = "ABI generation for Kotlin/JVM"
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":compiler:util"))
|
||||
compileOnly(project(":compiler:cli"))
|
||||
compileOnly(project(":compiler:backend"))
|
||||
compileOnly(project(":compiler:frontend"))
|
||||
compileOnly(project(":compiler:frontend.java"))
|
||||
compileOnly(project(":compiler:plugin-api"))
|
||||
compileOnly(project(":kotlin-build-common"))
|
||||
|
||||
runtimeOnly(project(":kotlin-compiler"))
|
||||
|
||||
testCompile(commonDep("junit:junit"))
|
||||
testCompile(projectTests(":compiler:incremental-compilation-impl"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
projectTest {
|
||||
workingDir = rootDir
|
||||
dependsOn(":dist")
|
||||
}
|
||||
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
dist()
|
||||
publish()
|
||||
|
||||
testsJar()
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
# that can be found in the license/LICENSE.txt file.
|
||||
#
|
||||
|
||||
org.jetbrains.kotlin.jvm.abi.JvmAbiCommandLineProcessor
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
# that can be found in the license/LICENSE.txt file.
|
||||
#
|
||||
|
||||
org.jetbrains.kotlin.jvm.abi.JvmAbiComponentRegistrar
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.jvm.abi
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
||||
import org.jetbrains.kotlin.cli.common.output.writeAll
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.File
|
||||
|
||||
class JvmAbiAnalysisHandlerExtension(
|
||||
private val compilerConfiguration: CompilerConfiguration
|
||||
) : AnalysisHandlerExtension {
|
||||
override fun analysisCompleted(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
bindingTrace: BindingTrace,
|
||||
files: Collection<KtFile>
|
||||
): AnalysisResult? {
|
||||
val bindingContext = bindingTrace.bindingContext
|
||||
if (bindingContext.diagnostics.any { it.severity == Severity.ERROR }) return null
|
||||
|
||||
val targetId = TargetId(
|
||||
name = compilerConfiguration[CommonConfigurationKeys.MODULE_NAME] ?: module.name.asString(),
|
||||
type = "java-production"
|
||||
)
|
||||
|
||||
val generationState = GenerationState.Builder(
|
||||
project,
|
||||
AbiBinaries,
|
||||
module,
|
||||
bindingContext,
|
||||
files.toList(),
|
||||
compilerConfiguration
|
||||
).targetId(targetId).build()
|
||||
KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION)
|
||||
|
||||
val outputDir = compilerConfiguration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)!!
|
||||
generationState.factory.writeAll(
|
||||
outputDir,
|
||||
fun(file: OutputFile, sources: List<File>, output: File) {
|
||||
// todo report
|
||||
}
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private object AbiBinaries : ClassBuilderFactory {
|
||||
override fun getClassBuilderMode(): ClassBuilderMode =
|
||||
ClassBuilderMode.FULL
|
||||
|
||||
override fun newClassBuilder(origin: JvmDeclarationOrigin): ClassBuilder =
|
||||
AbstractClassBuilder.Concrete(ClassWriter(0))
|
||||
|
||||
override fun asText(builder: ClassBuilder): String =
|
||||
throw UnsupportedOperationException("AbiBinaries generator asked for text")
|
||||
|
||||
override fun asBytes(builder: ClassBuilder): ByteArray {
|
||||
val visitor = builder.visitor as ClassWriter
|
||||
return visitor.toByteArray()
|
||||
}
|
||||
|
||||
override fun close() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.jvm.abi
|
||||
|
||||
import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
||||
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
|
||||
class JvmAbiCommandLineProcessor : CommandLineProcessor {
|
||||
companion object {
|
||||
const val COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.jvm.abi"
|
||||
|
||||
val OUTPUT_DIR_OPTION: CliOption =
|
||||
CliOption("outputDir", "<path>", "Output path for the generated files", required = true)
|
||||
}
|
||||
|
||||
override val pluginId: String
|
||||
get() = COMPILER_PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption>
|
||||
get() = listOf(OUTPUT_DIR_OPTION)
|
||||
|
||||
override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
OUTPUT_DIR_OPTION -> configuration.put(JvmAbiConfigurationKeys.OUTPUT_DIR, value)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.optionName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.jvm.abi
|
||||
|
||||
import com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import java.io.File
|
||||
|
||||
class JvmAbiComponentRegistrar : ComponentRegistrar {
|
||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val configuration = configuration.copy()
|
||||
configuration.get(JvmAbiConfigurationKeys.OUTPUT_DIR)?.let {
|
||||
val dir = File(it)
|
||||
configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, dir)
|
||||
}
|
||||
val extension = JvmAbiAnalysisHandlerExtension(configuration)
|
||||
AnalysisHandlerExtension.registerExtension(project, extension)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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.jvm.abi
|
||||
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||
|
||||
object JvmAbiConfigurationKeys {
|
||||
val OUTPUT_DIR: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(JvmAbiCommandLineProcessor.OUTPUT_DIR_OPTION.description)
|
||||
|
||||
}
|
||||
@@ -198,6 +198,7 @@ include ":kotlin-build-common",
|
||||
":libraries:kotlin-prepush-hook",
|
||||
":libraries:tools:mutability-annotations-compat",
|
||||
":include:kotlin-compiler",
|
||||
":plugins:jvm-abi-gen",
|
||||
|
||||
// plugin markers:
|
||||
':kotlin-gradle-plugin:plugin-marker',
|
||||
@@ -335,6 +336,7 @@ project(':examples:scripting-jvm-embeddable-host').projectDir = "$rootDir/librar
|
||||
project(':pill:generate-all-tests').projectDir = "$rootDir/plugins/pill/generate-all-tests" as File
|
||||
project(':kotlin-imports-dumper-compiler-plugin').projectDir = "$rootDir/plugins/imports-dumper" as File
|
||||
project(':libraries:kotlin-prepush-hook').projectDir = "$rootDir/libraries/tools/kotlin-prepush-hook" as File
|
||||
project(':plugins:jvm-abi-gen').projectDir = "$rootDir/plugins/jvm-abi-gen" as File
|
||||
|
||||
// plugin markers:
|
||||
project(':kotlin-gradle-plugin:plugin-marker').projectDir = file("$rootDir/libraries/tools/kotlin-gradle-plugin/plugin-marker")
|
||||
|
||||
Reference in New Issue
Block a user