I'm trying to create a share object which has its own dependencies statically linked.
Here is an example:
/* File: add.c */
#include <stdio.h>
int add(int a, int b) {
printf("Adding: %d %d\n", a, b);
return a + b;
}
When I try to compile I get the following error:
$ gcc -g -shared -fPIC -o libadd.so add.c -Wl,-Bstatic -lc -Wl,-Bdynamic
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(malloc.o): relocation R_X86_64_TPOFF32 against `tcache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(libc_fatal.o): relocation R_X86_64_PC32 against symbol `_dl_pagesize' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
Running on Ubuntu 18.04.4 LTS with gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 and GNU ld (GNU Binutils for Ubuntu) 2.30.
My questions:
How can I make the above work?
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
I also found this article here highlighting a similar issue but without a solution.
How can I make the above work?
Normal build of libc.a does not have -fPIC. On i386, you can actually link non-PIC object files into a .so, but the result would be an .so which requires text relocations (.text of such .so can't be shared between processes).
But on x86_64 you can't (relocations only have 4 bytes in the medium memory model, and you would need to relocate .text by more than +/-2GiB).
So to make this work, you must rebuild libc.a with -fPIC.
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
Most things will work, but TLS may cause complications.
Related
When I try to compile a trivial example test.c
int main () {
return 0;
}
for a cortex m7 target with hard float ABI by using the following invocation
arm-none-eabi-gcc -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard --specs=nosys.specs test.c
I get this error:
/usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/crt0.o: Conflicting CPU architectures 13/1
/usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/crt0.o
/usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/bin/ld: error: a.out uses VFP register arguments, /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/libc.a(lib_a-atexit.o) does not
[snip]
/usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/libnosys.a(_exit.o)
collect2: error: ld returned 1 exit status
So the issue is that gcc is linking to the wrong libc.a. If I use the argument print-multi-directory, it would appear that my version of arm-none-eabi-gcc should support this architecture:
$ arm-none-eabi-gcc -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard --specs=nosys.specs --print-multi-directory
thumb/v7e-m/fpv5/hard
And I can list the different versions of libc.a that are provided by arm-none-eabi-gcc:
$ find /usr/lib/arm-none-eabi/ -name libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/fpu/fpv5-sp-d16/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/fpu/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/fpu/fpv5-d16/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/softfp/fpv5-sp-d16/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/softfp/libc.a
/usr/lib/arm-none-eabi/newlib/armv7e-m/softfp/fpv5-d16/libc.a
/usr/lib/arm-none-eabi/newlib/libc.a
/usr/lib/arm-none-eabi/newlib/armv6-m/libc.a
/usr/lib/arm-none-eabi/newlib/fpu/libc.a
/usr/lib/arm-none-eabi/newlib/thumb/libc.a
/usr/lib/arm-none-eabi/newlib/armv7-m/libc.a
So it looks like there is a version of libc.a compiled for my desired architecture, but gcc isn't linking against it. How can I get gcc to link against the correct version of libc.a?
I'm using arm-none-eabi-gcc version 6.3.1 provided by the gcc-arm-none-eabi package for Ubuntu 18.04.
I am trying to create a shared object in fortran, that uses the netcdf static library.
The ultimate aim is to use this shared object in R, but I think the problem starts with my makefile, so I am just focusing on this here:
In my makefile i use the following flags
'F90 = ifort
FFLAGS = -O3 -fPIC -r8 # double-precision now run in Fortran , -fpic
for creating shared object file
LDFLAGS = -lnetcdff -lnetcdf -shared #-shared, for creating a shared
object file'
I think I managed to link everything allright, (you see all my object files below in the error message), but in the next step, when creating the shared object, there is a netcdf-library specific error message:
'ifort -O3 -fPIC -r8 -o HX.so HX.o HANDLE_ERR.o GET_CLM.o INTEGRATE.o
CLIMATE.o STATE.o PARAMETERS.o CONTROL.o HYDRO.o DYNAMICS.o CARBON.o
RINGS.o INIT.o SET_PARAMS.o -lnetcdff -lnetcdf -shared
ld: /usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a(netcdf4.o):
relocation R_X86_64_32 against `.bss' can not be used when making a
shared object; recompile with -fPIC
/usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a: could not read
symbols: Bad value
make: *** [HX.so] Error 1'
I find 'similar' problems, but as I am not familiar with the terminology and this is my very first try in generating a shared object, I cannot follow their instructions for my problem.
You need to install the dynamic (.so) version of NetCDF, be it from your repository or by compiling it yourself. As tim18 say in the comments, it also needs to be compiled with -fPIC, and the .so version will be.
I am trying to build libass into a shared library with static linking under MinGW-w64. When I configure with
./configure --disable-static --enable-shared
it generates the shared library (dynamically-linked) as expected. However, when I attempt to force static linking by setting
LDFLAGS=-static
instead of generating a statically-linked shared library (.dll with no dependency), it generates a static library (.a).
I am almost certain that I have all the dependent static libraries and no error or warning message is shown in the make process.
Can anyone please shed some light on what I'm doing wrong?
libtool says No.
The package's stock autotools ltmain.sh script parses the linkage flags and
if it finds -static it will not build a shared library, just a static
one.
Which is the most it could reasonably do, because you can't statically link a shared
library. A shared library must consist entirely of Position Independent (PIC)
code or the linkage will fail, whereas a static linkage will call for the linkage
of non-PIC object files, contributed by the non-PIC standard and runtime libraries,
if nothing else.
foo.c
#include <stdio.h>
void foo(void)
{
puts("foo");
}
Build a dynamically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -o libfoo.so foo.o
$ file libfoo.so
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), \
dynamically linked, BuildID[sha1]=1adff7204d84d138a80bc4b6f3f38211e4b42812, \
not stripped
Attempt to build a statically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -static -o libfoo.so foo.o
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/crtbeginT.o: \
relocation R_X86_64_32 against hidden symbol `__TMC_END__' cannot be used \
when making a shared object
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
The static lib is just an ar package.
You can use command of ar to make the pack and unpack it.
using gcc 4.5.1 in a 64bit x86 machine,I first create a.o as following:
g++ -fPIC -c a.cc -o a.o
then try to create liba.so as following:
g++ -static-libstdc++ -shared -W1,-soname,liba.so -o liba.so.1.0.0 a.o
but failed, with the following information:
relocation R_X86_64_32S against `vtable for __gnu_cxx::stdio_filebuf >' can not be used when making a shared object; recompile with -fPIC
I try to recompile libstdc++ library,with -fPIC added,but it failed anyway
I would expect that the static libstdc++ library was not build with -fPIC, and therefore can't be linked into a shared library.
Theoretically you could put non-PIC compiled code into a dynamic library, but it wouldn't be sharable (each program using it would have to have its own copy) so it's often not implemented.
You're going to need to link against the shared C++ library, make your own library a static library, or else rebuild libstdc++ yourself and grab the .o files from the build directory.
There is a similar question about this topic on stackoverflow, which refers to an external site about static linking of libstdc++.
I'm trying to link some .o files with:
gcc -m32 send.o lib.o -o send
and i get:
/usr/bin/ld: i386:x86-64 architecture of input file `send.o' is incompatible with i386 output
/usr/bin/ld: final link failed: Invalid operation
collect2: ld returned 1 exit status
I have installed
libc6-i386
gcc-multilib
ia32-lib
Where could be the problem?
You're not compiling. You're linking already compiled object files. It appears that send.o was compiled as an x86_64 object (without -m32). You cannot link a 64-bit executable from 32-bit object files.
Make sure all your object files are compiled in 32-bit mode.