Hey everyone,
I’m trying to create a reusable SDK for Andriod, and iOS using KMM. For the iOS side, to achieve that, I’d like to compile simulator, and arm versions of the Shared framework and combine them into an xcframework. That xcframework would then be distributed as a pod. You can refer to this blog post for some ideas how that usually works. Unfortunately, this setup is not working for me with KMM frameworks.
To setup this, I’ve started from KMM template and I’ve tweaked the packForXcode
gradle task to separate both build archs:
val packForXcodeArm by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets.getByName<KotlinNativeTarget>("iosArm64").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-framework-arm")
from({ framework.outputDirectory })
into(targetDir)
}
val packForXcodeX64 by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets.getByName<KotlinNativeTarget>("iosX64").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-framework-X64")
from({ framework.outputDirectory })
into(targetDir)
}
I’m then using a plain shell script to create a Shared.xcframework
like this:
./gradlew :shared:packForXCodeArm -PXCODE_CONFIGURATION=Release
./gradlew :shared:packForXCodeX64 -PXCODE_CONFIGURATION=Release
FRAMEWORK_NAME="shared"
ARM64PATH="shared/build/xcode-framework-arm/${FRAMEWORK_NAME}.framework"
X64PATH="shared/build/xcode-framework-X64/${FRAMEWORK_NAME}.framework"
UNIVERSAL_PATH="shared/build/xcode-framework-universal/"
xcodebuild -create-xcframework -framework "${ARM64PATH}" -framework "${X64PATH}" -output "${UNIVERSAL_PATH}/${FRAMEWORK_NAME}.xcframework"
This framework can now be dragged and dropped into a plain Xcode project and everything compiles and links perfectly, runs both on devices and simulator, but when I try to package this as a pod, it’s failing pod spec lint
step, and it fails with ld: framework not found Shared
error on xcode build.
I’ve used ideas from this github issue for my podspec: Is it possible to use a Kotlin/Native framework via CocoaPods from a remote GitHub repository · Issue #3140 · JetBrains/kotlin-native · GitHub, and I’ve disabled arm64 arch for simulator because of this recent issue.
Pod::Spec.new do |spec|
spec.name = 'Shared'
spec.version = '1.0.0'
spec.homepage = 'https://www.shareddemo.com'
spec.source = { :git => 'https://github.com/somerepo/repo.git', :tag => '1.0.0' }
spec.authors = ''
spec.license = { :type => 'MIT', :text => '' }
spec.summary = 'Shared demo pod'
spec.platform = :ios
spec.ios.deployment_target = '9.0'
spec.static_framework = true
spec.vendored_frameworks = "Shared.xcframework"
spec.libraries = "c++"
spec.module_name = "#{spec.name}_umbrella"
spec.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
spec.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
spec.pod_target_xcconfig = {
'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm',
'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86',
'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm',
'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
}
end
This would be a huge pro for iOS adoption if iOS devs can use it as just another pod. I would appreciate any pointers in the right direction on how to achieve this.
Just to note on versions, I’m using the latest version of Android Studio (4.2 preview), Kotlin (1.4.20) / KMM (0.2.0) plugin in, and cocoapods (1.10.0).