[klib] Add an option to write out header klibs
The header klib is supposed to only contain the public abi of the module similar to jvm-abi-gen. It is intended to be used as a dependency for other klib compilations instead of the full klib for compilation avoidance. ^KT-60807
This commit is contained in:
+19
-9
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.serializeKlibH
|
||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.Fir2IrOutput
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.FirSerializerInput
|
||||
import org.jetbrains.kotlin.backend.konan.driver.phases.SerializerOutput
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
@@ -34,11 +35,13 @@ internal fun PhaseContext.firSerializer(input: FirOutput): SerializerOutput? = w
|
||||
else -> firSerializerBase(input.firResult, null)
|
||||
}
|
||||
|
||||
internal fun PhaseContext.fir2IrSerializer(input: Fir2IrOutput) = firSerializerBase(input.firResult, input)
|
||||
internal fun PhaseContext.fir2IrSerializer(input: FirSerializerInput) =
|
||||
firSerializerBase(input.firToIrOutput.firResult, input.firToIrOutput, produceHeaderKlib = input.produceHeaderKlib)
|
||||
|
||||
internal fun PhaseContext.firSerializerBase(
|
||||
firResult: FirResult,
|
||||
fir2IrInput: Fir2IrOutput?,
|
||||
produceHeaderKlib: Boolean = false,
|
||||
): SerializerOutput {
|
||||
val configuration = config.configuration
|
||||
val sourceFiles = mutableListOf<KtSourceFile>()
|
||||
@@ -71,6 +74,8 @@ internal fun PhaseContext.firSerializerBase(
|
||||
moduleName = fir2IrInput?.irModuleFragment?.descriptor?.name?.asString()
|
||||
?: firResult.outputs.last().session.moduleData.name.asString(),
|
||||
firFilesAndSessionsBySourceFile,
|
||||
bodiesOnlyForInlines = produceHeaderKlib,
|
||||
skipPrivateApi = produceHeaderKlib,
|
||||
) { firFile, session, scopeSession ->
|
||||
serializeSingleFirFile(
|
||||
firFile,
|
||||
@@ -87,6 +92,7 @@ internal fun PhaseContext.firSerializerBase(
|
||||
additionalAnnotationsProvider = fir2IrInput?.components?.annotationsFromPluginRegistrar?.createMetadataAnnotationsProvider()
|
||||
),
|
||||
configuration.languageVersionSettings,
|
||||
produceHeaderKlib,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -102,14 +108,16 @@ class KotlinFileSerializedData(
|
||||
}
|
||||
|
||||
internal fun PhaseContext.serializeNativeModule(
|
||||
configuration: CompilerConfiguration,
|
||||
messageLogger: IrMessageLogger,
|
||||
files: List<KtSourceFile>,
|
||||
dependencies: List<KonanLibrary>?,
|
||||
moduleFragment: IrModuleFragment?,
|
||||
moduleName: String,
|
||||
firFilesAndSessionsBySourceFile: Map<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>,
|
||||
serializeSingleFile: (FirFile, FirSession, ScopeSession) -> ProtoBuf.PackageFragment
|
||||
configuration: CompilerConfiguration,
|
||||
messageLogger: IrMessageLogger,
|
||||
files: List<KtSourceFile>,
|
||||
dependencies: List<KonanLibrary>?,
|
||||
moduleFragment: IrModuleFragment?,
|
||||
moduleName: String,
|
||||
firFilesAndSessionsBySourceFile: Map<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>,
|
||||
bodiesOnlyForInlines: Boolean = false,
|
||||
skipPrivateApi: Boolean = false,
|
||||
serializeSingleFile: (FirFile, FirSession, ScopeSession) -> ProtoBuf.PackageFragment
|
||||
): SerializerOutput {
|
||||
if (moduleFragment != null) {
|
||||
assert(files.size == moduleFragment.files.size)
|
||||
@@ -126,6 +134,8 @@ internal fun PhaseContext.serializeNativeModule(
|
||||
normalizeAbsolutePaths = absolutePathNormalization,
|
||||
sourceBaseDirs = sourceBaseDirs,
|
||||
languageVersionSettings = configuration.languageVersionSettings,
|
||||
bodiesOnlyForInlines = bodiesOnlyForInlines,
|
||||
skipPrivateApi = skipPrivateApi
|
||||
).serializedIrModule(moduleFragment)
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -225,6 +225,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
|
||||
internal val metadataKlib get() = configuration.get(KonanConfigKeys.METADATA_KLIB)!!
|
||||
|
||||
internal val headerKlibPath get() = configuration.get(KonanConfigKeys.HEADER_KLIB)
|
||||
|
||||
internal val produceStaticFramework get() = configuration.getBoolean(KonanConfigKeys.STATIC_FRAMEWORK)
|
||||
|
||||
internal val purgeUserLibs: Boolean
|
||||
|
||||
+2
@@ -75,6 +75,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("provide manifest addend file")
|
||||
val METADATA_KLIB: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("metadata klib")
|
||||
val HEADER_KLIB: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("path to file where header klib should be produced")
|
||||
val MODULE_NAME: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("module name")
|
||||
val NATIVE_LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||
|
||||
+1
@@ -56,6 +56,7 @@ fun CompilerConfiguration.setupFromArguments(arguments: K2NativeCompilerArgument
|
||||
(arguments.produce ?: "program").uppercase())
|
||||
put(PRODUCE, outputKind)
|
||||
put(METADATA_KLIB, arguments.metadataKlib)
|
||||
putIfNotNull(HEADER_KLIB, arguments.headerKlibPath)
|
||||
|
||||
arguments.libraryVersion?.let { put(LIBRARY_VERSION, it) }
|
||||
|
||||
|
||||
+12
-1
@@ -108,8 +108,15 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
||||
engine.runFirSerializer(frontendOutput)
|
||||
} else {
|
||||
val fir2IrOutput = engine.runFir2Ir(frontendOutput)
|
||||
|
||||
val headerKlibPath = environment.configuration.get(KonanConfigKeys.HEADER_KLIB)
|
||||
if (!headerKlibPath.isNullOrEmpty()) {
|
||||
val headerKlib = engine.runFir2IrSerializer(FirSerializerInput(fir2IrOutput, produceHeaderKlib = true))
|
||||
engine.writeKlib(headerKlib, headerKlibPath)
|
||||
}
|
||||
|
||||
engine.runK2SpecialBackendChecks(fir2IrOutput)
|
||||
engine.runFir2IrSerializer(fir2IrOutput)
|
||||
engine.runFir2IrSerializer(FirSerializerInput(fir2IrOutput))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +131,10 @@ internal class DynamicCompilerDriver : CompilerDriver() {
|
||||
} else {
|
||||
engine.runPsiToIr(frontendOutput, isProducingLibrary = true) as PsiToIrOutput.ForKlib
|
||||
}
|
||||
if (!config.headerKlibPath.isNullOrEmpty()) {
|
||||
val headerKlib = engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput, produceHeaderKlib = true)
|
||||
engine.writeKlib(headerKlib, config.headerKlibPath)
|
||||
}
|
||||
return engine.runSerializer(frontendOutput.moduleDescriptor, psiToIrOutput)
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -10,6 +10,12 @@ import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
|
||||
import org.jetbrains.kotlin.backend.konan.firSerializer
|
||||
import org.jetbrains.kotlin.backend.konan.fir2IrSerializer
|
||||
|
||||
|
||||
internal data class FirSerializerInput(
|
||||
val firToIrOutput: Fir2IrOutput,
|
||||
val produceHeaderKlib: Boolean = false,
|
||||
)
|
||||
|
||||
internal val FirSerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, FirOutput, SerializerOutput?>(
|
||||
"FirSerializer", "Fir serializer",
|
||||
outputIfNotEnabled = { _, _, _, _ -> SerializerOutput(null, null, null, listOf()) }
|
||||
@@ -17,10 +23,10 @@ internal val FirSerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, F
|
||||
context.firSerializer(input)
|
||||
}
|
||||
|
||||
internal val Fir2IrSerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, Fir2IrOutput, SerializerOutput>(
|
||||
internal val Fir2IrSerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, FirSerializerInput, SerializerOutput>(
|
||||
"Fir2IrSerializer", "Fir2Ir serializer",
|
||||
outputIfNotEnabled = { _, _, _, _ -> SerializerOutput(null, null, null, listOf()) }
|
||||
) { context: PhaseContext, input: Fir2IrOutput ->
|
||||
) { context: PhaseContext, input: FirSerializerInput ->
|
||||
context.fir2IrSerializer(input)
|
||||
}
|
||||
|
||||
@@ -31,7 +37,7 @@ internal fun <T : PhaseContext> PhaseEngine<T>.runFirSerializer(
|
||||
}
|
||||
|
||||
internal fun <T : PhaseContext> PhaseEngine<T>.runFir2IrSerializer(
|
||||
fir2irOutput: Fir2IrOutput
|
||||
firSerializerInput: FirSerializerInput
|
||||
): SerializerOutput {
|
||||
return this.runPhase(Fir2IrSerializerPhase, fir2irOutput)
|
||||
return this.runPhase(Fir2IrSerializerPhase, firSerializerInput)
|
||||
}
|
||||
+12
-8
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
internal data class SerializerInput(
|
||||
val moduleDescriptor: ModuleDescriptor,
|
||||
val psiToIrOutput: PsiToIrOutput.ForKlib?,
|
||||
val produceHeaderKlib: Boolean,
|
||||
)
|
||||
|
||||
data class SerializerOutput(
|
||||
@@ -48,24 +49,27 @@ internal val SerializerPhase = createSimpleNamedCompilerPhase<PhaseContext, Seri
|
||||
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||
sourceBaseDirs = relativePathBase,
|
||||
languageVersionSettings = config.languageVersionSettings,
|
||||
bodiesOnlyForInlines = input.produceHeaderKlib,
|
||||
skipPrivateApi = input.produceHeaderKlib,
|
||||
).serializedIrModule(ir)
|
||||
}
|
||||
|
||||
val serializer = KlibMetadataMonolithicSerializer(
|
||||
config.configuration.languageVersionSettings,
|
||||
config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!,
|
||||
config.project,
|
||||
exportKDoc = context.shouldExportKDoc(),
|
||||
!expectActualLinker, includeOnlyModuleContent = true)
|
||||
config.configuration.languageVersionSettings,
|
||||
config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!,
|
||||
config.project,
|
||||
exportKDoc = context.shouldExportKDoc(),
|
||||
!expectActualLinker, includeOnlyModuleContent = true, produceHeaderKlib = input.produceHeaderKlib)
|
||||
val serializedMetadata = serializer.serializeModule(input.moduleDescriptor)
|
||||
val neededLibraries = config.librariesWithDependencies()
|
||||
SerializerOutput(serializedMetadata, serializedIr, null, neededLibraries)
|
||||
}
|
||||
|
||||
internal fun <T : PhaseContext> PhaseEngine<T>.runSerializer(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
psiToIrResult: PsiToIrOutput.ForKlib?,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
psiToIrResult: PsiToIrOutput.ForKlib?,
|
||||
produceHeaderKlib: Boolean = false,
|
||||
): SerializerOutput {
|
||||
val input = SerializerInput(moduleDescriptor, psiToIrResult)
|
||||
val input = SerializerInput(moduleDescriptor, psiToIrResult, produceHeaderKlib)
|
||||
return this.runPhase(SerializerPhase, input)
|
||||
}
|
||||
+14
-7
@@ -14,13 +14,19 @@ import org.jetbrains.kotlin.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.library.KotlinLibraryVersioning
|
||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.util.removeSuffixIfPresent
|
||||
|
||||
internal val WriteKlibPhase = createSimpleNamedCompilerPhase<PhaseContext, SerializerOutput>(
|
||||
internal data class KlibWriterInput(
|
||||
val serializerOutput: SerializerOutput,
|
||||
val customOutputPath: String?
|
||||
)
|
||||
internal val WriteKlibPhase = createSimpleNamedCompilerPhase<PhaseContext, KlibWriterInput>(
|
||||
"WriteKlib", "Write klib output",
|
||||
) { context, input ->
|
||||
val config = context.config
|
||||
val configuration = config.configuration
|
||||
val outputFiles = OutputFiles(config.outputPath, config.target, config.produce)
|
||||
val outputFiles = OutputFiles(input.customOutputPath?.removeSuffixIfPresent(".klib")
|
||||
?: config.outputPath, config.target, config.produce)
|
||||
val nopack = configuration.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val output = outputFiles.klibOutputFileName(!nopack)
|
||||
val libraryName = config.moduleId
|
||||
@@ -51,14 +57,14 @@ internal val WriteKlibPhase = createSimpleNamedCompilerPhase<PhaseContext, Seria
|
||||
(e.g. commonized cinterops, host vs client environment differences).
|
||||
*/
|
||||
val linkDependencies = if (context.config.metadataKlib) emptyList()
|
||||
else input.neededLibraries
|
||||
else input.serializerOutput.neededLibraries
|
||||
|
||||
buildLibrary(
|
||||
natives = config.nativeLibraries,
|
||||
included = config.includeBinaries,
|
||||
linkDependencies = linkDependencies,
|
||||
metadata = input.serializedMetadata!!,
|
||||
ir = input.serializedIr,
|
||||
metadata = input.serializerOutput.serializedMetadata!!,
|
||||
ir = input.serializerOutput.serializedIr,
|
||||
versions = versions,
|
||||
target = target,
|
||||
output = output,
|
||||
@@ -66,12 +72,13 @@ internal val WriteKlibPhase = createSimpleNamedCompilerPhase<PhaseContext, Seria
|
||||
nopack = nopack,
|
||||
shortName = shortLibraryName,
|
||||
manifestProperties = manifestProperties,
|
||||
dataFlowGraph = input.dataFlowGraph
|
||||
dataFlowGraph = input.serializerOutput.dataFlowGraph
|
||||
)
|
||||
}
|
||||
|
||||
internal fun <T : PhaseContext> PhaseEngine<T>.writeKlib(
|
||||
serializationOutput: SerializerOutput,
|
||||
customOutputPath: String? = null,
|
||||
) {
|
||||
this.runPhase(WriteKlibPhase, serializationOutput)
|
||||
this.runPhase(WriteKlibPhase, KlibWriterInput(serializationOutput, customOutputPath))
|
||||
}
|
||||
|
||||
+16
-14
@@ -12,21 +12,23 @@ import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
|
||||
class KonanIrFileSerializer(
|
||||
messageLogger: IrMessageLogger,
|
||||
declarationTable: DeclarationTable,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
bodiesOnlyForInlines: Boolean = false,
|
||||
compatibilityMode: CompatibilityMode,
|
||||
normalizeAbsolutePaths: Boolean,
|
||||
sourceBaseDirs: Collection<String>
|
||||
messageLogger: IrMessageLogger,
|
||||
declarationTable: DeclarationTable,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
bodiesOnlyForInlines: Boolean = false,
|
||||
compatibilityMode: CompatibilityMode,
|
||||
normalizeAbsolutePaths: Boolean,
|
||||
sourceBaseDirs: Collection<String>,
|
||||
skipPrivateApi: Boolean = false,
|
||||
) : IrFileSerializer(
|
||||
messageLogger = messageLogger,
|
||||
declarationTable = declarationTable,
|
||||
compatibilityMode = compatibilityMode,
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
bodiesOnlyForInlines = bodiesOnlyForInlines,
|
||||
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||
sourceBaseDirs = sourceBaseDirs
|
||||
messageLogger,
|
||||
declarationTable,
|
||||
compatibilityMode,
|
||||
languageVersionSettings,
|
||||
skipPrivateApi = skipPrivateApi,
|
||||
bodiesOnlyForInlines = bodiesOnlyForInlines,
|
||||
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||
sourceBaseDirs = sourceBaseDirs
|
||||
) {
|
||||
|
||||
override fun backendSpecificExplicitRoot(node: IrAnnotationContainer): Boolean {
|
||||
|
||||
+5
-1
@@ -15,6 +15,8 @@ class KonanIrModuleSerializer(
|
||||
normalizeAbsolutePaths: Boolean,
|
||||
sourceBaseDirs: Collection<String>,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val bodiesOnlyForInlines: Boolean = false,
|
||||
private val skipPrivateApi: Boolean = false,
|
||||
) : IrModuleSerializer<KonanIrFileSerializer>(messageLogger, compatibilityMode, normalizeAbsolutePaths, sourceBaseDirs) {
|
||||
|
||||
private val globalDeclarationTable = KonanGlobalDeclarationTable(irBuiltIns)
|
||||
@@ -33,5 +35,7 @@ class KonanIrModuleSerializer(
|
||||
compatibilityMode = compatibilityMode,
|
||||
normalizeAbsolutePaths = normalizeAbsolutePaths,
|
||||
sourceBaseDirs = sourceBaseDirs,
|
||||
languageVersionSettings = languageVersionSettings)
|
||||
languageVersionSettings = languageVersionSettings,
|
||||
bodiesOnlyForInlines = bodiesOnlyForInlines,
|
||||
skipPrivateApi = skipPrivateApi)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user