How to apply -fvisibility option to symbols in static libraries?
Solution 1:
Simply pass -Wl,--exclude-libs,ALL
to gcc
This will tell the linker to transform all the symbols in the static libraries to hidden.
--exclude-libs
also accepts a list of archives (i.e. static library names) for finer granularity on which libraries to hide symbols from.
Note: this will only work in systems using GNU binutils (e.g. Linux) or with a linker supporting --exclude-libs
(e.g. it won't work with OSX's ld64)
Solution 2:
Basically, visibility is handled during linking, and the linker doesn't seem impose it on static archives. A related question (though not a duplicate) was asked on SO here.
What I would advise you to do is to replace your linking stage: gcc -shared -o mylib.so foo.o libbar.a
into a two stages process where you get back the object files:
-
ar x libbar.a
(possibly into a suitable, empty directory) gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o
Solution 3:
This is an answer to the problem for OS X.
The Mac ld
doesn't support --exclude-libs
, but it does support -exported_symbol sym
and it does apply this to object files in static libraries. And when you're filtering to a public API, the whitelist is small enough to spell it out.
I ended up with the following in my Makefile to generate a -Wl,-exported_symbol,_api_func_1
flag for each exported symbol:
SYMBOLS = api_func_1 api_func_2 api_func_3 api_func_4
SYMBOLS += api_func_5 # add more as necessary
COMMA = ,
LDFLAGS += $(addprefix -Wl$(COMMA)-exported_symbol$(COMMA)_,$(SYMBOLS))
# ...
libmyapi.so: # ...
$(CC) -shared -o $@ ... $(LDFLAGS)
Then you can if-gate between this version of the flags and the GNU ld version after detecting which linker the system has.