Is it bad to enable Dead Code Stripping? - ios

My iOS project uses dlsym to dynamically point to an optional C library. Optional as-in the project can run with our without it, it just adds features.
For background info: Detect and use optional external C library at runtime in Objective-C
The problem is, XCode cleans up libraries that are "not used". Using dlsym means there are no direct references to my 3rd party library and XCode removes it.
I thought I found a solution, in "Other Linker Flags" I added
-force_load "$(SRCROOT)/my_external.a" which worked great in the simulator. (-all_load works fine too but seemed overkill to me).
The problem is when I moved to a real device, this workaround failed and the library is not loaded (same thing with -all_load).
The only thing that worked was to disable in XCode the feature called Dead Code Stripping.
Question is: is it really bad to disable or recommend my customers to disable this feature? If so, is there a better alternative?

Related

dlopen() dynamic library for iOS Simulator, in macOS application

I have a "fat" framework built for iOS, which is being used in a debugging tool built for macOS. Previously I was linking this framework statically, which worked, even though XCode complains about it being built for the simulator (since the architecture is the same). But now, newer versions of the library are dynamic, so that route doesn't work, as the tool is a command line application, which doesn't support embedding frameworks.
I could turn it into an application bundle, it seems, in order to solve that, but I'm not sure what this entails (creating a new project?). I can certainly figure it out but ..
In the meantime, I thought I'd load the library dynamically using dlopen() etc and retrieve the classes/methods I need (I already have some code for this which at least compiles). However, that call fails with the following message:
no suitable image found. Did find:
/<path to library file>: mach-o, but built for simulator (not macOS)
Since linking statically is only a warning and actually works, is there a way to make dlopen work as well?
Recompiling the framework itself is not an option for me in this situation.
Are you considering editing the binary of the dylib framework? If so in the Macho-O header you could try changing LC_VERSION_MIN_IPHONEOS to LC_VERSION_MIN_MACOSX.Probably it won't be enough,but it's a simple change for a quick test. Here's a screenshot comparison of those load commands in MachOView
Also covered the other way round here

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.

How to replace or resolve __TVOS_PROHIBITED dependencies in unistd.h

I'm trying to compile a dependent libraries from the source code and I've got this error:
/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/usr/include/unistd.h:446:8:
note: 'fork' has been explicitly marked unavailable here pid_t
fork(void) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
Is there any way to resolve this issue?
The thing is that I don't actually even need this functionality. When I compile this code for iOS and run it under tvOS then it works.
But I can not submit the application because it contains code compiled for iOS.
What would be the good trick to substitute there a dummy fork() function so it compiles OK (believing that it is not actually used by my specific use-cases).
I don't believe there is a way round this. You cannot create processes under iOS and tvOS is 90% iOS, so the same restriction applies.
You'll have to conditionally compile-out that section of code for iOS/tvOS.

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.

How can frameworks used by a static library be automatically imported on iOS?

My company makes a static library for iOS apps. One annoying step for developers is that they have to manually link against all the required frameworks that the library uses, and failing to do so leads to somewhat confusing compiler errors.
I would have previously thought this wasn't possible, but the company Chartboost claims to automatically link against non-default frameworks like AdSupport and StoreKit. Based on my testing in their sample app (available from the linked page), so far this appears to be the case (Even when disabling "Enable Modules" and "Link Frameworks Automatically" in the app that links against the static library).
Is there some way to enable this feature when creating a static library? I've tried enabling modules and the "Link Frameworks Automatically" LLVM options in Xcode, but so far haven't been able to get it working.
There's a piece of code called CBDynamicallyLoadedDependencies that calls dlopen() on the appropriate system library before making the function or method call.
My original answer wasn't correct. the dlopen() call is just in the x86 code. On the device, it's something different, but my ARM assembly isn't strong enough to figure it out. All I can say is that there's a piece of code that's acting as a trampoline to the desired functions and that references the system library files (like /System/Library/Frameworks/AdSupport.framework/AdSupport).
But the point is that it's not a simple project trick that makes it work normally. There's internal code involved.
They might use modules you mentioned and #import instead of #import, which should make the libraries link automatically.
For reference, check this question.
This might not be what you're looking for, but if you don't yet support Cocoapods, I would strongly advise taking a look:
http://cocoapods.org/
(Edit: Cocoapods is essentially linked to Xcode. Other IDEs will need another solution.)
You can advertise Cocoapods to developers as the "easy" way to work with your library, and the manual method as...well, the manual method. ;)
I'm not aware of any industry resistance to Cocoapods, so I don't see a downside to supporting it, and it does solve the problem you're talking about (albeit in a roundabout sort of way).
Also I've found Chartboost VERY developer-friendly. You might even reach out to them and ask.

Resources