将静态链接库转换为动态链接库
Turning a statically linked library into a dynamic one
我知道这个问题已经被问过几次了,但是没有一个解决方案对我有效。我有一个静态链接库,我想与Java 8之前版本的JNI层一起使用。根据我阅读的"如何在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层到wwpal rabbit库。
在构建过程中,我已经通过静态链接静态地创建了一个名为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程序不再在Ubuntu中编译"之类的结果似乎表明我忘记了-o
标志,但我知道我没有。
- 我想做的是可能的吗?
- 我做错了什么?
我在通过docker pull ubuntu:14.04
我可以用下面的命令行
消除一些错误 /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
我认为这有效的原因是通过排除标准库,我没有重新定义。我不知道该怎么做
我认为这里的问题是您使用的命令行。标志--whole-archive
和--no-whole-archive
应用于命令行上的所有后续参数,其中包括许多自动附加在后台的标准库和目标文件(例如,-lc
, crt0.o
, libc_nonshared.a
等)。
如果在你打算引入的静态库的文件名之后没有直接的--no-whole-archive
开关,这也会将--whole-archive
应用于你最后一个参数之后的内置存档,例如,它会尝试从libc.a
, libm.a
等中引入每个对象,这至少会失败,导致"多重定义"错误。尝试将--no-whole-archive
switch直接添加到target/vw_jni.a
之后的命令行中,这样您最终会得到如下内容:
/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
这实际上是不明智的,因为如果你把从一些静态库中提取的目标文件,这些目标文件仍然是位置相关的代码。
共享库最好包含位置无关的代码(因为动态链接器ld-linux.so
是mmap
-在.so
内的一些随机地址,例如,因为ASLR),否则动态链接器将不得不处理大量的重定位(因此动态链接变得非常低效)。
因此,即使您成功地将静态库转换为共享库,这样做也是不明智的。
所以保持你的静态库不变,或者用-fPIC
重新编译它们的源代码来构建一个共享对象。
- g++用户定义的动态链接库上的全局new和delete运算符
- 如何使用C++导出制作动态链接库
- 动态链接库中C++回调函数
- 调用函数一次用于动态链接库,一次从可执行文件调用函数
- 将函数传递给动态链接库
- 如何将动态链接库与CMake一起使用
- 从另一个动态链接库项目调用静态库函数
- JNI 不满意链接错误: 动态链接库 (DLL) 初始化例程失败
- 如何将此动态链接库链接到程序
- Ordinal 3283不能位于动态链接库libmysql.dll中
- 检查动态链接库是否已过时
- Qt测试模拟动态链接库
- SDL_AudioStreamFlush无法在动态链接库SDL2_mixer.dll中找到
- 在 Win 7 SP 中创建 exe vcxproj:过程入口点<function>无法位于动态链接库中KERNAL32.dll
- 编译C++中动态链接库,存在运行路径问题
- 导入库<>动态链接库兼容性
- Java/Python在C/C++中访问的动态链接库
- 多个动态链接库(DLL)是否可以从静态库(LIB)共享线程本地存储
- 将静态库封装在动态链接库(DLL)中
- 将静态链接库转换为动态链接库