假设我有一个静态库libx.a.如何从这个库中创建一些符号(不是全部),以便总是出现在我与我的库链接的任何二进制文件中?原因是我需要通过dlopen + dlsym提供这些符号。我知道--whole-archive链接器开关,但它强制将库存档中的所有目标文件链接到生成的二进制文件中,这不是我想要的...
到目前为止的观察(CentOS 5.4,32bit)( upd :这段错误;我无法重现此行为)
ld main.o libx.a
将很高兴地删除所有未引用的符号,而
ld main.o -L. -lx
将链接整个库。我想这取决于所使用的binutils的版本,然而,较新的链接器将能够从静态库中挑选单个对象。
另一个问题是如何在Windows下实现相同的效果?
提前致谢。任何提示将不胜感激。
答案 0 :(得分:3)
想象一下,您有一个项目,该项目由同一文件夹中的以下三个C文件组成;
// ---- jam.h
int jam_badger(int);
// ---- jam.c
#include "jam.h"
int jam_badger(int a)
{
return a + 1;
}
// ---- main.c
#include "jam.h"
int main()
{
return jam_badger(2);
}
你用这样的boost-build bjam文件构建它;
lib jam : jam.c <link>static ;
lib jam_badger : jam ;
exe demo : jam_badger main.c ;
你会收到这样的错误。
undefined reference to `jam_badger'
(我在这里使用了bjam,因为文件更容易阅读,但你可以使用你想要的任何东西)
删除'static'会产生一个工作二进制文件,就像向另一个库添加静态一样,或只使用一个库(而不是在另一个库内部进行愚蠢的包装)
发生这种情况的原因是因为ld足够聪明,只能选择实际使用的存档部分,在这种情况下,它们都不是。
解决方案是用静态存档包围-Wl, - 整个存档和-Wl, - no-whole-archive,就像这样;
g++ -o "libjam_candle_badger.so" -Wl,--whole-archive libjam_badger.a Wl,--no-whole-archive
不太确定如何让boost-build为你做这件事,但你明白了。
答案 1 :(得分:2)
首先要做的事情是:ld main.o libx.a
没有构建有效的可执行文件。一般情况下,您永远不会使用ld
直接链接任何内容; 始终使用适当的编译器驱动程序(在本例中为gcc
)。
此外,"ld main.o libx.a"
和"ld main.o -L. -lx"
应完全相同。我很怀疑你实际上从这两个命令得到了不同的结果。
现在回答您的问题:如果您希望从foo
导出bar
,baz
和a.out
,请执行以下操作:
gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic
更新:
你的陈述:“我想要包含的符号仅由内部库使用”没有多大意义:如果符号是库的内部符号,为什么要导出它们?如果其他东西使用它们(通过dlsym),那么它们不在库的内部 - 它们是库公共API的一部分。
您应该澄清您的问题,并解释您 正在努力实现的目标。提供示例代码也不会受到影响。
答案 2 :(得分:1)
我首先将您需要的符号拆分到一个单独的库中,只保留libx.a
中的可选符号。
答案 3 :(得分:1)
获取您需要包含的符号的地址。
如果gcc的优化器无论如何都会消除它,那么用这个地址做一些事情 - 应该就够了。