链接动态和静态库 Rcpp

Linking Dynamic and Static Libraries 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

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

-fPIC 是一个 仅编译标志 。如果你在 linking 时包含它,编译器会抱怨。如果您使用 Makefile 来编译您的项目(您没有包括如何使用问题中引用的变量),最好的方法是在 PKG_CFLAGS 中定义 -fPIC 以防万一您的项目仅包含共享对象目标。我不知道 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 是使用 PIC 标志编译的 .o 文件(又名 Position Independent Code) 将成为共享对象的一部分的对象文件是必需的。

将所有代码编译为 -fPIC 并不危险,因为 linker 可以将 link PIC 文件静态地放入您的代码中(位置无关文件仅引入程序中的开销很小,因为编译器保留了一个偏移寄存器来控制最终加载库的位置,这使您可以减少一个寄存器来操作)引入新的 .pic_o 后缀是为了允许产生你的库的静态和动态版本,所以静态版本只有 links 对象编译而没有 -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