This commit is contained in:
Svyatoslav Scherbina
2019-03-27 12:34:42 +03:00
committed by SvyatoslavScherbina
parent e6a391f024
commit 31892bd82e
3 changed files with 55 additions and 4 deletions
@@ -44,6 +44,8 @@ internal class LinkStage(val context: Context) {
private val bitcodeLibraries = context.llvm.bitcodeToLink
private val nativeDependencies = context.llvm.nativeDependenciesToLink
private val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
addAll(elements.filter { !it.isEmpty() })
}
@@ -223,7 +225,7 @@ internal class LinkStage(val context: Context) {
fun makeObjectFiles() {
val bitcodeFiles = listOf(emitted) +
val bitcodeFiles = listOf(emitted) + additionalBitcodeFilesToLink +
bitcodeLibraries.map { it.bitcodePaths }.flatten().filter { it.isBitcode }
objectFiles.add(when (platform.configurables) {
@@ -380,6 +380,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
.filter { (!it.isDefault && !context.config.purgeUserLibs) || imports.bitcodeIsUsed(it) }
}
val additionalProducedBitcodeFiles = mutableListOf<String>()
val staticData = StaticData(context)
private val target = context.config.target
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.getPackageFragments
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
import org.jetbrains.kotlin.backend.konan.getExportedDependencies
import org.jetbrains.kotlin.backend.konan.isNativeBinary
import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator
@@ -15,11 +16,13 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.konan.exec.Command
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.file.createTempFile
import org.jetbrains.kotlin.konan.target.AppleConfigurables
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.isSubpackageOf
@@ -87,6 +90,8 @@ internal class ObjCExport(val context: Context) {
categoryMembers = exportedInterface.categoryMembers,
topLevel = exportedInterface.topLevel
)
exportedInterface.generateWorkaroundForSwiftSR10177()
}
objCCodeGenerator.emitRtti()
@@ -226,6 +231,48 @@ internal class ObjCExport(val context: Context) {
file.writeBytes(contents.toString().toByteArray())
}
// See https://bugs.swift.org/browse/SR-10177
private fun ObjCExportedInterface.generateWorkaroundForSwiftSR10177() {
// Code for all protocols from the header should get into the binary.
// Objective-C protocols ABI is complicated (consider e.g. undocumented extended type encoding),
// so the easiest way to achieve this (quickly) is to compile a stub by clang.
val protocolsStub = listOf(
"__attribute__((used)) static void __workaroundSwiftSR10177() {",
buildString {
append(" ")
generatedClasses.forEach {
if (it.isInterface) {
val protocolName = namer.getClassOrProtocolName(it).objCName
append("@protocol($protocolName); ")
}
}
},
"}"
)
val source = createTempFile("protocols", ".m").deleteOnExit()
source.writeLines(headerLines + protocolsStub)
val bitcode = createTempFile("protocols", ".bc").deleteOnExit()
val clangCommand = context.config.clang.clangC(
source.absolutePath,
"-O2",
"-emit-llvm",
"-c", "-o", bitcode.absolutePath
)
val result = Command(clangCommand).getResult(withErrors = true)
if (result.exitCode == 0) {
context.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath
} else {
// Note: ignoring compile errors intentionally.
// In this case resulting framework will likely be unusable due to compile errors when importing it.
}
}
}
internal fun ModuleDescriptor.guessMainPackage(): FqName {