如何始终包含静态库中的符号?

时间:2009-11-19 12:43:04

标签: c windows linux

假设我有一个静态库libx.a.如何从这个库中创建一些符号(不是全部),以便总是出现在我与我的库链接的任何二进制文件中?原因是我需要通过dlopen + dlsym提供这些符号。我知道--whole-archive链接器开关,但它强制将库存档中的所有目标文件链接到生成的二进制文件中,这不是我想要的...

到目前为止的观察(CentOS 5.4,32bit)( upd :这段错误;我无法重现此行为)

ld main.o libx.a

将很高兴地删除所有未引用的符号,而

ld main.o -L. -lx

将链接整个库。我想这取决于所使用的binutils的版本,然而,较新的链接器将能够从静态库中挑选单个对象。

另一个问题是如何在Windows下实现相同的效果?

提前致谢。任何提示将不胜感激。

4 个答案:

答案 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导出barbaza.out,请执行以下操作:

gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic

更新:
你的陈述:“我想要包含的符号仅由内部库使用”没有多大意义:如果符号是库的内部符号,为什么要导出它们?如果其他东西使用它们(通过dlsym),那么它们在库的内部 - 它们是库公共API的一部分。

您应该澄清您的问题,并解释您 正在努力实现的目标。提供示例代码也不会受到影响。

答案 2 :(得分:1)

我首先将您需要的符号拆分到一个单独的库中,只保留libx.a中的可选符号。

答案 3 :(得分:1)

获取您需要包含的符号的地址。

如果gcc的优化器无论如何都会消除它,那么用这个地址做一些事情 - 应该就够了。