链接动态和静态库Rcpp

时间:2016-11-21 20:44:46

标签: c++ r rcpp

我正在使用静态库和动态库进行链接,但是我遇到了这个错误:

/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

以下是我的Makevars文件的样子:

( 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

当我在-fPIC变量中包含PKG_LIBS选项时,我不明白为什么会出现此错误。

1 个答案:

答案 0 :(得分:2)

-fPIC仅编译标志。如果在链接时包含它,编译器会对此进行投诉。如果您使用Makefile来编译项目(您没有包括如何使用问题中引用的变量),最好的方法是在-fPIC中定义PKG_CFLAGS以防万一您的项目仅包含共享对象目标。我不知道Makevars的情况,但可能跟随你的讨论会给你一些关于如何解决问题的提示。

如果要构建程序和共享库,最好的方法是定义一个新的.SUFFIXES依赖项(让我们称之为.pic_o)并定义一个名为PKG_SHAREDCFLAGS=-fPIC的变量,然后包含一个规则来编译这些依赖项,如此代码段所示:

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是使用.o标记编译的PIC个文件(又名 P \ n> 独立 C ode)对于将成为共享对象一部分的目标文件是必需的。

将所有代码编译为-fPIC并不危险,因为链接器将PIC文件静态链接到代码中没有问题(位置无关文件只会在程序中引入一点开销,因为编译器保留了offset寄存器,用于控制最终加载库的位置,这为您提供了一个较少操作的寄存器)引入新的.pic_o后缀是为了生成库的静态和动态版本,因此静态一个只链接没有-fPIC编译的对象,动态一个使用PIC。假设您有一个由a.cb.c c.c文件组成的库,并且您希望从中生成动态和静态库。以下方法将取得成功:

# 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 $@ 

执行:

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

假设我触摸文件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