Linking to iOS simulator binaries on OSX - ios

I was curious what would happen if I linked to an iOS simulator framework in a Mac app. So I copied UIKit to it's own folder (so the Framework search path wouldn't include all the iOS simulator framework, as like CoreFoundation is both on Mac and iOS but has different headers), and dragged it into the link section in Xcode. The error Xcode gave me was:
building for MacOSX, but linking against dylib built for iOS Simulator
file '/Users/jonathan/Desktop/macuikit/UIKit.framework/UIKit' for
architecture x86_64
Both architectures are x86_64, so how can it tell the framework is specifically for the iOS simulator, I removed all references to iOS in things like Info.plist, even tried deleted everything but the UIKit binary, but the same error came up. Is there something in the binary it self that tells the linker which platform it can run on, rather than just the architecture? I looked at the Mach-O header but there is only fields for CPU type and subtype, and neither has a value for the simulator as expected.

After a little bit of digging, it turns out that the platform on which the library can run on is indeed specified in the binary. In fact, you can edit the binary in your favorite Hex editor and make the linker skip this check entirely.
This information is not specified in the Mach-O header (as you have already realized). Instead, it is specified as a load command type. You can see the available types by digging through the LLVM sources. Specifically, the enum values LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS look interesting.
Now, find the offset for this in our binary. Open the same in MachOView (or any other editor/viewer or your choice) and note the offset:
Once the offset is noted, jump to the same in a Hex editor and update it. I modified LC_VERSION_MIN_IPHONEOS (25) to LC_VERSION_MIN_MACOSX (24)
Save the updates and try linking again. The error should go away. Of course, you will hit other issues when you try to actually run your example. Have fun with LLDB then :)

Related

Error upon app archive: Found an unexpected Mach-O header code: 0x72613c21

Im trying to archive our app to appstore. But when i do i'm receiving above error.
Platform: iOS
OS version: 14.4.2
Device manufacturer / model: iphone SE
React Native version (react-native -v): 0.64
xcode version: 12.4
I've been in touch with the guy behind the library react-native-background-fetch and asked him about the issue but i'm thinking there is another reason behind the problem.
This is the first time i'm getting this error so i'm not sure what to do.
IDEDistrubution.verbose.log
2021-04-22 14:55:50 +0000 Unable to determine platform from macho "/Users/joakimwennergren/Library/Developer/Xcode/Archives/2021-04-22/ActiveQuiz 2021-04-22, 16.54.xcarchive/Products/Applications/ActiveQuiz.app/ActiveQuiz-mobile-app/node_modules/react-native-background-fetch/ios/RNBackgroundFetch/TSBackgroundFetch.xcframework/ios-arm64_x86_64-maccatalyst/TSBackgroundFetch.framework". Failed with error: "Failed to discover platform for executable /Users/joakimwennergren/Library/Developer/Xcode/Archives/2021-04-22/ActiveQuiz 2021-04-22, 16.54.xcarchive/Products/Applications/ActiveQuiz.app/ActiveQuiz-mobile-app/node_modules/react-native-background-fetch/ios/RNBackgroundFetch/TSBackgroundFetch.xcframework/ios-arm64_x86_64-maccatalyst/TSBackgroundFetch.framework/TSBackgroundFetch"
TL;DR: I made a video to show how to fix the problem https://www.youtube.com/watch?v=Ah9aXs9lTD0 -- the following is a shorter version of the details that are shared in this article: https://christiantietze.de/posts/2021/07/mach-o-0x72613c21-static-library/
Code 0x72613c212 indicates that you are embedding a static library in your app bundle. That's not necessary, because static libraries already are merged with your app binary at build time by the linker.
Usually, .framework bundles are embedded into app bundles and then loaded when you run the app. These are dynamic libs; static libs are already 'in' the app binary, so they don't need to be shipped with the app bundle again. That's why Xcode complains.
How to Diagnose
An Apple Technical Note (TN2435) explains this:
This [Found an unexpected Mach-O header code: 0x72613c21] is caused by placing a static library in a bundle structure that looks like a framework; this packaging is sometimes referred to by third party framework developers as a static framework. Since the binary in these situations is a static library, apps cannot embed it in the app bundle.
From the Technical Note, here's how you can find out if a binary is a static library:
file <PathToAppFramework>/<FrameworkName>.framework/<FrameworkName>
The output could be like:
Mach-O universal binary with 2 architectures
<PathToLibrary> (for architecture armv7): current ar archive random library
<PathToLibrary> (for architecture arm64): current ar archive random library
For dynamic libraries that do need to be embedded in the app, the output instead says something like Mach-O 64-bit dynamically linked shared library x86_64
How to Fix
If your file output looks similar, the solution is to link but not embed:
This will include the static library in the build product right away.

Changing symbol names and embedding bitcode

tl;dr: I get this error message:
ld: -alias_list and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES)
cannot be used together
How do I fix it?
I am trying to create my own version of a third-party library. I want to make sure that none of my calls are going to the system version of this library, so I use --alias-list to put a prefix on all the symbols, and generate a header file which renames all the symbols from foo to MJB_foo. My build system then includes this header file with the --include option whenever I want to use this library.
This works great on Android and Linux (and I'm pretty sure it will eventually work on Windows too). However I get the above error when I try to link the shared library. How do I achieve the same effect?
In Build Settings of project you need to set Enable Bitcode to No. For iOS Apps bitcode is default but optional so you can send the app to AppStore without bitcode.
Bitcode re-optimize your app binary in the future without the need to submit a new version of your app to the App Store.
From Apple Doc:
For iOS apps, bitcode is the default, but optional. For watchOS and tvOS apps, bitcode is required. If you provide bitcode, all apps and frameworks in the app bundle (all targets in the project) need to include bitcode.
https://help.apple.com/xcode/mac/current/#/devbbdc5ce4f
What I have ended up doing is forcing the inclusion of the header full of #defines when building the library, as well as when using it. This allows me to drop --alias-list from the linker command line, so it is happy.
Sadly, this is not the complete solution. The library (it is OpenSSL) has a number of assembler modules, so those have to be patched with sed by the build script first.
It also has some macros which turn
FOO(SHA1)
into
void SHA1_Init(struct SHA1_CTX *ctx)
the problem is that SHA1 is one of the functions I am renaming, so it becomes instead:
void MJB_SHA1_Init(struct MJB_SHA1_CTX *ctx)
renaming the function is harmless (because it turns out it gets renamed uniformly), but I am not renaming the structs. The solution is to create another small file which renames MJB_SHA1_CTX et al back to SHA1_CTX.
*When bitcode is enabled for a target, all the objects, static libraries and user frameworks used when linking that target must contain bitcode.
Otherwise, an error or a warning will be issued by the linker. (Note: missing bitcode is currently a warning for iOS, but it will become an error in an upcoming release of Xcode .)
ENABLE_BITCODE should be consistently turned on for all the targets. If you use a library or framework provided by a third party, please contact the vendor for an updated version which contains bitcode."

How to get CocoaPods-based project to work in the simulator?

I'm trying CocoaPods for the first time, because I've inherited a project that relies on it for several libraries. Articles like this one make it sound like it should all Just Work, even in the simulator.
But it's not working for me — I get an "Undefined symbols for architecture i386" for every class defined in a pod library. Moreover,there are a bunch of ld warnings along the lines of "ld: warning: ignoring file blah/blah/Build/Products/Debug-iphonesimulator/SocketRocket/libSocketRocket.a, file was built for archive which is not the architecture being linked (i386)". I get one of these for each CocoaPods library.
How do I get Xcode to build the pod libraries for the simulator (or link the correct ones, if they're being built)?
OK, I've managed to make it work, though I don't know if it requires both of these steps:
Deleted the derived data, as suggested here
In the Pods project, changed "Build Active Architectures Only" to "No" for Debug as well (it was already set to No for Ad Hoc and Release), as suggested by some of the comments here.
I know that step 1 alone didn't do it... but I don't know whether step 2 by itself would have sufficed. Certainly both of them together did the trick for me.
Adding this answer in case it's helpful to anyone.
To my surprise, it was the simulator version that I was using; iPhone 5 wasn't supported. Xcode gave me no sign of this until I switched to an iPhone 6 simulator, which worked. When switching back to iPhone 5, Xcode then complained that "MyApp does not have an architecture that iPhone 5 can execute."
This is all true and I knew that, but I didn't think of it as the previous error Xcode was giving me was that -lPods-MyApp was missing.

iOS Simulator crashes, device doesn't (dyld: Symbol not found)

it took me some time to solve this so I thought if someone ever searches for it also they might find the solution here.
The problem occurred when I had a framework called CoreUI. This worked fine on my iPhone and iPad but it crashes on the simulator with the following error to the terminal
dyld: Symbol not found: _OBJC_CLASS_$_CUICatalog
Referenced from: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/UIKit.framework/UIKit
Expected in: /Users/sareninden/Library/Developer/Xcode/DerivedData/Treinplanner-bcfwuvntuwetsmavibxtvaiczpfg/Build/Products/Debug-iphonesimulator/CoreUI.framework/CoreUI
in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/UIKit.framework/UIKit
After looking through all the build settings and finding nothing I tried making an empty project with a framework called CoreUI. Without any logic added in it, it crashed with the same error.
It appeared that in the simulator CoreUI is also a framework name used by Apple. Even though it was a swift only framework this still causes conflicts.
This is how DYLD_FRAMEWORK_PATH works. Because you have your own CoreUI.framework in your DYLD_FRAMEWORK_PATH, that one is used instead of the system one to satisfy the linkage from UIKit.framework.
Don't pick framework names that are used by system frameworks, ie:
ls $(xcrun --sdk iphonesimulator --show-sdk-path)/System/Library/*Frameworks
The solution is to not use module names (for your app or framework) that Apple uses. I found a list of frameworks here (https://github.com/jonathanpenn/ui-auto-monkey/issues/8). I do not know if it is complete but it is a good start.

Cordova 3.4, Xcode 5.1 and iOS 7.1

I was building my project perfectly but after updating iOS to 7.1, I was then forced to update Xcode 5.1 and now I'm getting error and warning messages:
4S 7.04 – builds – no error or warning messages
5S 7.1 – doesn’t build – mixture of error and warning messages:
26 x Value conversion issue
Implicit conversion loses integer precision:
12 x Linker build errors
Then I do the steps outlined in this blog post to remove linker errors – delete all conditional architecture and make sure arm64 is in the all the projects and targets: http://shazronatadobe.wordpress.com/2014/03/12/xcode-5-1-and-cordova-ios/
4S 7.04 – builds – warning messages:
12 x Format String Issue
Values of type ‘NSInteger’ should not be used as format arguments; add an explicit cast to ‘long’ instead
5S 7.1 – doesn’t build – warning messages:
26 x Value conversion issue
Implicit conversion loses integer precision:
12 x Format String Issue
Values of type ‘NSInteger’ should not be used as format arguments; add an explicit cast to ‘long’ instead
I think the warning messages are now affecting the badges as they are not reseting correctly
Are the warning messages relevant? And would they likely be affecting resetting the badges?
Okay, so I have gone back and forth with this for a while and I've got a few possible solutions for you.
Make sure in Xcode you are selecting both your project and the target within that project also and make sure your settings are setup like the forum post you mentioned.
Make sure you also change the settings on the CordovaLib project as well. Both the project and the target need to be changed, but it's slightly different. you also need to add i386 as a supported platform in the cordova project, but is not needed in yours.
Other things to check are.... Make sure you are using the right kind of provisioning profile... ie. Distribution for production phone builds and Development for team builds and testing on your device.
Check and make sure you are not missing a library you needed to import. You can usually tell if you are missing a library by the mach-o linker errors though.
Example: I removed a plugin from my phonegap project via command line. Well then I added it back and my project would not build using the 'phonegap build ios' command. I had to open the XCode version of my project within xcode then re-import the AudioToolbox library under the Linked files and then I was able to build again via command line.
Good luck, comment here if you need more help.
Please check my attached images might be it will helpful for you.

Resources