Dynamic library image doesn't contain x86_64, i386 architectures - ios

I'm trying to build dynamic library for iOS, combined with architectures
armv7
armv7s
arm64
i386
x86_64
Here is my target's Build Settings
As you can see I've added x86_64 and i386 to Architectures and Valid Architectures, also Build Active Architecture Only is set to NO.
So after building my binary, I'm checking supported architectures by running file myDl.dylib in Terminal
myDl.dylib (for architecture armv7): Mach-O dynamically linked shared library arm
myDl.dylib (for architecture arm64): Mach-O 64-bit dynamically linked shared library
So it means it has been compiled for armv7 and arm64, and dlopen() fails on simulator with error "Unsupported architecture".
What am I doing wrong?
PS. When I use custom build script and use there "lipo" tool to create fat library, it works fine, but I don't like that way, and I want to get it normal working on Xcode.

Set armv7,armv7s and arm64 in valid architecture and make sure if you use any thirdparty framework that must be include 64 bit support.

Related

Optional library with missing simulator architecture

I have a 3rd party static library that hasn't been updated in a long time. As such, it does not include an iPhone simulator build for M1 Macs.
% lipo -info ./Zebra/lib/libZSDK_API.a
Architectures in the fat file: ./Zebra/lib/libZSDK_API.a are: armv7 i386 x86_64 arm64
I tried to set the "Link Binary With Libraries" to be optional for this library so I can still run on the Simulator. (The library is just for printing, and I don't need to print from the Simulator.)
The problem is that even though I have marked the static library as optional, Xcode still gives me a linker error about the missing architecture.
error build: In ../XXXX/External/Zebra/lib/libZSDK_API.a(TcpPrinterConnection.o), building for iOS Simulator, but linking in object file built for iOS, file '../XXXX/External/Zebra/lib/libZSDK_API.a' for architecture arm64
Is there any way to get around this so that Xcode does not fail the build, but just leaves the library unlinked? I thought this was the whole point of the "optional" setting on Link Binary With Libraries?

mach-o, but wrong architecture AFNetworking 3.0

Anybody know about the error “mach-o, but wrong architecture” ? I have built a custom framework(which includes a few other SDK's inside it) & trying to integrate in the client project. I can use/access the custom framework’s methods in the client’s app when I am running in a simulator, but the app is getting crashed while running on the device . Any suggestions will be really helpful. Thanks
Here is the log:-
dyld: Library not loaded: #rpath/AFNetworking.framework/AFNetworking
Referenced from:
/private/var/containers/Bundle/Application/644C95E8-6CFD-48BB-861E-7BCECB08FE43/abc_client.app/Frameworks/XYZ_iOS.framework/XYZ_iOS
Reason: no suitable image found. Did find:
/private/var/containers/Bundle/Application/644C95E8-6CFD-48BB-861E-7BCECB08FE43/abc_client.app/Frameworks/XYZ_iOS.framework/Frameworks/AFNetworking.framework/AFNetworking:
mach-o, but wrong architecture
/private/var/containers/Bundle/Application/644C95E8-6CFD-48BB-861E-7BCECB08FE43/abc_client.app/Frameworks/XYZ_iOS.framework/Frameworks/AFNetworking.framework/AFNetworking:
mach-o, but wrong architecture
When building for the Cocoa platform, Elements allows you to choose to build for different CPU Architectures, depending on the target devices and operating system versions you wish to support. Elements allows the creation of so-called "Universal Binaries", or "Fat Binaries", that can include executable code for more than one platform (for example 32-bit and 64-bit). source
The error means that there are architectures which are missing in your framework.
List an architectures in a framework:
There are two terminal tools:
file
file /path/to/MyFramework.framework/MyFramework source
Example output:
path/to//MyFramework.framework/MyFramework: Mach-O universal binary with 5 architectures
path/to//MyFramework.framework/MyFramework (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
path/to//MyFramework.framework/MyFramework (for architecture i386): Mach-O dynamically linked shared library i386
path/to//MyFramework.framework/MyFramework (for architecture armv7): Mach-O dynamically linked shared library arm
path/to//MyFramework.framework/MyFramework (for architecture armv7s): Mach-O dynamically linked shared library arm
path/to//MyFramework.framework/MyFramework (for architecture arm64): Mach-O 64-bit dynamically linked shared library
lipo
lipo -info /usr/lib/libiodbc.a source
When launching on a device a framework have to include arm64 or
armv7 architecture
When launching on a simulator a framework must
to include x86_64 architecture
Solution
Check if there is any modifications to architectures in Podfile
Check if there is any modifications to the project build settings for a architectures keys.

The Mystery of the Missing Architectures

I'm following a tutorial on building a multi-platform iOS framework -- it mentions these architecture names:
In my Xcode build Settings, I set my architectures like so:
$(ARCHS_STANDARD)
i386
x86_64
arm7s
armv7
armv7s
However, upon building I get the following errors:
Anyone have a clue why?
There is no arm7s, the only one I know of thats similar is armv7s.
Remove the mention of arm7s and try rebuild.
The particular tutorial you're looking at is incorrect. The supported iOS device architectures are:
armv7
armv7s
arm64
For the simulator:
i386
There's an Apple Reference Doc for build settings that makes a mention of some of these. It hasn't been updated since 2010, so theres no armv7s or armv64, but you can see what else has been supported. No mention of arm7, or arm7s.

iOS architectures vs Valid Architectures and repercussions of settings

I have a library that is not 64 bit ready, so I removed arm64 from "architectures". I was then able to use the application on 64 bit platforms in the simulator. (It didn't work until I made that change. It would just crash)
When I was going to create an archive for my app to send to the store, I got the following error:
(null): File is universal (3 slices) but does not contain a(n) armv7s slice: /Users/cmuench/Desktop/PHP-Point-Of-Sale-Repos/PHP-Point-Of-Sale-iOS/PHP Point Of Sale/starSDK/StarIO.framework/StarIO file '/Users/cmuench/Desktop/PHP-Point-Of-Sale-Repos/PHP-Point-Of-Sale-iOS/PHP Point Of Sale/starSDK/StarIO.framework/StarIO' for architecture armv7s
I think this is because the another framework I use I am using for a receipt printer doesn't support armv7s.
3 questions:
Why was it able to work in debugging environment but then fail when creating an archive? The only way I could get the archive to work was by removing armv7s from "valid architectures"
Will my application work on newer hardware that uses the armv7s platform? (I don't have the newer hardware)
What is the difference between "architectures" and "Valid Architectures" in build settings?
In the simulator, the architecture is i386 not armv7 or armv7s. You would only get this error if you tried to run a debug session in a iOS device which had an armv7s chip.
Yes, arm64 and armv7s will run armv7 binaries.
Build Setting Reference describes all the build settings.
ARCHS (Architectures): Space-separated list of identifiers. Specifies the architectures (ABIs, processor models) to which the binary is targeted. When this build setting specifies more than one architecture, the generated binary may contain object code for each of the specified architectures.
VALID_ARCHS (Valid Architectures): Space-separated list of identifiers. Specifies the architectures for which the binary may be built. During the build, this list is intersected with the value of ARCHS build setting; the resulting list specifies the architectures the binary can run on. If the resulting architecture list is empty, the target generates no binary.

Can you make Xcode 5.1 target dependencies build only valid architectures?

With Xcode 5.1 Apple has made $(ARCHS_STANDARD) include arm64. If your project does not support arm64 you can simply change the architecture build setting to $(ARCHS_STANDARD_32_BIT) and it will not build arm64.
However if you have a target dependency that uses $(ARCHS_STANDARD) it will build arm64 and you will get an error because your project is expecting symbols that are not arm64.
Is there a way to make your target dependency aware what you are building against so it will build the valid architecture?
Our quick fix was to leave the Architectures entry as $(ARCHS_STANDARD) but change Valid Architectures to armv7 and armv7s until the third party libraries we're using are updated.

Resources