如何将-fvisibility选项应用于静态库中的符号?

Ste*_*ows 43 gcc visibility static-libraries

我有一个共享库项目,它由4个静态库(.a)和一个object(.o)文件构成.我正在尝试添加-fvisibility=hidden选项以将输出中的符号限制为仅使用__attribute__在源中标记的符号.

我已经-fvisibility=hidden.so项目的编译选项(包括.o文件)和项目添加了选项.a.

目标文件中的符号将按照预期从最终中删除.so.但是,.a项目中的符号仍然在最终.so文件中.将-fvisibility=hidden选项添加到.solink命令无效.

我究竟做错了什么?

我的目的是从.so除了接口函数之外的所有符号中删除库.

编辑:我实际上使用版本地图来解决这个问题.但是,随着外部符号的更改,它需要继续维护版本脚本.接受的答案有更好的主意.

fon*_*ons 62

简单地传递-Wl,--exclude-libs,ALL给gcc

这将告诉链接器将静态库中的所有符号转换为隐藏.

--exclude-libs 还接受一个档案列表(即静态库名称),以便更精细地在哪些库中隐藏符号.

注意:这仅适用于使用GNU binutils(例如Linux)或支持链接器的系统--exclude-libs(例如,它不适用于OSX的ld64)

  • @ManishShukla问题是关于静态库的问题 (6认同)
  • 非常感谢你!我将其与-fvisibility = hidden一起使用,并有选择地仅导出公共API(特别是对于项目外部的静态库,IMO仅白名单方法是明智的)。也许如果您可以添加一些标签,将来的Googler将会感激不尽。 (3认同)
  • 我观察到的是,如果使用链接时优化进行编译,这将无法可靠地排除符号。 (3认同)
  • 我相信它是-Wl, - exclude-libs = ALL(用=替换第二个逗号) (2认同)
  • 不幸的是,这在Mac OS上不起作用,因为ld在Mac OS下不知道这个选项. (2认同)

F'x*_*F'x 31

基本上,在链接期间处理可见性,并且链接器似乎不会将其强加于静态存档.在这里问了一个相关的问题(虽然不是重复的).

我建议你做的是替换你的链接阶段:gcc -shared -o mylib.so foo.o libbar.a进入一个两阶段的过程,你得到了目标文件:

  • ar x libbar.a (可能进入一个合适的空目录)
  • gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o


Rik*_*ing 5

这是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)
Run Code Online (Sandbox Code Playgroud)

然后,在检测到系统具有哪个链接程序之后,可以在此标志版本与GNU ld版本之间进行if-gate操作。