.objc_class_name stripped by dead code stripping
.objc_class_name stripped by dead code stripping
- Subject: .objc_class_name stripped by dead code stripping
- From: Greg Hurrell <email@hidden>
- Date: Sun, 6 Aug 2006 23:42:25 +0200
I have an application and a bundle of unit tests. When building the
test bundle I would like to use the BUNDLE_LOADER build setting to
tell the linker to look in the application executable for undefined
symbols.
The trouble is that performing dead code stripping on the application
strips away the symbols that the bundle needs (symbols like
".objc_class_name_MYClass"). Is there any way to set the visibility
flag on only those symbols? I know I can use the following for
functions and other symbols, but I have not been able to find a way
to apply it to Objective-C classes:
__attribute__((visibility("default")))
I have tried every combination that I can think of without success. I
know that the docs say that:
"Objective-C class and message names are bound by the Objective-C
runtime, not by the linker, so the notion of visibility does not
apply to them. There is no mechanism for hiding an Objective-C class
defined in a dynamic library from the clients of that library."
But this doesn't seem to be true; there is a mechanism and that
mechanism is dead-code stripping. If you use "nm" to compare an
executable built with and without dead code stripping you'll see that
the former has the .objc_class_name symbols stripped.
There are workarounds but none of them are ideal:
1. Turn off dead-code stripping (throwing the baby out with the bath
water).
2. Enclosing the entire class implementation with pragmas (no effect):
#pragma GCC visibility push(default)
#pragma GCC visibility pop
3. Enclosing the entire class interface with the same pragmas (no
effect).
4. Pass "-undefined dynamic_lookup" when linking the bundle (the
problem with this is it is too aggressive and applies to all symbols,
not just the ones which got stripped by dead-code stripping, meaning
what should be link-time errors could turn into nastier run-time
errors).
5. Use the EXPORTED_SYMBOLS_FILE build setting (you have to include
lots of symbols in the file, not just the class symbols, or you'll
get lots of linker warnings).
6. Build the app without dead code stripping, build the bundle, then
re-build the app with code stripping (too time consuming for complex
apps and horribly kludgy to boot).
7. Specify symbols that are ok to be undefined using "-Wl,-
U,symbol" (not allowed with two-level namespaces and unworkable for
large numbers of symbols).
8. Apply "-fvisibility=default" compiler flags to specific files in
the app (applies to entire files, not just class symbols; and doesn't
work anyway... dead code stripping still wipes out the class names).
It could be argued that this is all moot because unit tests occur
during development, and development is often done without linking
(thanks to ZeroLink) so these linking problems go away, but that's
not true in this instance: these unit tests are designed to be
shipped to customers along with release builds so that customers can
verify on-site that everything works as it should. For now I am going
with option "4" above but I don't like it; I'd much rather figure out
how to selectively enforce visibility on class symbols only.
Here are all my build settings related to symbols, linking and
stripping, but I have tried toggling them all one by one and the only
one which seems to break BUNDLE_LOADER is DEAD_CODE_STRIPPING:
DEBUG_INFORMATION_FORMAT = stabs
DEAD_CODE_STRIPPING = YES
GCC_GENERATE_DEBUGGING_SYMBOLS = YES
GCC_DEBUGGING_SYMBOLS = full
DEPLOYMENT_POSTPROCESSING = YES
SKIP_INSTALL = NO
STRIP_INSTALLED_PRODUCT = NO
SEPARATE_STRIP = NO
STRIP_STYLE = all
GCC_SYMBOLS_PRIVATE_EXTERN = YES
GCC_INLINES_ARE_PRIVATE_EXTERN = YES
ONLY_LINK_ESSENTIAL_SYMBOLS = NO
KEEP_PRIVATE_EXTERNS = NO
GCC_ENABLE_SYMBOL_SEPARATION = YES
Cheers,
Greg
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden