编译共享库时没有未定义的引用

时间:2014-12-25 22:12:57

标签: c shared-libraries ld

我想知道为什么在使用-shared作为gcc的选项编译为共享库时,我没有得到任何未定义的引用。考虑以下情况:

#include <confuse.h>

int
main(int argc, char **argv)
{
    cfg_opt_t opts[1];
    cfg_t *cfg = cfg_init(opts, CFGF_NOCASE);
    return 0;
}

这里需要libconfuse才能正确运行程序。如果我将其编译为“普通”应用程序而未指定需要libconfuse(-lconfuse)即可获得以下内容(从我的常规角度看)错误:

$ gcc -Wall -Wno-unused-variable test.c -o test
/tmp/ccTVz6an.o: In function `main':
test.c:(.text+0x20): undefined reference to `cfg_init'
collect2: error: ld returned 1 exit status

如果我正在编译与共享库相同的代码,则不会收到有关库的任何错误消息:

$ gcc -Wall -Wno-unused-variable test.c -o test.so -shared
$ echo $?
0

有人可以把光带入黑暗吗?

2 个答案:

答案 0 :(得分:4)

您正在编译(共享)库,而不是程序,并且库预计不会完整,因此未定义的引用不会阻止共享库的构建。

是的,这听起来有点令人惊讶,特别是如果你来自操作系统(Windows?),其中共享库总是完全链接,但这就是ELF的工作原理。

如果要确保在构建共享库时解析所有引用,可以使用链接器选项--no-undefined

gcc -Wall -Wno-unused-variable test.c -o test.so -shared -Wl,--no-undefined

请注意,链接共享库时用于解析引用的库将作为NEEDED条目添加到该库的标题中,然后在使用该库时自动链接。有关详细信息,请参阅objdump -p

答案 1 :(得分:2)

使用共享库(非静态库),您可以将库libA.so链接到其他库libB.so

因此,您可以将您的共享库编译为:

  gcc -Wall -Wno-unused-variable -fPIC test.c \
       -o libmytest.so -shared -lconfuse

稍后您可以使用

将该库链接到某个main.c
  gcc -Wall main.c -lmytest -L. -o myprog

或者您可以在./libmytest.so上使用dlopen(3)在运行时加载它(请阅读有关./dlopen有意义的原因的手册页)

简单的解释在Program Library HowTo。但Drepper's paper: How to Write Shared Libraries是最好的参考。

允许共享库(甚至是静态库)具有未定义的引用,因为该库的用户通常显式地链接它所需的较低级库。 / p>