【问题标题】:ld fails to link a static library to a dynamic library even when all files are compiled with fPIC即使所有文件都使用 fPIC 编译,ld 也无法将静态库链接到动态库
【发布时间】:2023-04-10 06:38:01
【问题描述】:

在 CentOS 7 x64 系统上,我构建了启用了 -fPIC 的最新 Boost 1.61.0。我正在尝试将 libboost_log.a 链接到我正在构建的动态库,以便我的库的用户不必安装 Boost。使用 CentOS 7 附带的库存 GCC 4.8.5 成功,但当我使用 devtoolset-4 中的 GCC 5.2.1 时失败。

这是错误:

/opt/rh/devtoolset-4/root/usr/libexec/gcc/x86_64-redhat-linux/5.2.1/ld: /opt/boost/lib/libboost_log.a(attribute_name.o): relocation R_X86_64_32 against `_ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43' can not be used when making a shared object; recompile with -fPIC
/opt/boost/lib/libboost_log.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

我是如何构建 Boost 的: ./b2 -j6 -q -d+2 cxxflags=-fPIC cflags=-fPIC variant=release Boost 默认使用-O3。因此,我的程序也使用了-O3。

用于构建我的库的命令: /opt/rh/devtoolset-4/root/usr/bin/c++ -fPIC -O3 -g -DNDEBUG -shared -Wl,-soname,libfoobar.so.0 -o libfoobar.so.0.5 foobar.cc.o -L/opt/boost/lib /opt/boost/lib/libboost_filesystem.a /opt/boost/lib/libboost_log.a /opt/boost/lib/libboost_program_options.a -lpthread -Wl,-rpath,/opt/boost/lib

证明 libboost_log.a 是用 fPIC 构建的:

$ objdump -r /opt/boost/lib/libboost_log.a | grep _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 0000000000000002 R_X86_64_32 _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 0000000000000011 R_X86_64_32S _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 00000000000001a3 R_X86_64_32 _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 00000000000001be R_X86_64_32S _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 000000000000001c R_X86_64_32S _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43 0000000000000021 R_X86_64_32 _ZZN5boost3log12v2s_mt_posix3aux14lazy_singletonINS1_14attribute_name10repositoryENS_10shared_ptrIS5_EEE3getEvE29_boost_log_once_block_flag_43

想法: 如您所见,libboost_filesystem.a 似乎链接正常,只是 libboost_log.a 无法链接。我现在可以检查什么?欢迎任何提示。谢谢!

【问题讨论】:

  • 在构建 boost 时编译器是否相同,即/opt/rh/devtoolset-4/root/usr/bin/c++?如果 /usr 和 /opt/rh/devtoolset-4/root/usr 中有 C++ 头文件并且它们不匹配,则可能会出现一些问题。
  • @J.J.Hakala 当然我使用的是安全版本。让我通过在库中找出字符串来证明这一点……等等,笏? Boost Build 不尊重scl enable devtoolset-4?!
  • @J.J.Hakala 你是对的。我检查了 Boost 没有正确构建。如果您可以添加答案,我会将其标记为正确。谢谢!

标签: c++ linux gcc boost


【解决方案1】:

使用的编译器 /opt/rh/devtoolset-4/root/usr/bin/c++ 不是 /usr/bin/c++。如果这两个编译器具有不同版本的 C++ 头文件,它们可能会生成具有不同方法符号的库(名称修改)。如果编译器版本不同,可能还有其他原因导致链接失败。

我建议编译 C++ 代码,以便在编译每个 C++ 库时至少 gcc 的主要版本是相同的。

【讨论】:

  • 我想补充一点,根本原因是 Boost Build (b2) 不尊重 scl enable devtoolset-4 并且仍然使用 /usr/bin/g++。我必须通过在project-config.jam 中设置using gcc : : path/to/gcc 来告诉它使用devtoolset-4 编译器。
猜你喜欢
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-07
  • 1970-01-01
相关资源
最近更新 更多