方便库中的符号未在可执行文件中导出

8
我有一个程序叫做myprogram,它链接了一个静态便捷库libconvenience.a,其中包含一个名为func()的函数。但是myprogram中没有调用func()函数;func()需要能够从插件库plugin.so中被调用。
myprogram中,符号func()没有被动态导出。如果我运行以下命令:
nm myprogram | grep func

我什么也没有得到。然而,libconvenience.a 中并没有缺失:

nm libconvenience/libconvenience.a | grep func
00000000 T func

我正在使用 automake,但是如果我手动在命令行上执行最后的链接步骤,它也不起作用:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries`

然而,如果我像这样链接程序,跳过使用便利库并直接链接本应进入libconvenience.a的目标文件,func() 将如预期地出现在 myprogram 的符号中:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries`

如果我在myprogram中的任何位置添加一个虚拟调用func(),那么func()也会显示在myprogram的符号中。但是,我认为--export-dynamic应该导出所有符号,无论它们是否在程序中使用!我正在Fedora 14上使用automake 1.11.1和gcc 4.5.1。我还使用Libtool 2.2.10构建plugin.so(但不使用方便库)。我没有忘记将-Wl,--export-dynamic放入myprogram_LDFLAGS中,也没有忘记将包含func()的源代码放入libconvenience_a_SOURCES中(一些搜索表明这些是此问题的常见原因)。有人可以帮助我理解这里发生了什么吗?
2个回答

7
我成功解决了这个问题。是 John Calcote 的优秀 Autotools 书中的一条注释指引我找到了正确的方向:
链接器会将在命令行上明确指定的每个目标文件添加到二进制产品中,但它们只从存档文件中提取实际在链接代码中被引用的目标文件。
为了抵消这种行为,可以使用 libtool 的 --whole-archive 标志。然而,这会导致所有系统库的符号也被引入,从而导致大量双重符号定义错误。因此,--whole-archive 需要紧接在链接器命令行上的 libconvenience.a 前面,并且需要跟随 --no-whole-archive,以使其他库不以同样的方式处理。这有点困难,因为 automake 和 libtool 实际上不能保证在命令行上保持您的标志相同的顺序,但 Makefile.am 中的这行代码解决了这个问题:
myprogram_LDFLAGS = -Wl,--export-dynamic \
    -Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive

在Bazel中,这对应于cc_library(alwayslink=True) - FDS

0
如果您需要将func放在plugin.so中,应尽可能在那里定位它。方便库只是为了方便链接到可执行文件或库作为中间步骤。

是的,但我明确需要func不在插件中,因为func是API的一部分,多个插件需要调用它。这些插件是在其他地方编写的,我试图避免对它们进行本地修改。 - ptomato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接