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

时间:2010-02-08 14:23:48

标签: gcc visibility static-libraries

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

我已将-fvisibility=hidden选项添加到.so项目(涵盖.o文件)和.a项目的编译选项中。

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

我做错了什么?

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

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

3 个答案:

答案 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。