This demonstrates how the linker treats unused code. Toggle DEAD_STRIP
and USE_STATIC_LIB
to compare different results.
DEAD_STRIP=0 USE_STATIC_LIB=1 ./build.sh
no_dead_strip
.
The assembler directive .no_dead_strip symbol_name can be used to specify that a symbol is not to be dead stripped. For example:
.no_dead_strip _my_version_string
.cstring
_my_version_string:
.ascii “cctools-501”
This can be seen (in object files only) with nm -m
option and shows up as [no dead strip] in the following output:
% nm -m x.o
00000000 (__TEXT,__cstring) non-external *[no dead strip]* _my_version_string
The .no_dead_strip directive is generated by the new compiler when the attribute((used)) is specified on a symbol. LLVM assembly language use @llvm.used. In object files, this bit is N_NO_DEAD_STRIP as defined in <mach-o/nlist.h>. And is set in relocatable .o files (MH_OBJECT filetype) only in the n_desc field of an nlist struct.
Mac OS X Compiler Tools Release Notes
When linking object files (.o):
- If no symbol is used, all symbols defined in the .o will still be linked, but can be striped by DCE.
When linking static libraries (.a):
- If no symbol is used, the .a will be ignored.
- If some symbols are used, the .o files (inside .a) which contain those symbols will be linked, while other .o will be ignored.
Please note this behavior is different than DCE, which can strip unused methods from a linked object file. In other words, DCE can strip code at function level.
From man ld
, "-ObjC loads all members of static archive libraries that implement an Objective-C class or category". However, this is not the whole truth. From the source code of ld64
, -ObjC
will actually load all Swift static libraries as well. This behavior can be confirmed by a sample code.
Because of this and non-strippable public symbols, linking swift libraries with -ObjC
can enlarge the binary size a lot.