From d51e0e0a3030f4a2cdd1a450e85f6f27b787ea07 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 4 Dec 2017 14:50:32 +0300 Subject: [PATCH] Improve produced framework layout on mac --- .../kotlin/backend/konan/LinkStage.kt | 12 ++++++--- .../backend/konan/objcexport/ObjCExport.kt | 25 ++++++++++++++----- .../jetbrains/kotlin/konan/file/NoJavaUtil.kt | 10 ++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index 7f0ba61bca9..38cc69d549d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -338,9 +338,15 @@ internal class LinkStage(val context: Context) { } else { val framework = File(context.config.outputFile) val dylibName = framework.name.removeSuffix(".framework") - frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibName") - framework.mkdirs() - executable = framework.child(dylibName).absolutePath + val dylibRelativePath = when (target) { + KonanTarget.IPHONE, KonanTarget.IPHONE_SIM -> dylibName + KonanTarget.MACBOOK -> "Versions/A/$dylibName" + else -> error(target) + } + frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath") + val dylibPath = framework.child(dylibRelativePath) + dylibPath.parentFile.mkdirs() + executable = dylibPath.absolutePath } val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug, dynamic) + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index b825e744663..7040bbd924f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -42,7 +42,13 @@ internal class ObjCExport(val context: Context) { val mapper = headerGenerator.mapper val framework = File(context.config.outputFile) - val headers = framework.child("Headers") + val frameworkContents = when (target) { + KonanTarget.IPHONE, KonanTarget.IPHONE_SIM -> framework + KonanTarget.MACBOOK -> framework.child("Versions/A") + else -> error(target) + } + + val headers = frameworkContents.child("Headers") val frameworkName = framework.name.removeSuffix(".framework") val headerName = frameworkName + ".h" @@ -50,7 +56,7 @@ internal class ObjCExport(val context: Context) { headers.mkdirs() header.writeLines(headerGenerator.build()) - val modules = framework.child("Modules") + val modules = frameworkContents.child("Modules") modules.mkdirs() val moduleMap = """ @@ -64,17 +70,24 @@ internal class ObjCExport(val context: Context) { modules.child("module.modulemap").writeBytes(moduleMap.toByteArray()) - emitInfoPlist(framework, frameworkName) + emitInfoPlist(frameworkContents, frameworkName) + + if (target == KonanTarget.MACBOOK) { + framework.child("Versions/Current").createAsSymlink("A") + for (child in listOf(frameworkName, "Headers", "Modules", "Resources")) { + framework.child(child).createAsSymlink("Versions/Current/$child") + } + } val objCCodeGenerator = ObjCExportCodeGenerator(CodeGenerator(context), namer, mapper) objCCodeGenerator.emitRtti(headerGenerator.generatedClasses, headerGenerator.topLevel) } - private fun emitInfoPlist(framework: File, name: String) { + private fun emitInfoPlist(frameworkContents: File, name: String) { val directory = when (target) { KonanTarget.IPHONE, - KonanTarget.IPHONE_SIM -> framework - KonanTarget.MACBOOK -> framework.child("Resources").also { it.mkdirs() } + KonanTarget.IPHONE_SIM -> frameworkContents + KonanTarget.MACBOOK -> frameworkContents.child("Resources").also { it.mkdirs() } else -> error(target) } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NoJavaUtil.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NoJavaUtil.kt index 19100f594b3..2b28475dd1e 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NoJavaUtil.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NoJavaUtil.kt @@ -39,6 +39,8 @@ data class File constructor(internal val javaPath: Path) { get() = javaPath.fileName.toString() val parent: String get() = javaPath.parent.toString() + val parentFile: File + get() = File(javaPath.parent) val exists get() = Files.exists(javaPath) @@ -121,6 +123,14 @@ data class File constructor(internal val javaPath: Path) { } } + fun createAsSymlink(target: String) { + val targetPath = Paths.get(target) + if (Files.isSymbolicLink(this.javaPath) && Files.readSymbolicLink(javaPath) == targetPath) { + return + } + Files.createSymbolicLink(this.javaPath, targetPath) + } + override fun toString() = path // TODO: Consider removeing these after konanazing java.util.Properties.