将静态库链接到共享的:标头中的枚举类->针对未定义的符号重新定位R_X86_64_PC32

时间:2018-09-08 10:51:21

标签: c++ linux gcc shared-libraries static-linking

我想做什么

我尝试将代码分成模块,并使用-fPIC选项将其编译为静态库。

最后,它们将使用--whole-archive链接到共享库,该共享库也使用-fPIC进行编译。

对于整个编译,我将CMake generated make filesC++17GCC8一起使用!

enter image description here

问题

尝试使用GCC8 x86_64libstdc++_pic这样做会失败:

  

/ usr / bin / x86_64-linux-gnu-ld:CMakeFiles / shirabeengine.dir / code / source / core / engine.cpp.o:针对未定义符号'_ZN6enginelsERSoRKNS_13EEngineStatusE'的重定位R_X86_64_PC32无法使用宾语;用-fPIC重新编译   / usr / bin / x86_64-linux-gnu-ld:最终链接失败:值错误   collect2:错误:ld返回1退出状态


执行的步骤

我已完成验证,所有库均已使用-fPIC正确构建并包含重定位信息:

  1. 我解压缩了所有静态库ar -x <name>.a
  2. 我在每个目标文件上运行readelf --relocs <name>.cpp.o | egrep '(GOT|PC|PLT|JU?MP_SLOT)'来查看它是否包含重定位信息。

节选:

  

000000000036 217600000004 R_X86_64_PLT32 0000000000000000 _ZN9__gnu_cxx17__norma-4   00000000004e 161000000004 R_X86_64_PLT32 0000000000000000 __stack_chk_fail-4   000000000019 217700000004 R_X86_64_PLT32 0000000000000000 _ZNK9__gnu_cxx17__norm-4   000000000028 217700000004 R_X86_64_PLT32 0000000000000000 _ZNK9__gnu_cxx17__norm-4   000000000044 1ff700000004 R_X86_64_PLT32 0000000000000000 _ZNSt12_Vector_baseIN6-4   00000000005e 1ff800000004 R_X86_64_PLT32 0000000000000000 _ZSt8_DestroyIPN6engin-4   000000000014 212f00000004 R_X86_64_PLT32 0000000000000000 _ZNKSt12__shared_ptrIN-4   000000000014 217800000004 R_X86_64_PLT32 0000000000000000 _ZNSt13__future_base13-4   000000000020 213100000004 R_X86_64_PLT32 0000000000000000 _ZNKSt19__shared_ptr_a-4   000000000014 212f00000004 R_X86_64_PLT32 0000000000000000 _ZNKSt12__shared_ptrIN-4   000000000025 18b300000004 R_X86_64_PLT32 0000000000000000 _ZSt20__throw_future_e-4   000000010248 089e00000002 R_X86_64_PC32 0000000000000000 .text._ZN9__gnu_cxxeqI + 0   000000010268 089f00000002 R_X86_64_PC32 0000000000000000 .text._ZNSt6vectorIN6e + 0   000000010271 007f00000002 R_X86_64_PC32 0000000000000000 .gcc_except_table + e68   00000001028c 08a000000002 R_X86_64_PC32 0000000000000000 .text._ZNKSt13packaged + 0   0000000102ac 08a100000002 R_X86_64_PC32 0000000000000000 .text。 ZNSt13已打包 + 0   0000000102cc 08a200000002 R_X86_64_PC32 0000000000000000 .text._ZN9__gnu_cxx17_ + 0   0000000102ec 08a300000002 R_X86_64_PC32 0000000000000000 .text._ZNK9__gnu_cxx17 + 0

  1. 如gcc编译器选项参考所述,我运行readelf --debug-dump=macro <name>.o | grep __PIC__来查看_PIC_宏是否已定义并设置为2

节选:

  

DW_MACRO_define_strp-lineno:0宏: PIC 2

  1. 我检索了50多篇文章,stackoverflow条目和答案,所有这些都与未解决的符号相关,这些符号与.cpp文件中定义的功能/方法有关。在我的情况下,它是在头文件中定义的符号,找不到该文件, 这就是为什么我提出了另一个问题。

结果

所有测试均验证了静态库和共享库的每个目标文件的-fPIC编译和重定位符号存储成功。

唯一无效的东西: 如链接器错误所报告,在命名空间enum class EEngineStatus中包含engine。符号_ZN6enginelsERSoRKNS_13EEngineStatusE不包含在受影响的engine.cpp.o中。


怀疑的影响力

我将其中一个静态库与vulkan SDK链接,据我所知,该库尚未-fPIC编译。

这会中断与vulkan SDK无关的库的整个链接吗?


帮助

有人知道我在做什么吗?

我衷心希望,任何人都可以提供帮助。 我的知识显然还很有限。

提前谢谢您。

解决方案

在@jww写下答案之前,我将在此处提供该答案供其他人使用。

事实证明标题已处理,但我不理解该消息。

由于@jww,我学会了如何对未定义的符号进行解贴:

  

echo _ZN6enginelsERSoRKNS_13EEngineStatusE | c ++ filt

这产生了未实现的功能,因此丢失了,我能够解决问题。

0 个答案:

没有答案