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).
Related
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.
I am currently building a program using GLEW, compiled with MinGW ( in Eclipse ). I built the GLEW libs from the source provided by the GLEW website.
I have been able to use the GLEW declared functions without a problem if I link with the .DLL. However, if I try to link with the static library ( libglew32.a ) with the "GLEW_STATIC" flag defined, I get an error for the function "glewInit()":
undefined reference to `imp_glewInit#0'
If I open up libglew32.a in a hex editor, I can see that there is an entry, but it is named _glewInit#0. So it seems like the disconnect is that my program's compile is trying to append this "imp" string to the front of the function name in the library.
It seems like there must be mis-match of the calling convention here, but I don't know what would cause it yet. There are certainly lots of different ways that GLEW declares the api functions in the header depending on what compiler definitions are set, but I haven't narrowed it down yet.
Any ideas out there?
It looks like that imp prefix gets added for function stubs that are intended to be loaded at runtime from a .DLL. In other words, I wasn't actually staticly linking against GLEW. It turned out that I didn't quite have my eclipse C++ symbols set up correctly, so GLEW_STATIC was not being defined. After making sure that it was set up in the g++ call, it links just fine.
I am working on an iOS app which links several static libraries. The challenge is, those linked libraries define same method names with different implementations. Oddly, I don't get any duplicate symbol definition errors; but, to no surprise, I end up with access to only one implementation of the method.
To be more clear, say I have libA and libB and they both define a global C method called func1()
When I link both libA and libB, and make a call to func1(), it resolves to either libA's or libB's implementation without any compilation warning. I, however, need to be able to access both libA's func1() and libB's func1() separately.
There's a similar SO post that explains how it can be done in C (via symbol renaming) but unfortunately, as I found out, objcopy tool doesn't work for ARM architecture (hence iPhone).
(I will submit it to the App Store, hence, dynamic linking is not an option)
It appears that you are in luck - you can still rename symbols with the ARM binary format, it's just a bit more hacky than the objcopy method...
NOTE: This has only been tested minimally, and I would strongly advise you to make a backup of all libraries in question before trying this!
Also note that this only works for files not compiled with the C++ compiler! This will fail if the C++ compiler was used on these files.
First, you will need a decent hex editor, for this example, I will be using Hex Fiend.
Next, you will open up a copy of your of of your libraries, let's call it lib1-renamed.a, and do the following with it:
Find the name of the symbol you wish to re-name. It can be found using the nm tool, or, if you know the header name, you should be set.
Next, you will use hex fiend, and to a textual replace of the old name (in this case foo), and give it a new name (in this case, bar). These names must have the same length, or it will corrupt the binary's offsets!
Note: if there is more than one function that contain's foo's name in it, you may have problems.
Now, you must edit the headers of the library you changed, to use the new function name (bar) instead of the old one.
If you have done the three simple† steps above properly, you should now be able to compile & link the two files successfully, and call both implementations.
If you are trying to do this with a universal binary (e.g. one the works on the simulator as well), you'd be best off using lipo to separate the two binaries, using objcopy on the i386/x64 binary, and then using my method on the ARM binary, and lipo it back together.
†: Simplicity is not guaranteed, nor is it covered by the Richard J. Ross III super warranty. For more information about the super warranty, call 1-800-FREE-WARRANTY now. That's 1-800-FREE-WARRANTY now!
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.
Can you use macros defined in static libraries?
I have my own debug macro called TWDEBUG that I use in a static library I create for sharing.
If I import the static library to my new project and use it, the compiler does not seem to recognize it. I did set up preprocessor macros to TWDEBUG and Other C flags and Other C++ flags to -TWDEBUG, but when I ran the code the ifdef macro doesn't get executed.
Macros are evaluated at compile-time. So their values are frozen when you build the static library. For debugging statement, this usually means that they are omitted and not part of the built library.
If you later add the static library to a project, you can change the value of the macros. But it won't have any effect on the static library since it is not compiled anymore. The debugging statements are missing.
Update:
So to implement a debug option, I see two options:
Instead of macros and ifdefs, you use a global variable and proper ifs to turn debugging on and off. Other developers can use an API (global function) to set the debugging level so you can hide the global variable.
Create two static library from the same source code, one with debugging enabled for development purposes and the other with debugging disabled for production use. This option is probably only viable if XCode can automatically switch between the two libraries. And at the moment, I don't know how you would configure that.