【问题标题】:Linker error: "relocation R_X86_64_PC32 against symbol `xmlFree' ... recompile with -fPIC" but offending library was already compiled with -fPIC链接器错误:“针对符号 `xmlFree' 重新定位 R_X86_64_PC32 ... 使用 -fPIC 重新编译”但有问题的库已经使用 -fPIC 进行了编译
【发布时间】:2020-08-22 10:21:24
【问题描述】:

我正在尝试构建一个共享库。我的目标是将所有依赖项作为静态库拉到一个共享库中。我的理解是,这可以通过-Wl,--whole-archiveflag 来完成。这是我负责配置共享库的 CMake 脚本的 sn-p。

    # shared library
    add_library(semsim SHARED "${SEMSIM_HEADERS}" "${SEMSIM_SOURCES}") # created the shared library
    #fPIC for linux shared library strs
    set_property(TARGET semsim PROPERTY POSITION_INDEPENDENT_CODE ON) #turn fPIC on 
    target_compile_options(semsim PRIVATE -Wl,--whole-archive) # enable pulling static libraries into shared library

我在尝试编译时遇到的错误(详细模式已打开)是:

/usr/bin/c++ -fPIC -std=c++14 -g  -shared -Wl,-soname,libsemsim.so -o libsemsim.so CMakeFiles/semsim.dir/CurlGet.cpp.o CMakeFiles/semsim.dir/RDFNode.cpp.o CMakeFiles/semsim.dir/Subject.cpp.o CMakeFiles/semsim.dir/Predicate.cpp.o CMakeFiles/semsim.dir/Resource.cpp.o CMakeFiles/semsim.dir/Triple.cpp.o CMakeFiles/semsim.dir/SemsimUtils.cpp.o CMakeFiles/semsim.dir/MetaID.cpp.o CMakeFiles/semsim.dir/XmlAssistant.cpp.o CMakeFiles/semsim.dir/Reader.cpp.o CMakeFiles/semsim.dir/Editor.cpp.o CMakeFiles/semsim.dir/Writer.cpp.o CMakeFiles/semsim.dir/RDF.cpp.o CMakeFiles/semsim.dir/Participant.cpp.o CMakeFiles/semsim.dir/PhysicalEntity.cpp.o CMakeFiles/semsim.dir/PhysicalPhenomenon.cpp.o CMakeFiles/semsim.dir/PhysicalProcess.cpp.o CMakeFiles/semsim.dir/PhysicalPropertyResource.cpp.o CMakeFiles/semsim.dir/PhysicalForce.cpp.o CMakeFiles/semsim.dir/Query.cpp.o CMakeFiles/semsim.dir/SemsimCombineArchive.cpp.o CMakeFiles/semsim.dir/Triples.cpp.o ../../third_party/libCombine-0.2.3/INSTALL/lib/libcombine-static.a ../../third_party/zipper/INSTALL/lib/libZipper-static.a ../../third_party/zlib-1.2.11/INSTALL/lib/libz.a /usr/local/lib/libbz2.a /usr/local/lib/libxml2.a -ldl -lbz2 -lz -lcurl -lxslt 
/usr/bin/ld: /usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

但是,根据this的问题,/usr/local/lib/lxml2.a已经编译好了fPIC

(base) ciaran@DESKTOP:/usr/local/lib$ ls
cmake            libcharset.so.1.0.0  libraptor2.a         librasqal.la        librdf.so        libxml2.so.2
libbz2.a         libcurlcpp.a         libraptor2.la        librasqal.so        librdf.so.0      libxml2.so.2.9.10
libcharset.a     libiconv.la          libraptor2.so        librasqal.so.3      librdf.so.0.0.0  pkgconfig
libcharset.la    libiconv.so          libraptor2.so.0      librasqal.so.3.0.0  libxml2.a        python2.7
libcharset.so    libiconv.so.2        libraptor2.so.0.0.0  librdf.a            libxml2.la       python3.6
libcharset.so.1  libiconv.so.2.6.1    librasqal.a          librdf.la           libxml2.so       xml2Conf.sh
(base) ciaran@DESKTOP:/usr/local/lib$ readelf -d libxml2.a | grep TEXT
(base) ciaran@DESKTOP:/usr/local/lib$

这让我相信,也许我误解了错误信息 - 有人能解释一下这里发生了什么吗?

【问题讨论】:

  • 顺便说一句,--whole-archive 是一个 linker 选项,将其传递给 compiler(通过 target_compile_options)没有意义。

标签: c++ linux cmake shared-libraries fpic


【解决方案1】:

您没有误解错误消息,或者至少没有严重误解。

但是,根据this的问题,/usr/local/lib/lxml2.a 已经编译fPIC了

你得出这个结论是因为命令:

/usr/local/lib$ readelf -d libxml2.a | grep TEXT

什么都不输出,说明你选择了the second most popular answer 这个问题,尽管在撰写本文时,它的投票率不如the most popular answer

我猜你这样做是因为最流行的答案告诉你如何测试目标文件 PIC-ness,并且您想测试一个库,就像第二个最受欢迎的答案一样。要么 也许是因为您首先尝试了最受欢迎的答案,它表明您的 libxml2.a PIC。

但是第二个最受欢迎的答案是测试一个共享库,你用它来测试 static 库中的目标文件。共享库与 目标文件或此类的静态库,并且给出此答案的问题询问如何测试 目标文件的 PIC 特性。所以这个答案没有回答这个问题:真的 它建议如何测试名称如共享库的文件是否实际上是 共享库。

最受欢迎的答案确实回答了问题,如果是正确答案,那么 它也适合您,因为链接器已诊断出:

/usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' \
can not be used when making a shared object; recompile with -fPIC

libxml2.a中存档的目标文件uri.o不是PIC。

但最流行的答案,尽管很受欢迎,却是无效的。 它提出的 PIC-ness 测试——没有支持论据——可以 将非 PIC 对象文件误识别为 PIC(您可能观察到)。

that 问题没有答案 对你来说是一个正确的答案,为什么不重要。系统链接器本身 是关于目标文件是否与位置无关的最终权威。 除了尝试将目标文件链接到 DSO 之外的任何单行测试都只是一种尝试 对链接器进行二次猜测:如果它的判断与 链接器意味着测试已损坏,而不是链接器。

而且您已经知道链接器的判断。它试图链接libxml2.a(uri.o) 进入 DSO 发现它不能,因为它包含一个非位置无关的 搬迁记录。

您拥有的/usr/local/lib/libxml2.a 是建立在传统的 默认假设其中存档的目标文件不需要编译为 与位置无关的代码(使用-fPIC),因为静态库只会 输入到非位置无关的可执行文件的链接中。如果你想 链接一些 PI 二进制文件,然后将其与共享库 libxml2.so 链接, 根据定义,这是 PI。您的libxml2.a 还使用编译器构建 默认情况下不发出 PI 对象代码。您当前的情况可能是 编译器仍然具有越来越过时的特性,但您不需要找到 出去。

您需要将您的本地libxml2 安装替换为其中的对象 libxml2 中的文件已使用 fPIC 编译。如果您已经知道如何执行此操作,则可以跳过其余部分并继续进行。

如果你在某个地方得到了构建的 libxml2 的源代码包 并安装并且你想坚持那个版本,然后cd进入它的根目录并运行:

make uninstall

否则,通过以 root 身份删除所有匹配的文件和符号链接来删除安装 /usr/local/lib/libxml2 和目录/usr/local/include/libxml2

如果您想坚持使用已有的源代码包(您在其中运行 make uninstall), 然后,在其根目录中,运行:

make distclean

恢复到原始状态。

如果您没有想要坚持使用的源代码包,请从 https://gitlab.gnome.org/GNOME/libxml2/ 克隆或下载并提取最新的源代码包, 然后cd进入根目录并运行:

./autogen.sh

生成构建系统。

到目前为止,无论你做了什么,然后在包根目录中运行:

./configure CFLAGS=-fPIC [any other non-default configuration options]

如果成功完成,则运行:

make

如果成功完成,则以root身份运行:

make install

如果成功完成,那么/usr/local/lib/libxml2.a 将 重新创建包含 PI 对象文件,您将能够链接您的 反对它的共享库。

如果您不确定[any other non-default configuration options] ./configure 命令,然后运行:

./configure -h

事先寻求帮助和/或寻求建议。

【讨论】:

  • 哇,感谢您的详细回答。我很感激你的努力!事实上,我已经通过获取源代码并使用CMAKE_POSITION_INDEPENDENT_CODE=ON 重建解决了这个问题,我猜这与您的建议相同。你确实帮助我理解了这里发生了什么。
猜你喜欢
  • 2013-01-24
  • 2013-09-20
  • 1970-01-01
  • 2021-09-03
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
相关资源
最近更新 更多