我正在使用静态库和动态库进行链接,但是我遇到了这个错误:
/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
选项时,我不明白为什么会出现此错误。
答案 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.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 $@ $?
$(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