Legoless
Legoless

Reputation: 11112

Merging iOS .dylib into framework with lipo breaks bitcode recompilation

I'm trying to build a dynamic iOS framework manually from .dylib files. Binaries are created with cmake and xcodebuild and produce two .dylib files, one containing armv7, armv7s and arm64 and the other x86_64 and i386 architectures. Libraries are compiled with -fembed-bitcode parameter and everything succeeds.

.dylib files are then merged with next command:

lipo -create lib_arm.dylib lib_i386.dylib -output MyFramework

Framework is then created by copying the output from lipo command to:

MyFramework.framework/MyFramework

Headers and Info.plist are manually generated and added to the framework.

This framework is then installed via CocoaPods into the application as a vendored_framework. It is known that CocoaPods will strip the i386/x86_64 libraries from any fat binaries, for App Store distribution.

Application builds, runs, archives and uploads successfully to App Store.

However, since Bitcode is enabled, App Store will process the .ipa, and recompile with bitcode, this is where it fails and I receive an email from App Store, that it failed processing. Following instructions, I can reproduce the error locally with Exporting for Ad-Hoc Distribution and recompiling for bitcode. The error I receive is this:

ipatool failed with an exception: #<Errno::ENOENT: No such file or directory - /lib_arm.dylib>\n

So apparently during the recompilation, there is still a reference or somewhere to lib_arm.dylib, even though it was merged into a fat dylib Mach-O universal binary (file output of the merged dylib binary below):

>> file MyFramework
MyFramework: Mach-O universal binary with 5 architectures: [x86_64: Mach-O 64-bit dynamically linked shared library x86_64] [i386] [arm_v7] [arm_v7s] [arm64]
MyFramework (for architecture x86_64):  Mach-O 64-bit dynamically linked shared library x86_64
MyFramework (for architecture i386):    Mach-O dynamically linked shared library i386
MyFramework (for architecture armv7):   Mach-O dynamically linked shared library arm_v7
MyFramework (for architecture armv7s):  Mach-O dynamically linked shared library arm_v7s
MyFramework (for architecture arm64):   Mach-O 64-bit dynamically linked shared library arm64

This is pretty much where my compiler/linker knowledge gets out of scope. So my question is:

Where am I going wrong with this? Maybe bitcode should be compiled differently? Or maybe I am using lipo in wrong way?

Thank you!

Upvotes: 1

Views: 2000

Answers (1)

Legoless
Legoless

Reputation: 11112

After inspecting load commands of the created fat binary with otool -l command, I realized that using lipo itself does not change the LC_ID_DYLIB in the binary and it will reuse one from the first provided library. Using install_name_tool to change the id to correct one of the framework (including @rpath for iOS dynamic frameworks) fixes the error.

install_name_tool -id @rpath/MyFramework.framework/MyFramework MyFramework

Make sure the entire path to binary is included, together with .framework directory.

Upvotes: 3

Related Questions