diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt index 2ad7454f251..d851b12e930 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt @@ -72,6 +72,8 @@ object BinaryOptions : BinaryOptionRegistry() { val enableSafepointSignposts by booleanOption() val packFields by booleanOption() + + val cInterfaceMode by option() } open class BinaryOption( diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CInterfaceGenerationMode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CInterfaceGenerationMode.kt new file mode 100644 index 00000000000..155ccde1ed2 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CInterfaceGenerationMode.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.backend.konan + +/** + * Configure the way C export works for dynamic/static libraries. + */ +enum class CInterfaceGenerationMode { + /** + * Do not generate any C interface. + */ + NONE, + + /** + * Generate C header file the way it is described in + * https://kotlinlang.org/docs/native-dynamic-libraries.html. + * + */ + V1 +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 57630dd088b..3f6498850cb 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -30,6 +30,12 @@ val KonanConfig.isFinalBinary: Boolean get() = when (this.produce) { val CompilerOutputKind.isNativeLibrary: Boolean get() = this == CompilerOutputKind.DYNAMIC || this == CompilerOutputKind.STATIC +/** + * Return true if compiler has to generate a C API for dynamic/static library. + */ +val KonanConfig.produceCInterface: Boolean + get() = this.produce.isNativeLibrary && this.cInterfaceGenerationMode != CInterfaceGenerationMode.NONE + val CompilerOutputKind.involvesBitcodeGeneration: Boolean get() = this != CompilerOutputKind.LIBRARY diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 2dd8e42c1f6..9a583c722fd 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -608,6 +608,15 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration java.io.File(path) } } + + internal val cInterfaceGenerationMode: CInterfaceGenerationMode by lazy { + val explicitMode = configuration.get(BinaryOptions.cInterfaceMode) + when { + explicitMode != null -> explicitMode + produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC -> CInterfaceGenerationMode.V1 + else -> CInterfaceGenerationMode.NONE + } + } } fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt index 6a89955b19e..05af3ea30d2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/DynamicCompilerDriver.kt @@ -78,8 +78,13 @@ internal class DynamicCompilerDriver : CompilerDriver() { private fun produceCLibrary(engine: PhaseEngine, config: KonanConfig, environment: KotlinCoreEnvironment) { val frontendOutput = engine.runFrontend(config, environment) ?: return + val (psiToIrOutput, cAdapterElements) = engine.runPsiToIr(frontendOutput, isProducingLibrary = false) { - it.runPhase(BuildCExports, frontendOutput) + if (config.cInterfaceGenerationMode == CInterfaceGenerationMode.V1) { + it.runPhase(BuildCExports, frontendOutput) + } else { + null + } } require(psiToIrOutput is PsiToIrOutput.ForBackend) val backendContext = createBackendContext(config, frontendOutput, psiToIrOutput) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt index 917a93007fa..661d600c334 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt @@ -93,7 +93,7 @@ internal fun PhaseEngine.runBackend(backendContext: Contex try { backendEngine.useContext(generationState) { generationStateEngine -> val bitcodeFile = tempFiles.create(generationState.llvmModuleName, ".bc").javaFile() - val cExportFiles = if (config.produce.isNativeLibrary) { + val cExportFiles = if (config.produceCInterface) { CExportFiles( cppAdapter = tempFiles.create("api", ".cpp").javaFile(), bitcodeAdapter = tempFiles.create("api", ".bc").javaFile(), @@ -317,7 +317,7 @@ internal fun PhaseEngine.lowerModuleWithDependencies(modu internal fun PhaseEngine.runBackendCodegen(module: IrModuleFragment, cExportFiles: CExportFiles?) { runCodegen(module) - val generatedBitcodeFiles = if (context.config.produce.isNativeLibrary) { + val generatedBitcodeFiles = if (context.config.produceCInterface) { require(cExportFiles != null) val input = CExportGenerateApiInput( context.context.cAdapterExportedElements!!, diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 8255c4e1a73..1e8f5764a5a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -483,7 +483,7 @@ internal class CodeGeneratorVisitor( overrideRuntimeGlobals() appendLlvmUsed("llvm.used", llvm.usedFunctions.map { it.toConstPointer().llvm } + llvm.usedGlobals) appendLlvmUsed("llvm.compiler.used", llvm.compilerUsedGlobals) - if (context.config.produce.isNativeLibrary) { + if (context.config.produceCInterface) { context.cAdapterExportedElements?.let { appendCAdapters(it) } } }