How to weaken strongly linked symbols in a mach-o static library? - ios

Our app supports iOS5 however one of our 3rd party static libraries has started strongly linking against iOS6 symbols in UIKit. I'd like to change this linkage to weak and disable the library on iOS5 (assuming the library doesn't use the symbols in load).
I'm looking for something like what I imagine objcopy --weaken-symbol from linux does, so does anyone know of any likely tools or will this involve learning the mach-o format?

I'm none the wiser on mach-o, but I realised that static libraries can't actually decide on how they link against my frameworks. Only I can do that.
So I went into Target > Build Phases > Link Binary With Libraries and set UIKit to Optional. Now the app launches on iOS5 and I can simply (I think!) not call the offending library.
I'm only slightly disappointed I didn't get to write a re-linking tool

Related

Adding multiple static Rust libraries in an iOS app

I have two libraries (with C compatible interface) written in Rust that I'm trying to integrate into an iOS app.
When integrating the two .a files in the same project, I get errors because symbols from the Rust standard library are now present multiple times:
duplicate symbol _rust_eh_personality in:
/Users/x/Development/ios-client/Y/Rust/lib1_ffi.a(lib1_ffi.0.o)
/Users/x/Development/ios-client/Y/Rust/lib2_ffi.a(lib2_ffi.0.o)
...
How can this be solved? Could the Rust symbols be extracted into a separate library? Or can the symbols be namespaced?
At the time of this posting, the prevalent theory is that this issue occurs when Link-Time Optimization (LTO) is enabled and is caused by a bug in the static libraries that rustc produces (link).
As a temporary measure, it has been suggested that LTO should not be enabled until this issue has been resolved.

Can't Use Swift-Generated Shared Framework in Objective-C

This is a variant of the old "dyld: Library not loaded: #rpath/libswiftCore.dylib" problem. I'm pretty sure I know what the issue is, but I don't have any ideas on how to fix it.
I'll reference the project I'm working on, so I don't clutter the question with huge blocks of code.
The project generates a dylib that can be thrown into another project, and abstract a huge block of coding for developers (a communication layer of a client/server system).
I want the framework to be as simple as possible to to use; even if that means making it a big fat pig. I just want people to be able to toss it into their project (Swift or ObjC), and not have to worry about playing around with different variants for things like simulators and devices.
I use a variant of the old Wenderlich script to lipo the executables for x86 and ARM together.
Note the commented-out section. There be draggones.
Works great. In Swift.
Objective-C, not so great. That's because of the various Swift frameworks that need to be carried into the Objective-C program.
I switched on the embed frameworks setting, and the target dutifully gives me all my frameworks.
The problem is that each architecture has frameworks for ONLY that architecture. They aren't "fat" frameworks, so my hand-built "fat" framework really is kinda skinny, because it will only work on certain architectures.
My question is whether or not there's a way to ensure that the Swift frameworks I embed can be made "fat," or if I just have to give up, and package different variants of the framework for Objective-C programmers.
Any ideas?
I'm giving up on this sucker.
You cain't git thar f'm here.
This library will be Swift-only.

iOS App is including ALL symbols from static library

I have a problem that I haven't been able to resolve in regards to when I link my iOS App against one or more static libraries. Here is the issue:
I am creating several static libraries (MACH-O type: Relocatable Object File) each of which contain a large number of symbols. Each of these static libraries are FAT libraries, containing a slice for each iOS/Simulator architecture. From my understanding, when I compile my iOS Application only the symbols that are used by my App should be compiled into and included in my App, however, ALL of the symbols are being included.
I've done some testing using otool, nm, and other tools and can see that when I link against any of these libraries, even if I don't call any of the code in the libraries, ALL of the symbols are being compiled into the App. It takes my App from 42kB all the way to 3+MB.
Any ideas on why this is happening?
Objective-C is a dynamic runtime; it is permissible e.g. to perform:
NSString *classToUse = ["MPViewController" stringByAppendingString:class];
return [[NSClassFromString(classToUse) alloc] init];
... and furthermore this is more or less exactly what happens when you load a NIB — string class and property names are loaded from disk, the backing classes are then found via the runtime and properties applied by key-value coding. So dynamic lookup is not an edge case.
A linker can therefore not make any assumptions about which symbols are used from an Objective-C static library, unlike e.g. a C linker.
Yes,It can be done by stripping static libraries, but if post-processing is enabled. Set Xcode build setting "Deployment Postprocessing" to yes. (DEPLOYMENT_POSTPROCESSING=YES). Also make sure that "Use separate strip" is set to Yes. You can check this
You can also achieve what you are expecting by using Dynamic Library, there is a very nice article here
Extra Tip
* While creating library set Debug Symbols to NO in your build settings. This can reduce the size of your static library by up to 30%.

iOS Static Library | Linking only USED symbols

I am using some third party iOS Static Libraries and am having some trouble keeping the binary size small. The libraries that I am using have an Objective-C interface that is backed by native C/C++ code. The issue is that ALL of the symbols from the library (checked with nm) are being included in my App when linked (even if I don't reference any of the code in the library). This is contrary to my understanding of static libraries where only the code that your application (or other linked libraries) reference is pulled into your application.
I've done a bunch of reading and have found that due to the dynamic nature of Objective-C, there are particular issues that can arise from linking object files or static libraries containing only Objective-C category methods. Because of this, you can pass the -ObjC flag to the linker to have the linker pull in ALL object files containing Objective-C classes or categories. This ensures that all classes and categories are defined at runtime, but bloats your App's binary with unused Objective-C classes/categories/method definitions.
Strangely enough, I am seeing the effects of adding the -ObjC linker flag while not using it anywhere in my build. ALL of the Objective-C symbols are being included, and as a consequence, ALL of the native C/C++ symbols that the Objective-C code references, whether or not my App references any of the code in the library. Has anyone else experienced this problem or found a solution to it?
OS X 10.11.4 and Xcode 7.3.
First, a disclaimer: I haven't personally tried the solution I describe here (all the projects I've worked on just use the -ObjC flag indiscriminately), so YMMV.
That said, this might be of use: https://github.com/CocoaPods/CocoaPods/issues/712
Basically, the idea is, rather than using the -Objc carpet bomb, you can do a slightly more targeted load on a per-library basis: -force_load $(TARGET_BUILD_DIR)/lib<yourLibName>.a.
The author of the referenced link specifically mentions CocoaPods as the culprit for a specific problem he encountered, but I would think (hope) that this solution would apply to the more general question you're asking.
As to the question of why you even have to bother, the only thing I can find that even comes close to an actual explanation can be found here: https://developer.apple.com/library/mac/qa/qa1490/_index.html. This post describes an "impedance mismatch" between Unix (BSD) static libraries and the more dynamic Objective-C based libraries (even static ones) containing e.g. categories. Current linkers can't make the required connections at compile/link time for methods that are essentially bound at runtime, so these linker flags are a workaround to that problem.

BitCode and unexported_symbols_list cannot be used together?

For an iOS Framework, I'd like to be able to hide the symbols inside of it, in order to prevent collisions when the framework, and the application that uses the framework, include different versions of the same 3rd party library.
Until now this has been possible by specifying -unexported_symbols_list in the options.
However, in Xcode 7 Beta 5, the following error message...
-unexported_symbols_list and -bitcode_bundle (Xcode
setting ENABLE_BITCODE=YES) cannot be used together
...occurs when trying to compile the BitCode version of the framework.
So, I have three (3) questions:
1) Is there a straightforward way to hide your symbols when compiling BitCode?
2) If not, is there anything else that can be done to keep the Framework's 3rd-party libraries from colliding with the Application's 3rd-party libraries when they are the same lib, but different versions?
3) Why can't -unexported_symbols_list and -bitcode_bundle be used together?
Partial answer (since I am also looking for the complete answer)
When using -exported_symbols_list or -unexported_symbols_list in the options, the various functions symbols are turned into local symbols.
For some reason, the linker is unable use bitcode option with local symbols.
Hence the two cannot be used together.
Also note, strip keyword which is used for symbol hiding can hide global symbols but the library has to be dynamic.
This is an option I haven't explored completely yet. If a dynamic library works for you, then you should explore it.
If this helps someone get a different perspective as to how to resolve this issue, that would be awesome.

Resources