Search code examples
ioskotlincocoapodskotlin-native

Import Kotlin/Native framework in Cocoapod


I'm trying to add a vendored framework built with Kotlin/Native in a private CocoaPod but I get an error:

  • I have generated an iOS framework with Kotlin/Native.
  • I copy the framework folder (compiled/generated by Konan) into my custom pod folder
  • In the podspec, I add the framework path in the "vendored_frameworks" list
  • I launch pod repo push myCocoapodsRepo myProject.podspec --verbose"
  • I receive an error :

[iOS] xcodebuild: fatal error: lipo: input file (/Users/jeandaube/Library/Developer/Xcode/DerivedData/App-auugdpsmbbpvarfzghxatkvwftsn/Build/Products/Release-iphonesimulator/App.app/Frameworks/MyProject.framework/MyProject) must be a fat file when the -remove option is specified

Should I somehow change the format of how I export the framework with Konan in a first place?


Solution

  • You're getting the error because, by default, Kotlin Native only produces binaries for a single architecture. CocoaPods than fails when it tries to treat it as a "fat" binary with multiple architectures. Since you'll need multiple architectures anyway (at least arm64 for the device and x86_64 for the simulator) the approach I'm using is to create both architectures and then merge them with lipo The resultant fat framework can then be vended by CocoaPods or just drag/drop installed in Xcode.

    def outputDirectory = "$export_dir/$projectName/$projectVersion"
    def outputFramework = "$outputDirectory/${projectName}.framework"
    
    konanArtifacts {
        // Declare building into a framework, build arm64 for device, x64 for simulator                                                      
        framework(projectName, targets: ['ios_arm64', 'ios_x64' ]) {
            // The multiplatform support is disabled by default.                                   
            enableMultiplatform true
        }
    }
    
    // combine original arm64 and x64 libraries into a single library in
    // the exported framework folder
    task combineArchitectures(type: Exec, dependsOn: compileKonanLibrary) {
        executable 'lipo'
        args = [
                '-create',
                '-arch',
                'arm64',
                new File(compileKonanLibraryIos_arm64.artifact, 'Library'),
                '-arch',
                'x86_64',
                new File(compileKonanLibraryIos_x64.artifact, 'Library'),
                '-output',
                "$outputFramework/Library"
        ]
    }
    
    // export the arm64 (doesn't matter which really) framework, skipping
    // the library binary itself
    task exportFramework(type: Copy, dependsOn: compileKonanLibrary) {
        from compileKonanLibraryIos_arm64.artifact
        into outputFramework
        exclude projectName
        finalizedBy combineArchitectures
    }
    
    // build a pod spec by copying and updating a template file
    task exportPodspec(type: Copy) {
        from "Library.podspec"
        into outputDirectory
        filter {
            it.replaceAll('@@projectName@@', projectName)
                .replaceAll('@@projectVersion@@', projectVersion)
        }
    }
    
    task export {
        dependsOn "exportFramework"
        dependsOn "exportPodspec"
    }