[K2/N] Compile to native binary in two stages

^KT-56855 Fixed

Merge-request: KT-MR-10219
Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
Vladimir Sukharev
2023-05-24 13:07:12 +00:00
committed by Space Team
parent 62901e22ec
commit 74c57e6057
3 changed files with 43 additions and 19 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
@@ -26,11 +27,14 @@ import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.ir.linkage.partial.partialLinkageConfig
import org.jetbrains.kotlin.ir.linkage.partial.setupPartialLinkageConfig
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.util.profile
import org.jetbrains.kotlin.utils.KotlinPaths
import java.nio.file.Files
private class K2NativeCompilerPerformanceManager: CommonCompilerPerformanceManager("Kotlin to Native Compiler")
@@ -64,7 +68,42 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
if (!enoughArguments) {
messageCollector.report(ERROR, "You have not specified any compilation arguments. No output has been produced.")
}
if(configuration.get(KonanConfigKeys.PRODUCE) != CompilerOutputKind.LIBRARY &&
configuration.getBoolean(CommonConfigurationKeys.USE_FIR) &&
configuration.kotlinSourceRoots.isNotEmpty()) {
// K2/Native backend cannot produce binary directly from FIR frontend output, since descriptors, deserialized from KLib, are needed
// So, such compilation is split to two stages:
// - source files are compiled to intermediate KLib by FIR frontend
// - intermediate Klib is compiled to binary by K2/Native backend
// In this implementation, 'arguments' is not changed accordingly to changes in `firstStageConfiguration` and `configuration`,
// since values of fields `produce`, `output`, `freeArgs`, `includes` does not seem to matter downstream in prepareEnvironment()
val firstStageConfiguration = configuration.copy()
// For the first stage, use "-p library" produce mode
firstStageConfiguration.put(KonanConfigKeys.PRODUCE, CompilerOutputKind.LIBRARY)
// For the first stage, construct a temporary file name for an intermediate KLib
val originalOutput = firstStageConfiguration.get(KonanConfigKeys.OUTPUT)
val intermediateKLib = Files.createTempFile(File(originalOutput ?: "intermediate").name, ".klib").toString()
firstStageConfiguration.put(KonanConfigKeys.OUTPUT, intermediateKLib)
val firstStageExitCode = executeStage(firstStageConfiguration, arguments, rootDisposable)
if (firstStageExitCode != ExitCode.OK)
return firstStageExitCode
// For the second stage, remove already compiled source files from the configuration
configuration.put(CLIConfigurationKeys.CONTENT_ROOTS, listOf())
// For the second stage, provide just compiled intermediate KLib as "-Xinclude=" param
configuration.put(KonanConfigKeys.INCLUDED_LIBRARIES, listOf(intermediateKLib))
// Now, `configuration` param is prepared for the second stage of compilation, and `arguments` param does not need changes, as noted above.
}
return executeStage(configuration, arguments, rootDisposable)
}
private fun executeStage(
configuration: CompilerConfiguration,
arguments: K2NativeCompilerArguments,
rootDisposable: Disposable
): ExitCode {
val environment = prepareEnvironment(arguments, configuration, rootDisposable)
try {