【问题标题】:Turning a statically linked library into a dynamic one将静态链接库变成动态库
【发布时间】:2015-06-08 16:30:27
【问题描述】:

我知道这个问题已被问过几次,但没有一个解决方案对我有用。我有一个静态链接库,我想将它与 Java 8 之前的版本的 JNI 层一起使用。根据我对"how to link static library into dynamic library in gcc" 的阅读,这似乎是可能的。这是我的命令行:

/usr/bin/g++ -shared -std=c++0x -D__extern_always_inline=inline -Wall -pedantic -O3 -fomit-frame-pointer -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -DNDEBUG -fPIC -Wl,--whole-archive target/vw_jni.a -o target/vw_jni.lib

这是基于将 JNI 层写入Vowpal Wabbit 库。

在构建过程的这一点上,我通过静态链接静态创建了一个名为target/vw_jni.a 的文件

target/vw_jni.a: In function `_fini': (.fini+0x0): multiple definition of `_fini' /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here target/vw_jni.a: In function `data_start': (.data+0x8): multiple definition of `__dso_handle' /usr/lib/gcc/x86_64-linux-gnu/4.9/crtbeginS.o:(.data.rel.local+0x0): first defined here target/vw_jni.a: In function `_init': (.init+0x0): multiple definition of `_init' /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init': (.text+0x0): multiple definition of `__libc_csu_init' target/vw_jni.a:(.text+0x1cea20): first defined here /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_fini': (.text+0x70): multiple definition of `__libc_csu_fini' target/vw_jni.a:(.text+0x1ceab0): first defined here /usr/lib/gcc/x86_64-linux-gnu/4.9/crtendS.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__' target/vw_jni.a:(.data+0x2630): first defined here /usr/bin/ld: target/vw_jni.a: .preinit_array section is not allowed in DSO /usr/bin/ld: failed to set dynamic section sizes: Nonrepresentable section on output collect2: error: ld returned 1 exit status

我不确定这意味着什么,当我四处搜索时,发现诸如 "C program no longer compiles in Ubuntu" 这样的结果似乎表明我忘记了 -o 标志,但我知道我没有。

  1. 我正在尝试做的事情可能吗?
  2. 我做错了什么?

我在通过docker pull ubuntu:14.04获得的一个Docker实例上做这个

更新:

我可以使用以下命令行来消除一些错误

/usr/bin/g++ -shared -std=c++0x -D__extern_always_inline=inline -Wall -pedantic -O3 -fomit-frame-pointer -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -DNDEBUG -fPIC -nostdlib -Wl,--whole-archive target/vw_jni.a -o target/vw_jni.lib

这会生成以下输出

/usr/bin/ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored. /usr/bin/ld: target/vw_jni.a: .preinit_array section is not allowed in DSO /usr/bin/ld: failed to set dynamic section sizes: Nonrepresentable section on output collect2: error: ld returned 1 exit status

我认为这可行的原因是通过排除标准库我没有重新定义。不过我不确定从这里去哪里。

【问题讨论】:

  • 如果不出意外,您可以将库的所有成员提取到一个空目录中,并将它们链接到一个动态库中(假设所有成员都是 .o 文件,至少)。
  • 我想我可以。理想情况下,我想将此库打包在 Maven 工件中,因此我必须将所有这些都打包。
  • 你知道静态库中的每个对象都是用-fPIC编译的吗?
  • 我知道所有的大众代码都是。这还包括以下链接器选项-l boost_program_options -l pthread -l z

标签: c++ gcc linker static-linking dynamic-linking


【解决方案1】:

我认为这里的问题在于您使用的命令行。 --whole-archive 和 --no-whole-archive 标志适用于命令行上的所有后续参数,其中包括许多标准库和目标文件(例如,-lc、crt0.o、libc_nonshared.a 等),它们是自动附加在幕后。

如果您打算引入的静态库的文件名后面没有直接--no-whole-archive 开关,这也会将--whole-archive 应用于您最后一个参数之后的内置存档,例如,它也会尝试从libc.a、libm.a 等中引入每个对象,这至少会因“多重定义”错误而失败。尝试在target/vw_jni.a 之后直接将--no-whole-archive 开关添加到您的命令行,这样您最终会得到类似的结果:

/usr/bin/g++ -shared -std=c++0x   -D__extern_always_inline=inline -Wall -pedantic -O3 \
  -fomit-frame-pointer -fno-strict-aliasing  -D_FILE_OFFSET_BITS=64 -DNDEBUG -fPIC \
  -Wl,--whole-archive target/vw_jni.a -Wl,--no-whole-archive \
  -o target/vw_jni.lib

【讨论】:

    【解决方案2】:

    这实际上是不明智的,因为如果你把从某个静态库中提取的目标文件放到这些目标文件中,这些目标文件仍然是位置相关的代码。

    共享库最好包含 position independent code(因为动态链接器 ld-linux.so 是 mmap-ing 段内的 .so 在某个随机地址,例如因为 ASLR),否则动态链接器将不得不处理大量重定位(因此动态链接变得非常低效)。

    因此,即使您成功地将静态库转换为共享库,这样做也不明智。

    所以保持你的静态库不变,或者用-fPIC重新编译它们的源代码来构建一个共享对象。

    【讨论】:

    • 我会以我不是 g++ 专家的事实作为开头,但我确实有能力从源代​​码完全重新编译。编译时我正在使用 -fPIC 进行构建。我认为将静态库与 -static 和 -fPIC 链接。如果这不聪明,请告诉我。
    • 如果有源代码,重新编译成共享对象即可。
    • 这正是我想要做的。问题是我需要包含所有依赖项,但我无法找到一种方法来做到这一点。你知道什么方法吗?
    • 确定构建静态库的规则。附加到该规则的依赖项应该足以让您为动态库构建合适的依赖项。
    • 我不确定你的意思
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多