我有一个共享库项目,它是由4个静态库(.a
)和一个对象(.o
)文件构建的。我正在尝试添加-fvisibility=hidden
选项以将输出中的符号限制为仅使用__attribute __在源中标记的符号。
我已将-fvisibility=hidden
选项添加到.so
项目(涵盖.o
文件)和.a
项目的编译选项中。
目标文件中的符号将按照预期从最终.so
中删除。但是,.a
项目中的符号仍在最终的.so
文件中。将-fvisibility=hidden
选项添加到.so
链接命令无效。
我做错了什么?
我的目的是从.so
除了接口函数之外的所有符号移除到库中。
答案 0 :(得分:59)
只需将-Wl,--exclude-libs,ALL
传递给gcc
这将告诉链接器将静态库中的所有符号转换为隐藏。
--exclude-libs
还接受一个档案列表(即静态库名称),以便更精细地在哪些库中隐藏符号。
注意:这只适用于使用GNU binutils的系统(例如Linux)或支持--exclude-libs
的链接器(例如,它不适用于OSX的ld64)
答案 1 :(得分:30)
基本上,在链接期间处理可见性,并且链接器似乎不会将其强加于静态存档。在SO here上询问了一个相关问题(虽然不重复)。
我建议你做的是将链接阶段gcc -shared -o mylib.so foo.o libbar.a
替换为两个阶段的过程,在这个过程中你会找回目标文件:
ar x libbar.a
(可能进入合适的空目录)gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o
答案 2 :(得分:4)
这是OS X问题的答案。
Mac ld
不支持--exclude-libs
,但它支持-exported_symbol sym
, 将此应用于静态库中的目标文件。当您过滤到公共API时,白名单足够小,可以拼出来。
我最终在Makefile中使用以下内容为每个导出的符号生成-Wl,-exported_symbol,_api_func_1
标志:
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)
然后,在检测到系统具有哪个链接器之后,您可以在此版本的标志和GNU ld版本之间进行if-gate。