I've built a static library that I'm my iOS binary is linking in. Code stripping is off, etc. for the static library, and I can see the symbols in the archive (via nm).
So, I link that library into my application as a framework. But, I'm not actually calling that function directly. As a result, I can see the symbols that I'm calling directly in my binary, but not the ones that aren't called. But, since I actually want these symbols to be there at runtime, I'm compiling with -all_load.
But, this seems to place an unnecessary burden on the users of the library. Is there something I can add in the static library that enforces this, rather than relying on the user of the library?
Depending on what you are trying to accomplish, you can precisely control which symbols are dead-stripped and which are always loaded, even if the user of the library doesn't actually use them.
The easiest way is to create a library initialization function that references the exact symbols you don't want dead-stripped. This is precise, and saves you the burden of wrestling with the linker command-line options, which may insulate you from (unlikely) tool behavior changes down the road.
Frameworks have automatic initializers (quite handy) that can be called automatically when the framework is loaded at runtime, right after any static variables are initialized.
__attribute__((constructor))
static void MyModuleInitializer()
{
static BOOL initialized = NO;
if (!initialized) {
// References to symbols that should be kept around.
initialized = YES;
}
}
Just for grins, automatic finalizers are also supported using the __attribute__((destructor)) decorator.
Related
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%.
I did quite a bit of googling for a definitive answer, but I could not find one.
We have cross-platform sources that need to be used by our iOS apps. I have already packaged them as static framework and got a test app to link successfully against and make a call into it.
The problem I am having is that it makes heavy use of global static constructors.
I am seeing erratic behavior with only a subset of objects getting instantiated but not all.
My questions:
Do static constructors even work within the context of an iOS static
lib?
How would one debug such a problem?
Thanks!
constructors in a static library get called erratically
The use of -all_load and -force_load does not make any difference in invocation of constructor attribute labeled functions
What you need to do is this:
make sure the constructors are global symbols. do this by exporting them via a symbols' file.
consider creating an init function and use the linker setting "initialization routine" to control the order of the instantiation of your global objects..
Do static constructors work within the context of an iOS static lib?
They only start to work once they're linked into an executable, but once that is accomplished they will work.
How do you debug such a problem
There are a few approaches
You have to presume no specific order of the invocation of the constructors.
Make sure the constructors are being linked into the executable (use nm to determine this)
You can try an -Wl,-all_load to get it to load all the components of all archives into the executable (or -Wl,-force_load,libstatic.a to just load for a specific static archive).
I am very new to the field of ios programming and working with linker is just a whole new world to me. I would try my best to be precise about my question.
Context: Static library linking in an ios project using xcode.
Problem:
Problem members:
3 static libraries.
libTestLibA.a
libTestLibB.a
libTestLibB_mine.a -- same functionality as libTestLibB.a -- same classes/methods everything.
Problem description
I am making an app using libTestLibA.a.
libTestLibA has some classes that depend on some classes from libTestLibB. Hence libTestLibA.a has libTestLibB.a compiled in itself.
Now, I have my own library named libTestLibB_mine. It has the exact same functionality as that of libTestLibB. Same methods / classes for same functionality. I want libTestLibA to use libTestLibB_mine instead of libTestLibB. I just have compiled static libraries (.a) for each of the problem members , ie, libTestLibA, libTestLibB and libTestLibB_mine.
Question:
When I compile my application, can I force a static compiled library (libTestLibA.a) to make use of another library (libTestLibB_mine.a) instead of what it already contains (libTestLibB.a)? If yes, how? If not, is there some work around?
Much thanks.
If A has already been statically complied against B, then I don't think you can replace B with B_mine. But as a workaround, I think what you might be looking for here is "Method Swizzling". What it does is, at runtime, replace the method of a class with another method (intercept the message and direct it somewhere else).
The following links should be useful to you.
CocoaDev Method Swizzling
JRSwizzle - open source library to make swizzling easier
Be sure to read about the dangers of method swizzling too.
Is there an elegant way (Objective C or C) for my app (jailbroken iOS) to check whether a specific dynamic library is available or not in iOS, other than checking if the actual dylib file exists at a specific path with an NSFileManager or calling dlopen? (e.g., an object that has info about available dynamic libraries that I can access.)
Update: I know I can also make it a requirement in my project settings (Xcode), but then the app just crashes on startup if the dylib isn't available, without any feedback (if there's a way to catch this and do an alert before crashing, that would be an acceptable solution, too).
If you are using weak linking for your dylib, it should be pretty easy to detect if the library is present by checking for a particular symbol.
Say you have a void foo( void ); function in that library.
You can declare that prototype as extern in your own code, and use the weak_import attribute:
extern void foo( void ) __attribute__( ( weak_import ) );
This way, if the symbol is not found (because its not anymore in the library, or because the whole library is not available), the linker will set the address of the symbol to NULL.
You can then simply and elegantly check for that symbol:
if( foo == NULL )
{
/* Alerts the user */
}
else
{
/* It's safe to use foo() */
}
For further reading: Framework Programming Guide
It's my personal opinion that your approach is off. When installing a jailbroken app, most end-users will install it through Cydia/Installer/Icy, which is a wrapper for APT.
When you do finally push your package up to those stores, you can specify package 'dependencies', which will make it so that your app will not be able to be installed at all, let alone be run, without those packages installed.
It's up to you, however, to determine the package which contains the dylib you wish.
There are only a few edge-case scenarios which could cause a missing dylib once installed from APT, namely deleting the libraries, messing with MobileSubstrate settings, and someone downloading your app outside of APT.
However, in this case, the users shouldn't expect your app to work perfectly, seeing as they have been messing around with developer-type things which they probably shouldn't be.
If you're building a commercial iOS SDK that will be included in other people's code and you have third party libraries that you have a license to, is there an effective way to simplify the library / framework structure by not exporting those 3rd party symbols in a static lib?
I appreciate I could instruct developers to check for overlapping symbols, but I'd like to minimize instructions. Ie, just want them to drop the lib into their project and off they go. I also do not want to export my third party symbols as they may change in later projects.
Unfortunately, there isn't a lot to be done here very easily. A static library is just a bunch of .o files glued together. There is no linker step to determine what pieces are actually needed between .o's. That's not done until the final link step (by your customer).
That said, there are some things you can think about:
First, whenever possible, avoid including sub-libraries inside of a static library. This is really dangerous if it's possible for the customer to have other copies of the same sub-library. Your situation seems to be difference since your sub-library is licensed, so the customer is unlikely to have multiple copies, but for example, you should never include a static copy of libcurl in your static library. You must ask the customer to link libcurl themselves, or else things will explode quite badly for them. (See Linking static libraries, that share another static library.) Again, this sounds like it may not apply to you, but keep it in mind if you have common open-source libraries in the mix.
An old-school solution for dealing with visibility is to glue together your compile units. This is a fancy way of saying "concatenate all your .c/.m files into one massive file and compile that." Any function you mark "static" will not be visible outside this compile unit, and so shouldn't be exported. This also happens to increase the possibility of compiler inlining and other optimizations (particularly without fancy link-time optimization) inside of your library.
See Symbol Exporting Strategies. You have several options:
marking symbols as static (probably not possible in this case since they come from a 3rd party)
Use an exported symbols list or an unexported symbols list
Set the visibility attribute of the symbol directly (again, probably not possible in this case)
Use -fvisibility command line option when compiling (probably your best bet here)
Use weak imports
Use a weak library
These are explained at the link above.