我想知道为什么在使用-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
有人可以把光带入黑暗吗?
答案 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>