kgui
kgui

Reputation: 4165

Linking Dynamic and Static Libraries Rcpp

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

Answers (1)

Luis Colorado
Luis Colorado

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

Related Questions