我创建了一个.c
文件,该文件与大约300个其他.o
文件一起转换为.c
文件,并包含在.a
静态库中。该库以及许多其他库用于创建.so
动态库。在使用.a
分析.so
和nm
文件时,我发现由于某种原因,.c
文件中定义的符号出现在.a
中文件但不在.so
文件中。我认为没有理由这应该发生。有人可以帮帮我吗?用于创建两个二进制文件的步骤是:
gcc -fvisibility=hidden -c foo.c -o foo.c.o
ar cr libbar.a foo.c.o ...
gcc -fvisibility=hidden -fPIC -o libfinal.so libbar.a x.o y.a ...
我在此处指定隐藏可见性的原因是我只想暴露几个选定的符号。要公开来自foo.c
的符号,我已指定了visibility属性,以便标题foo.h
中的函数签名如下所示:
extern int _____attribute _____((visibility(“default”)))func();
编辑:命令nm libbar.a | grep Ctx
给出:
000023c5 T CtxAcquireBitmap
000026e9 T CtxAcquireArray
00001e77 T CtxCallMethod
但是,nm libfinal.so | grep Ctx
没有显示任何内容。
更新:找到了另一个post,其中讨论了--whole-archive
选项的用法。此外,偶然发现--export-dynamic
选项,显然告诉链接器保留未引用的符号。进一步调查。
答案 0 :(得分:4)
尝试使用--whole-archive
链接器选项在链接
gcc -o libfinal.so -Wl,--whole-archive libbar.a x.o y.a -Wl,--no-whole-archive
来自man ld
:
<强> - 全 - 归档强>
对于--whole-archive选项后命令行中提到的每个存档,包括存档中的每个目标文件 链接,而不是在存档中搜索所需的目标文件。这通常用于将存档文件转换为共享文件 库,强制每个对象都包含在生成的共享库中。此选项可能会被多次使用。从gcc使用此选项时的两个注意事项:首先,gcc不知道此选项,因此您必须使用-Wl,-whole-archive。 其次,不要忘记在档案列表之后使用-Wl,-no-whole-archive ,因为gcc会将自己的档案列表添加到您的档案中 链接,你可能不希望这个标志也影响那些。
答案 1 :(得分:1)
据我所知,在编译.a时,gcc只会拉出其他模块引用的对象。如果你的意图是将.a的全部内容包含在.so中,那么使用libbar.a中的内容进行简单的“编译/链接x.c到libfinal.so”就不是你想要的了。
答案 2 :(得分:-1)
在我的主文件中为所需符号创建虚拟引用并没有解决问题。引用的符号出现在二进制转储(使用nm
获得)中,并带有U
(=未定义)标记。我设法通过在创建.so
文件时直接链接目标文件而不是首先将其包含在.a
库中来解决问题。由于这些函数已标记为extern
,因此它们包含在.so
中,即使它们未在库中引用。如果他们没有被标记为extern
,他们就不会像sylvainulg那样被包括在内。
感谢Dmitry指出--whole-archive
选项。我不知道存在这样的选择。