代码之家  ›  专栏  ›  技术社区  ›  Julien

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

  •  1
  • Julien  · 技术社区  · 7 年前

    当我从静态库构建共享库时,它的自由功能将消失。我知道在最后一个库中保留符号的变通方法,但我想知道为什么我首先需要这个变通方法。

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

    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 回复  |  直到 7 年前
        1
  •  1
  •   Mike Kinghan Luchian Grigore    7 年前

    当链接器遇到对象文件时, 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 .