Kotlin-native: iOS universal binary generation

Created on 24 Jan 2019  路  14Comments  路  Source: JetBrains/kotlin-native

It's not an issue but rather a question.

Are there any plans to implement this as a part of the compiler or is it going to be on users' shoulders?

Most helpful comment

I've published a sample project with my configuration. Some of the things might be already deprecated, but parts of it might be still useful to someone.
https://github.com/endanke/kotlin-mpp-framework-skeleton

All 14 comments

This is frequently asked question, and generally lipo is an instrument used by Apple users to create fat/universal binaries, and it could be used with Kotlin/Native produced binaries. See https://stackoverflow.com/questions/49017793/import-kotlin-native-framework-in-cocoapod for some explanations on how to do that.

Thanks for your answer. Yeah, it's not that hard to use lipo, although it gets tedious when you are dealing with frameworks: you not only have to merge binaries but also merge some keys of Info.plist etc. Also, dSYM bundles have to be merged.

One might argue that Xcode users don't usually have to deal with lipo because Xcode actually merges thin frameworks into fat ones out of the box, it just does it only to binaries built against the same SDK (i.e. only ones for device or ones for simulator). Manual lipo usage is thus left for scenarios like merging device & simulator slices.

To elaborate, Xcode users have to use lipo only if they want to do something "unusual", like merging device & simulator slices. But for iOS devs using Kotlin Native it's something they do on a daily basis, thus it would be nice to have it out of the box in my opinion.

@olonho
Is it possible to use that approach from the StackOverflow answer with the kotlin-multiplatform plugin?
I've only recently started to use it, and if I know it correctly we can't mix the konan andkotlin-multiplatform plugins in the same configuration, however all new iOS sample projects are based on the new plugin.
If I'm wrong, can you show us a sample configuration of using lipo with the kotlin-multiplatform plugin?

I've found the following example to use lipo with kotlin-multiplatform:
Freak5M/OCRParser/build.gradle
So if I understand we need two iOS targets, build them both and combine the output in a new task. My only concern with this approach is if I use an interoped C library in one target, I have to build it in both targets, which increases the build time significantly. For now, I made a separate release task to build both, and for development, I can keep using only the active architecture.

Edit: Since the referenced repository got removed, here's a sample task of combining two frameworks with Gradle. For this configuration we need two iOS targets named as iosArm64 and iosX64. (The XCODE_CONFIGURATION property comes from the multiplatform sample app configuration.)

task combineIosArchitectures(type: Exec) {
    final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
    def frameworkDir = mode == 'DEBUG' ? 'debugFramework' : 'releaseFramework'

    executable 'lipo'
    args = [
            '-create',
            '-arch',  'arm64', buildDir.path + '/bin/iosArm64/' + frameworkDir + '/ProjectName.framework/ProjectName',
            '-arch', 'x86_64', buildDir.path + '/bin/iosX64/' + frameworkDir + '/ProjectName.framework/ProjectName',
            '-output', buildDir.path + "/xcode-frameworks/ProjectName.framework/ProjectName"
    ]
}

@Endanke ,

I am attempting to get this to work, are you saying that we need two preset targets with duplicate code? Or are you building both targets from the same src tree? Would you be willing to share a bit more of your gradle script?

@jonl-percsolutions-com
Check out this issue where we discussed a similar thing: https://github.com/JetBrains/kotlin-native/issues/2718
I'm planning to release a public repository with the configurations. Not sure if I can do it this weekend, but I'll let you know whenever it's available.

For anyone else whom comes across this problem, I found the plugin below that will build the universal library. Even though it was built with cocoapods in mind, it doesn't really require the use of cocoapods to get the universal library to build. https://github.com/AlecStrong/kotlin-native-cocoapods

A similar task will be added to Kotlin 1.3.30. A simple sample showing how to use it is here.

@ilmat192 thanks for sharing this! I'm experiencing an issue though, generated dSYM bundle is invalid:

Screen Shot 2019-04-14 at 10 12 57

The intermediate Info.plist folder shouldn't be there.

~Also it looks like header merging is broken too but I can only reproduce it in my project.~ Never mind this one.

cc @olonho

Thank you! The PR is merged and included in the bugfix branch.

I've published a sample project with my configuration. Some of the things might be already deprecated, but parts of it might be still useful to someone.
https://github.com/endanke/kotlin-mpp-framework-skeleton

Mark

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dpomada picture dpomada  路  3Comments

Marcopohlo picture Marcopohlo  路  4Comments

talanov picture talanov  路  3Comments

jonnyzzz picture jonnyzzz  路  4Comments

nvlizlo picture nvlizlo  路  4Comments