如何在共享库中保持静态库中的自由功能

时间:2018-07-13 17:50:41

标签: c++ g++ ld

当我从静态库构建共享库时,其自由功能消失了。我知道将符号保留在最终库中的解决方法,但我想理解为什么首先需要这种解决方法。

让我们考虑这个源文件:

extern "C" void HERE_I_AM() {}

如果我执行以下命令

g++ test.cpp -shared -o libtest-without-static.so
nm libtest-without-static.so

我可以看到该函数在共享库中可用:

…
0000000000201000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000000590 r __GNU_EH_FRAME_HDR
0000000000000580 T HERE_I_AM               <-- HERE
0000000000000468 T _init
                 w _ITM_deregist
…

但是如果我先在静态库中编译文件

g++ -c test.cpp 
ar crf libtest.a test.o
g++ -shared libtest.a -o libtest-with-static.so
nm libtest-with-static.so

然后该函数不在共享库中

0000000000201020 B __bss_start
0000000000201020 b completed.7641
                 w __cxa_finalize
0000000000000440 t deregister_tm_clones
00000000000004d0 t __do_global_dtors_aux
0000000000200e88 t __do_global_dtors_aux_fini_array_entry
0000000000201018 d __dso_handle
0000000000200e90 d _DYNAMIC
0000000000201020 D _edata
0000000000201028 B _end
000000000000051c T _fini
0000000000000510 t frame_dummy
0000000000200e80 t __frame_dummy_init_array_entry
0000000000000528 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000000408 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000480 t register_tm_clones
0000000000201020 d __TMC_END__

我知道我可以通过使用-Wl,--whole-archive或通过使用静态库的符号使用类成员函数来在共享库中获取该函数,但是我不明白为什么上面的命令没有这样做产生相同的共享库。

1 个答案:

答案 0 :(得分:1)

链接器遇到目标文件时,按输入顺序foo.o 将其无条件链接到输出文件(程序或共享库)。

当遇到静态库libbar.a时,它将(默认情况下)检查存档 查找任何目标文件,例如libbar.a(foo.o)提供了未解决的定义 目标文件(或共享库)已引用的符号 链接。

如果找到任何此类目标文件,则将其从存档中提取并链接它们 放入输出文件中,就像它们在命令行中单独列出一样 和静态库根本没有提到。如果找不到,则存档 对链接没有任何帮助。

在您的第一个编译链接中:

$ g++ test.cpp -shared -o libtest-without-static.so

g++有效地将其分解为编译步骤和链接步骤:

    $  g++ -c -o temporary.o test.cpp
    $  g++ temporary.o -shared -o libtest-without-static.so

其中temporary.o是无条件链接的。

在第二个链接中:

$ g++ -shared libtest.a -o libtest-with-static.so

单独的存档成员libtest.a(test.o)无法定义任何未解决的 已链接的引用,因为没有链接。 libtest.a 对共享库和输出共享库的链接没有任何帮助 除g++ -shared ...链接的默认库提供的样板外,不包含任何符号。

链接中静态库的默认用途不同于单独命名的目标文件,它是 提供链接器一袋目标文件,从中仅选择所需的目标文件 满足现有的未解决参考。您无需确切知道它们将是哪个。你刚才 需要知道他们在那个袋子里。您必须先链接至少一个目标文件 任何静态库(如果将有该静态库的任何未解决的引用) 成员可能会满意。或指定--whole-archive

相关问题