Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 347
Jean-Théo Avatar asked Feb 27 '18 20:02

Jean-Théo


2 Answers

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"
}
like image 50
David Berry Avatar answered Sep 27 '22 19:09

David Berry


Kotlin/Native does not produce multiarchitecture (aka fat) binaries (see https://en.wikipedia.org/wiki/Fat_binary) thus an attempt to run lipo on the framework it produces does not make sense.

like image 21
Nikolay Igotti Avatar answered Sep 27 '22 20:09

Nikolay Igotti