链接动态和静态库RCPP
问题描述:
我在使用静态库和动态库链接的过程,但是,我碰到这个错误:链接动态和静态库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
是仅编译标志。如果在链接时包含它,编译器会对此提出投诉。如果您正在使用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 [email protected] -o $<
libshared.so_objs = a.pic_o b.pic_o c.pic_o
libshared.so: $(libshared.so_objs)
$(CPP) $(PKG_LDFLAGS) $(LDFLAGS) -o [email protected] $(libshared.so_objs) $(libshared.so_libs)
.pic_o
是.o
文件与PIC
标志编译(又名P osition 我 ndependent ç ODE)这是需要用于将要成为共享对象的一部分的对象文件。
将所有代码编译为-fPIC
并不危险,因为链接器将PIC文件静态链接到代码中没有问题(位置独立文件只会在程序中引入一点开销,因为编译器会保留一个偏移寄存器控制库的最终加载位置,这样可以减少一个寄存器的使用)引入新的.pic_o
后缀将允许生成静态和动态版本的库,因此静态版本只链接编译时没有编译的对象-fPIC
动态的使用PIC。假设您有一个库,由a.c
,b.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 [email protected] $?
$(RANLIB) [email protected]
.c.pic_o:
$(CC) $(CFLAGS) -fPIC -c $< -o [email protected]
libA.so.3.0: $(libA.so.3.0_objs)
$(LD) -shared $(libA.so.3.0_objs) $(libA.so.3.0_libs) -o [email protected]
和执行:
[email protected]:~/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
:
[email protected]:~/pru_19091$ touch b.c
[email protected]:~/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
你的问题有没有关系RCPP,真的,但表示存在问题,你正在创建一个可用的R包(考虑到你自己施加的限制)。一个十几年来一直在做这件事的oldie-but-goldie是Matrix软件包,它的[src/Makevars](https://github.com/cran/Matrix/blob/master/src/Makevars)可能会帮助你您。 –
@DirkEddelbuettel“你的问题与Rcpp无关,”为了其他读者,你怎么知道这一点?这是什么意思?在devtools :: load_all()后,错误状态为“用-fPIC重新编译”,即使包含此标志。这看起来像一个Rcpp问题:http:// stackoverflow。com/questions/21094740/linking-rcpp-to-interp2d-gsl-type-library – EB2127
如何设置'src/Makevars'与使用编译代码的R包相关。对于Rcpp,我们只是使用标准的R构建工具和说明,这就是您遇到的问题。并且很简单:错误信息来自编译器,您用来驱动它的工具可能是'devtools'。再次,没有Rcpp在这里。 –