Reputation: 4055
I know this question has been asked a few times, but none of the solutions have worked for me. I have a statically linked library that I would like to use with a JNI layer with versions pre Java 8. Based on my reading of "how to link static library into dynamic library in gcc", it seems possible. Here is my command line:
/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
This is based on writing a JNI layer to the Vowpal Wabbit library.
At this point in the build process I have statically created a file called target/vw_jni.a
through static linking
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
I'm not sure what this means and when I search around for it find results such as "C program no longer compiles in Ubuntu" that seem to suggest that I forgot a -o
flag, but I know I have not.
I'm doing this on a Docker instance obtained through docker pull ubuntu:14.04
UPDATE:
I'm able to get rid of a few of the errors with the following command line
/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
This generates the following output
/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
The reason I think this works is that by excluding the standard lib I don't have the redefinitions. I'm not sure where to go from here though.
Upvotes: 1
Views: 1297
Reputation: 31
I think the problem here is with the command line you're using. The flags --whole-archive
and --no-whole-archive
apply to all subsequent arguments on the command line, which includes a number of standard libraries and object files (e.g., -lc
, crt0.o
, libc_nonshared.a
, etc.) that are automatically appended behind the scenes.
If there's no --no-whole-archive
switch directly after the filenames of static libraries you intend to bring in, this will also apply --whole-archive
to the built-in archives that come after your last argument, e.g., it will try to also bring in every object from libc.a
, libm.a
, etc. which will at the very least fail with a "multiple definition" error. Try adding --no-whole-archive
switch to your command line directly after target/vw_jni.a
so you end up with something like:
/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
Upvotes: 2
Reputation: 1
This is practically not wise, because if you put the object files extracted from some static library these object files still remain position dependent code.
Shared libraries should very preferably contain position independent code (because the dynamic linker ld-linux.so
is mmap
-ing segments inside the .so
at some random address, e.g. because of ASLR), otherwise the dynamic linker would have to process a big lot of relocations (so dynamic linking becomes very inefficient).
So even if you succeed to convert your static library into a shared one, it won't be wise to do so.
So keep your static library as is, or recompile their source code with -fPIC
to build a shared object.
Upvotes: 1