将静态链接库转换为动态库

时间:2015-06-08 16:30:28

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

我知道这个问题已被问过几次,但没有一个解决方案对我有用。我有一个静态链接的库,我想使用JNI层与Java 8之前的版本。基于我对"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. 我做错了什么?
  3. 我在通过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

    我认为这有效的原因是,通过排除标准库,我没有重新定义。我不知道从哪里开始。

2 个答案:

答案 0 :(得分:2)

我认为这里的问题是您使用的命令行。标志--whole-archive--no-whole-archive适用于命令行上的所有后续参数,其中包括许多标准库和目标文件(例如-lccrt0.o,{{ 1}}等)。

如果要导入的静态库的文件名后没有直接切换libc_nonshared.a,这也会将--no-whole-archive应用于最后一个参数之后的内置归档文件,例如,也会尝试引入--whole-archivelibc.a等中的每个对象,这些对象至少会因“多个定义”错误而失败。尝试在libm.a之后直接将--no-whole-archive开关添加到命令行中,这样最终得到的结果如下:

target/vw_jni.a

答案 1 :(得分:1)

这实际上 并不明智,因为如果你把从某些静态库中提取的目标文件放在这些目标文件中,那么它们仍然是依赖于位置的代码。

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

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

请按原样保留静态库,或使用-fPIC重新编译源代码以构建共享对象。

相关问题