Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

iOS universal binary generation #2574

Closed
nikolaykasyanov opened this issue Jan 24, 2019 · 14 comments
Closed

iOS universal binary generation #2574

nikolaykasyanov opened this issue Jan 24, 2019 · 14 comments

Comments

@nikolaykasyanov
Copy link

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?

@olonho
Copy link
Contributor

olonho commented Jan 24, 2019

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.

@nikolaykasyanov
Copy link
Author

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.

@olonho olonho closed this as completed Jan 24, 2019
@nikolaykasyanov
Copy link
Author

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.

@endanke
Copy link

endanke commented Jan 31, 2019

@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 and kotlin-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?

@endanke
Copy link

endanke commented Feb 6, 2019

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"
    ]
}

@jonl-percsolutions-com
Copy link

@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?

@endanke
Copy link

endanke commented Mar 30, 2019

@jonl-percsolutions-com
Check out this issue where we discussed a similar thing: #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.

@jonl-percsolutions-com
Copy link

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

@ilmat192
Copy link
Contributor

ilmat192 commented Apr 5, 2019

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

@nikolaykasyanov
Copy link
Author

nikolaykasyanov commented Apr 14, 2019

@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

@nikolaykasyanov
Copy link
Author

nikolaykasyanov commented Apr 14, 2019

Reported: https://youtrack.jetbrains.com/issue/KT-31008.
UPD: and fixed JetBrains/kotlin#2271.

@ilmat192
Copy link
Contributor

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

@endanke
Copy link

endanke commented Apr 16, 2019

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

@fenglh
Copy link

fenglh commented Feb 18, 2021

Mark

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants