编译失败,报错信息为“当制作共享对象时,重定位R_X86_64_32无法用于`.rodata.str1.8'”。

106

我试图在一个64位Cent OS的VPS上从makefile编译这个源代码,但是它不起作用。

以下是完整的错误信息:

# 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

有人知道出了什么问题吗?


9
你是否尝试使用-fPIC重新编译? - Joachim Isaksson
抱歉,我不确定如何做这个。在谷歌上找不到关于“-fPIC”的任何信息。 - user1667191
5
请尝试类似于COMPILE_FLAGS=-c -O3 -w -DLINUX -fPIC -I../SDK/amx/的东西。 - Joachim Isaksson
相关:https://dev59.com/SW025IYBdhLWcg3wSkAq - Ciro Santilli OurBigBook.com
19
如果你在谷歌搜索-fPIC,你肯定会找不到任何内容。移除减号或使用引号“-fPIC”,否则你会忽略所有包含 fPIC 的结果。 - d00d
9个回答

134

按照编译器的要求做,即使用-fPIC重新编译。要了解此标志的作用以及在此情况下为什么需要它,请参见GCC手册的代码生成选项

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

最后,你也可以在维基百科上阅读相关信息。


5
请问您能否说明如何使用 -fPIC 进行重新编译? - Beni Bogosel
16
很简单,您只需为库的所有源文件(翻译单元,例如 *.cpp 文件)的所有编译器调用添加 -fPIC。具体实现方式取决于您所使用的构建系统。例如,在 CMake 中,您可以发出 set_target_properties(${LIBRARY_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)。对于那个人(使用古老的 Make),他需要执行 COMPILE_FLAGS+=-fPIC,因为他正在使用此变量来表示库的所有源文件的编译标志集合。 - Alexander Shukaev
1
启用-fPIC的configure配置选项:configure --enable-shared,请参见https://dev59.com/T3RB5IYBdhLWcg3wa2q2#850464。 - camino

57
在我的情况下,这个错误是由于一个make命令期望从由LDFLAGS环境变量指示的远程目录获取共享库(*.so文件)。但实际上,只有静态库可用(*.la或*.a文件),所以问题不在我编译的程序上,而在于它试图获取的远程库。因此,在编译被重定位错误中断的过程中,我不需要添加任何标志(例如-fPIC)。相反,我重新编译了远程库,使得共享对象可用。
基本上,这是一个伪装成文件未找到错误的错误。
在我的情况下,我需要在必要程序的configure调用中删除一个错放的--disable-shared开关,因为默认情况下既构建共享库又构建静态库。
我注意到大多数程序同时构建两种类型的库,所以我的情况可能是一个特例。一般来说,您可能需要启用共享库,具体取决于默认设置。
为了检查您的特定编译开关和默认设置,我建议阅读出现在./configure --help | less中的摘要,通常在Optional Features部分。我经常发现这种阅读比那些没有随着依赖程序发展而更新的安装指南更可靠。

2
完美,“这只是一个文件未找到的错误伪装。” 在我这种情况下,依赖关系尚未安装。 - Litty
在我的情况下,手动构建了一个更新的openssl副本并安装,但没有共享库。我正在尝试构建的库已经使用-fPIC编译。编译器是否有任何方式可以识别此错误以提供更少的晦涩错误消息,例如“预期找到共享库libssl.so,但只找到不兼容的静态库/usr/local/ssl/lib/libssl.a。”? - Rohan Mahy
1
谢谢。我使用了make -j命令,但该软件包不允许并行执行。 - MikeBergmann
在我的情况下,我有这行代码"find_library(NGHTTP2_LIB NAMES libnghttp2.a libnghttp2.so libnghttp2.dylib)",并且它只选择了 .a 文件,后来我将它更改为 "find_library(NGHTTP2_LIB NAMES libnghttp2.so libnghttp2.a libnghttp2.dylib)",然后它开始工作了。我的担心是,之前它为什么能正常工作? - Nabz C
1
@NabaChinde,恐怕我无法回答你的问题,因为我缺乏关于你的结果的上下文信息。我肯定会鼓励你发布一个单独的问题,在其中解释你的工作情况和意外行为。 - XavierStuvw

22

在链接阶段使用-no-pie选项进行修复:

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

这就是我需要的,以便成功编译。 - KhanKhuu

11

并不总是与编译标志有关, 当使用 distcc 时在 gentoo 上也会出现相同的错误.

原因在于 distcc 服务器使用了未加固的配置文件,而客户端配置文件已被加固。请查看此讨论: https://forums.gentoo.org/viewtopic-p-7463994.html


4

仅仅清理项目就解决了我的问题。

我的项目是一个C++应用程序(不是共享库)。在经历了许多成功的构建之后,我随机地遇到了这个错误。


2

我有同样的问题。尝试使用-fPIC标志重新编译。


0
我们遇到了同样的问题。结果发现是Makefile中混淆了。当链接器是gcc,但C++编译器是clang++时出现了错误。将链接器更改为clang++即可解决问题。

0

0

我知道这个问题是一年前提出的。 我在我的系统上尝试了给定的错误。 我尝试使用Makefile模拟给定的错误并提供此错误。 错误的Makefile(每行以制表符开头而不是多个空格):

all:
    @echo "/usr/bin/gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c";\
    /usr/bin/gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c;\
    echo "/usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp";\
    /usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp;\
    echo "/usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp";\
    /usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp;\
    echo "/usr/bin/g++ -O2 -shared -o "TCP_V1.so" *.o";\
    /usr/bin/g++ -O2 -shared -o "TCP_V1.so" *.o

错误:

  /usr/bin/gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c
  /usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp
  /usr/bin/g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp
  /usr/bin/g++ -O2 -shared -o TCP_V1.so *.o
  /usr/bin/ld: one.o: relocation R_X86_64_32 against `.rodata.str1.1'
  can not be used when making a shared object; recompile with -fPIC
  one.o: error adding symbols: Bad value
  collect2: error: ld returned 1 exit status

更新的 Makefile:

all:
      @echo "/usr/bin/gcc -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c";\
      /usr/bin/gcc -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c;\
      echo "/usr/bin/g++ -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp";\
      /usr/bin/g++ -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp;\
      echo "/usr/bin/g++ -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp";\
      /usr/bin/g++ -fPIC -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp;\
      echo "/usr/bin/g++ -O2 -shared -o "TCP_V1.so" *.o";\
      /usr/bin/g++ -O2 -shared -o "TCP_V1.so" *.o

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接