如何在共享库中保留静态库中的自由函数



当我从静态库构建共享库时,它的免费函数将消失。我知道一个将符号保留在最终库中的解决方法,但我想了解为什么我首先需要这个解决方法。

让我们考虑一下这个源文件:

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或通过使用静态库的符号来获得共享库中的函数,但我不明白为什么上面的命令不能产生相同的共享库。

当链接器遇到对象文件时,输入序列中的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

其中CCD_ 6被无条件地链接。

在您的第二个链接中:

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

单独存档成员CCD_ 7未能定义任何未解析的已经链接的引用,因为没有任何引用。libtest.a对共享库和输出共享库的链接没有任何贡献不包含任何符号,但包含g++ -shared ...链接的默认库提供的样板。

链接中静态库的默认用途与单独命名的对象文件不同,是为链接器提供一个对象文件包,从中只选择需要的对象文件满足手头已有的未解析引用。你不需要确切地知道他们会是谁。你只需要需要知道它们在那个袋子里。您必须链接至少一个对象文件任何静态库(如果有任何未解析的引用(成员可能会满意。或者指定--whole-archive

最新更新