I have a command-line executable from which I would like to be able load essentially any dynamic library that contains Objective-C classes. In the Project Settings, I have specified that my program supports garbage collection (without requiring it). To this end, I use dlopen to load the libraries, as it’s globally more flexible than NSBundle (first off and most importantly, it can load libraries that aren’t in a bundle).
However, when I try to load a library or framework that requires garbage collection, dlopen fails and I get this message:
Unable to open /path/to/object: dlopen(/path/to/lib, 2): no
suitable image found. Did find:
/path/to/lib: GC capability mismatch
If my program supports garbage collection, why can’t it load libraries that require it? How can I load libraries that require it?
I can’t really flag my executable as requiring garbage collection because it will stop working with libraries that don’t support it.
Right now I have two versions of my executable, but that’s sub-par.
Additional informations: I target Mountain Lion only. My program is a universal binary and it currently handles relaunching as its 32-bits counterpart using the posix_spawn function, however there seems to be no flag controlling garbage collection there.
I found the solution to my problem. The Objective-C runtime has several switches triggered by environment variables, including
OBJC_DISABLE_GCthat can turn off the garbage collector even if the executable wants it on. This switch is taken into account when new images are loaded (seegc_enforcerand how it uses theUseGCstatic variable), so turning the GC off will actually affect the way libraries are loaded into the process.My solution, then, is to implement proper retain/release logic into my executable but compile it with
-fobjc-gc-only. I then try to load the library normally; if it works, everything’s good. If it doesn’t, I programmatically relaunch the process with the same arguments, plusOBJC_DISABLE_GC=YESin its environment, so the GC is disabled and the library successfully loads this time.This snippet excludes error handling.