Reputation: 4165
I am in the process of linking using a static library and dynamic library but, I run into this error:
/usr/bin/ld: ../src/SeqLib/bin//libseqlib.a(libseqlib_a-FermiAssembler.o): relocation R_X86_64_32S against `_ZNSs4_Rep20_S_empty_rep_storageE' can not be used when making a shared object; recompile with -fPIC
Here is how my Makevars file looks like:
( cd SeqLib; ./configure --enable-shared; make)
PKG_CPPFLAGS= -I../src/SeqLib/ -I../src/SeqLib/fermi-lite/ -I../src/SeqLib/htslib/cram/ -I../src/SeqLib/htslib/htslib/ -I../src/SeqLib/htslib/ -I../src/SeqLib/bwa/
PKG_LIBS=-fPIC -enable-shared-lib -L../src/SeqLib/bin/ -lbwa -lfml -lhts -lseqlib
I don't understand why I am getting this error when I included the -fPIC
option in the PKG_LIBS
variable.
Upvotes: 0
Views: 2109
Reputation: 12698
-fPIC
is a compile only flag. If you include it when linking, the compiler will complaint about that. If you are using a Makefile
to compile your project (you have not included how do you use the variables cited in your question) the best approach is to define -fPIC
in the PKG_CFLAGS
in case your project contains only shared object targets. I don't know the case of a Makevars, but probably the followind discussion will give you some hints on how to solve your problem.
If you are building programs and shared libraries, the best approach is to define a new .SUFFIXES
dependency (let's call it .pic_o
) and define a variable called PKG_SHAREDCFLAGS=-fPIC
and then include a rule to compile those dependencies as this snippet shows:
PKG_SHAREDCPPFLAGS = -fPIC
.SUFFIXES: .pic_o
.c.pic_o:
$(CPP) $(PKG_CPPFLAGS) $(PKG_SHAREDCPPFLAGS) -c $@ -o $<
libshared.so_objs = a.pic_o b.pic_o c.pic_o
libshared.so: $(libshared.so_objs)
$(CPP) $(PKG_LDFLAGS) $(LDFLAGS) -o $@ $(libshared.so_objs) $(libshared.so_libs)
.pic_o
are .o
files compiled with the PIC
flag (aka Position Independent Code) which is required for object files that are going to be part of a shared object.
It's not dangerous to compile all your code as -fPIC
, as the linker has no problem to link PIC files statically into your code (position independent files only introduce a little overhead in your program, as the compiler reserves an offset register to control where the library has been finally loaded, and this gives you one register less to operate with) The introduction of a new .pic_o
suffix is to allow to produce static and dynamic versions of your library, so the static one only links objects compiled without -fPIC
and the dynamic one uses the PIC ones. Let's suppose you have a library, composed of a.c
, b.c
c.c
files, and you want to produce a dynamic and a static library from them. The following approach will success:
# All the targets.
targets=libA.a libA.so.3.0
TOCLEAN += $(targets)
# object files of the libA.a static library.
libA.a_objs = a.o b.o c.o
TOCLEAN += $(libA.a_objs)
# object files of the libA.so.3.0 dynamic library.
libA.so.3.0_objs = a.pic_o b.pic_o c.pic_o
TOCLEAN += $(libA.so.3.0_objs)
libA.so.3.0_libs = -lc
all: $(targets)
clean:
rm -f $(TOCLEAN)
.PHONY: all
.SUFFIXES: .pic_o
libA.a: $(libA.a_objs)
$(AR) -r $@ $?
$(RANLIB) $@
.c.pic_o:
$(CC) $(CFLAGS) -fPIC -c $< -o $@
libA.so.3.0: $(libA.so.3.0_objs)
$(LD) -shared $(libA.so.3.0_objs) $(libA.so.3.0_libs) -o $@
And execution:
lcu@FreeBSD:~/pru_19091$ make clean all
rm -f libA.a libA.so.3.0 a.o b.o c.o a.pic_o b.pic_o c.pic_o
cc -O2 -pipe -c a.c -o a.o
cc -O2 -pipe -c b.c -o b.o
cc -O2 -pipe -c c.c -o c.o
ar -r libA.a a.o b.o c.o
ar: warning: creating libA.a
ranlib libA.a
cc -O2 -pipe -fPIC -c a.c -o a.pic_o
cc -O2 -pipe -fPIC -c b.c -o b.pic_o
cc -O2 -pipe -fPIC -c c.c -o c.pic_o
ld -shared a.pic_o b.pic_o c.pic_o -lc -o libA.so.3.0
Suppose I touch file b.c
:
lcu@FreeBSD:~/pru_19091$ touch b.c
lcu@FreeBSD:~/pru_19091$ make
cc -O2 -pipe -c b.c -o b.o
ar -r libA.a b.o
ranlib libA.a
cc -O2 -pipe -fPIC -c b.c -o b.pic_o
ld -shared a.pic_o b.pic_o c.pic_o -lc -o libA.so.3.0
Upvotes: 3