编译失败,“在创建共享库时,无法使用针对.rodata.str1.8的重定位R_X86_64_32”


84

我正在尝试从VPS中的makefile编译此源代码,但无法正常工作。VPS是64美分的操作系统

这是完整的错误

# make
gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c
g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp
g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp
g++ -O2 -fshort-wchar -shared -o "TCP_V1.so" *.o
/usr/bin/ld: TCP-LINUX_V1.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be     used when making a shared object; recompile with -fPIC
TCP-LINUX_V1.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [all] Error 1

这是我的makefile:

GPP=g++
GCC=gcc
OUTFILE="TCP_V1.so"

COMPILE_FLAGS=-c -O3 -w -DLINUX -I../SDK/amx/

all:
    $(GCC) $(COMPILE_FLAGS) ../SDK/amx/*.c
    $(GPP) $(COMPILE_FLAGS) ../SDK/*.cpp
    $(GPP) $(COMPILE_FLAGS) *.cpp
    $(GPP) -O2 -fshort-wchar -shared -o $(OUTFILE) *.o

有人知道怎么了吗?


6
你尝试了recompile with -fPIC吗?
约阿希姆·伊萨克森

抱歉,我不确定如何执行此操作。在Google上找不到有关“ -fPIC”的任何信息。
user1667191 2013年

4
试试类似的东西COMPILE_FLAGS=-c -O3 -w -DLINUX -fPIC -I../SDK/amx/
Joachim Isaksson


9
如果您在Google中搜索-fPIC,您肯定会一无所获。删除负号或使用引号“ -fPIC”,否则您将忽略所有包含fPIC的结果。
d00d

Answers:


119

执行编译器告诉您的操作,即使用进行重新编译-fPIC。要了解此标志的作用以及在这种情况下为什么需要它,请参阅GCC手册的代码生成选项

简而言之,术语“位置无关代码”(PIC)指的是与内存地址无关的生成的机器代码,即,不对将其加载到RAM中的位置进行任何假设。共享对象(SO)应该仅包含位置无关的代码,因为它们应具有动态更改其在RAM中位置的能力。

最后,您也可以在Wikipedia上阅读它。


3
您能解释一下如何使用-fPIC重新编译吗?
Beni Bogosel 2014年

12
@Beni Bogosel:这很简单。您只需将库的-fPIC所有源文件(翻译单元,例如*.cpp文件)添加到所有编译器调用中。具体的执行方式取决于您使用的构建系统。例如,在CMake中,您可以发出set_target_properties(${LIBRARY_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)。对于这个家伙(使用普通的旧Make),他将不得不做,COMPILE_FLAGS+=-fPIC因为他正在使用此变量来表示库中所有源文件的编译标志集。
亚历山大·舒卡耶夫

1
使用configure启用-fPIC:configure --enable-shared,请参见stackoverflow.com/a/850464/440403
camino

49

在我的情况下,发生此错误是因为make命令期望*.soLDFLAGS环境变量指示的远程目录中获取共享库(文件)。错误的是,那里只有静态库(*.la*.a文件)可用。

因此,我的问题不在于正在编译的程序,而是与它试图获取的远程库有关。因此,我不需要向-fPIC因重定位错误而中断的编译添加任何标志(例如)。相反,我重新编译了远程库,以便共享对象可用。

基本上,这是变相的文件找不到错误。

在我的情况下,由于共享库和静态库都是默认构建的,因此必须在必要程序--disable-sharedconfigure调用中删除放错位置的开关。


我注意到大多数程序都同时构建两种类型的库,因此我的情况可能是一个极端的案例。通常,您可能需要启用共享库,具体取决于默认值。

要使用编译开关和默认值检查您的特定情况,我将阅读随出现的摘要./configure --help | less,通常在可选功能部分中。我经常发现,这种阅读要比依赖程序发展时未更新的安装指南更可靠。


1
完美,“这是变相的文件找不到错误”。在我的情况下,依赖项尚未安装。
Litty

+1在我的情况下,openssl的较新副本是手动生成的,没有共享库就安装了。我尝试构建的库已使用-fPIC编译。无论如何,编译器是否可以识别此错误以给出不太模糊的错误消息,例如“预期找到共享库libssl.so,但仅找到不兼容的静态库/usr/local/ssl/lib/libssl.a。” ?
Rohan Mahy'7

1
谢谢。我有一个make -j,并且此软件包不允许并行执行。
MikeBergmann

就我而言,这行是“ find_library(NGHTTP2_LIB NAMES libnghttp2.a libnghttp2.so libnghttp2.dylib)”。用它来工作之前,什么对我来说,它只是拿起.A一个,后来我把它改为find_library(NGHTTP2_LIB名字libnghttp2.so libnghttp2.a libnghttp2.dylib)”,并开始工作的我关心的是,?
Naba Chinde

1
@NabaChinde恐怕我也无法回答您的问题,因为我缺乏有关您结果的背景信息。我当然会鼓励您提出一个单独的问题,在其中解释您的工作状况和意外行为。
XavierStuvw


9

-no-pie在链接器阶段用选项修复了它:

g++-8 -L"/home/pedro/workspace/project/lib" -no-pie ...

4

只需清理项目即可为我解决。

我的项目是C ++应用程序(不是共享库)。经过大量成功的构建后,我随机出现此错误。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.