2016-11-21 220 views
0

我在使用靜態庫和動態庫鏈接的過程,但是,我碰到這個錯誤:鏈接動態和靜態庫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在這裏。 –

回答

2

-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