链接动态和静态库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选项时出现此错误。

+1

你的问题有没有关系RCPP,真的,但表示存在问题,你正在创建一个可用的R包(考虑到你自己施加的限制)。一个十几年来一直在做这件事的oldie-but-goldie是Matrix软件包,它的[src/Makevars](https://github.com/cran/Matrix/blob/master/src/Makevars)可能会帮助你您。 –

+1

@DirkEddelbuettel“你的问题与Rcpp无关,”为了其他读者,你怎么知道这一点?这是什么意思?在devtools :: load_all()后,错误状态为“用-fPIC重新编译”,即使包含此标志。这看起来像一个Rcpp问题:http:// stackoverflow。com/questions/21094740/linking-rcpp-to-interp2d-gsl-type-library – EB2127

+1

如何设置'src/Makevars'与使用编译代码的R包相关。对于Rcpp,我们只是使用标准的R构建工具和说明,这就是您遇到的问题。并且很简单:错误信息来自编译器,您用来驱动它的工具可能是'devtools'。再次,没有Rcpp在这里。 –

-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.cc.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