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

How to keep a free function from a static library in a shared library

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

让我们考虑这个源文件:

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 或使用静态库符号的 class 成员函数来获取共享库中的函数,但我不知道为什么上面的命令没有产生相同的共享库。

当linker遇到目标文件时,foo.o在输入序列中它 link无条件地将其放入输出文件(程序或共享库)。

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

如果它找到任何这样的目标文件,它会从存档中提取它们并 links 它们 进入输出文件,就像它们在命令行中单独列出一样 并且根本没有提到静态库。如果没有找到,存档 对link年龄没有任何贡献。

在你的第一次编译中-link年龄:

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

g++ 将其分解(必须)为一个编译步骤和一个 link 步骤,有效地:

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

其中 temporary.o 是 link 无条件编辑的。

第二个link年龄:

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

单独存档成员libtest.a(test.o)未能定义任何未解决的问题 已经 linked 的引用,因为没有。 libtest.a 对共享库和输出共享库的 linkage 没有任何贡献 不包含符号,但包含 g++ -shared ... linkage.

的默认库提供的样板

linkage 静态库的默认用途,与单独命名的目标文件不同,是 为 linker 提供一袋目标文件,select 只需要这些文件 满足手头未解决的参考资料。您不需要确切地知道它们将是哪些。你刚才 需要知道它们在那个袋子里。之前你必须 link 至少一个目标文件 任何静态库,如果有任何未解析的引用,静态库 会员可能会满意。或者指定 --whole-archive.