1

我正在尝试链接到使用 Boost 的第 3 方库。我已经链接到正确的 boost 库 (libboost_program_options.a),但仍然没有找到它。

错误消息(为清楚起见,进行了一些格式化):

undefined reference to `boost::program_options::validate(boost::any&, 
                              std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, 
                              std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, 
                              int)'

nm --demangle libboost_program_options.a | grep 验证

boost::program_options::validate(boost::any&,                                   std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, 
                                  bool*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, 
                                  std::string*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::string, std::allocator<std::string> > const&, 
                                  bool*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::string, std::allocator<std::string> > const&, 
                                  std::string*, 
                                  int)

第二个记录看起来很相似,但显然不够接近。知道如何编译 Boost 以获得与库中的内容匹配的签名吗?我向图书馆所有者提出请求,以查看他们正在使用的 Boost 版本等,但尚未收到回复。

这是在使用 g++ 4.8.5 版的 CentOS 7 机器上。但是我试图链接的库大量使用 C++11,并且是用 g++ v 6.1 编译的,所以我安装了 devtoolset-6,它为我提供了一个 g++ 6 环境(g++ 版本 6.3.1)

我从头开始下载并构建了 Boost (v1.65.1),因此它是使用相同的编译器构建的,而不是系统版本。

编辑...我认为 John Zwinck 走在正确的轨道上,但我无法让 boost 库编译到新的 ABI。

validate() 函数位于 value_semantic.cpp

将构建剥离到基础,并添加讨论的标志:

g++ -std=c++11 -D_GLIBCXX_USE_CXX11_ABI -c -o test.o libs/program_options/src/value_semantic.cpp

nm --demangle test.o | grep validate
00000000000008b6 T boost::program_options::validate(boost::any&, std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, bool*, int)
0000000000000c02 T boost::program_options::validate(boost::any&, std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, std::string*, int)
00000000000005f2 T boost::program_options::validate(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, bool*, int)
0000000000000b9a T boost::program_options::validate(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, std::string*, int)

_GLIBCXX_USE_CXX11_ABI 宏是否仅适用于 gcc 5.1?

4

3 回答 3

3

看来您std::string在 C++11 中与 GCC Dual ABI 发生冲突:https ://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

您的程序正在尝试使用

std::__cxx11::basic_string<char>* 

但是你的 Boost 库有

std::basic_string<char>*

这意味着您的 Boost 库是使用 5.1 之前的 GCC 构建的,或者关闭了新的 ABI。无论哪种情况,您都可以通过添加以下编译器标志在关闭新 ABI 的情况下编译您自己的代码:

-D_GLIBCXX_USE_CXX11_ABI=0

通过用它编译你的程序,就可以使用系统提供的(旧的 ABI)Boost 库。但接下来的问题将是您的供应商使用哪个 C++ ABI 编译他们的代码(询问他们,或__cxx11在他们的库中查找)。

于 2017-11-11T02:37:24.690 回答
1

https://stackoverflow.com/a/52611576/981959所述,您不能cxx11在 GCC 的 devtoolset 版本中使用新的 ABI(因为 devtoolset GCC 的全部意义在于保持与系统 libstdc++ 的 ABI 兼容)。

您的选择是:

  • 获取使用与 gcc4 兼容的 ABI 的第三方库的新版本,因此您可以使用 devtoolset 编译器链接到它;或者
  • 自己构建和安装更新的 GCC,使用它而不是 devtoolset GCC,并确保在运行时使用libstdc++.so的 GCC 。
于 2018-10-02T15:59:51.270 回答
0

好的,我想我已经弄清楚为什么我不能让 g++ 生成 cxx11 签名(新 ABI)。

如果我使用 -v 选项运行 g++:

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-6/root/usr/libexec/gcc/x86_64-redhat-linux/6.3.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/devtoolset-6/root/usr --mandir=/opt/rh/devtoolset-6/root/usr/share/man --infodir=/opt/rh/devtoolset-6/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-default-libstdcxx-abi=gcc4-compatible --with-isl=/builddir/build/BUILD/gcc-6.3.1-20170216/obj-x86_64-redhat-linux/isl-install --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 6.3.1 20170216 (Red Hat 6.3.1-3) (GCC)

请注意“配置为”字段下的以下内容

--with-default-libstdcxx-abi=gcc4 兼容

我相信这意味着 g++ 的 devtoolset-6 版本是使用“内置”的旧式 ABI 构建的,因此它不会响应 _GLIBCXX_USE_CXX11_ABI 宏。

根据此链接:https ://gcc.gnu.org/onlinedocs/libstdc++/manual/configure.html

--with-default-libstdcxx-abi=OPTION 设置 _GLIBCXX_USE_CXX11_ABI 宏的默认值(参见宏)。默认是 OPTION=new 将宏设置为 1,使用 OPTION=gcc4-compatible 将其设置为 0。此选项不会更改库 ABI。

它似乎只会更改 _GLIBCXX_USE_CXX11_ABI 的默认值,但在我的尝试中设置 _GLIBCXX_USE_CXX11_ABI 没有任何效果。

对此并不积极,但这是我目前的工作理论。任何额外的见解表示赞赏。

于 2017-11-15T22:41:32.297 回答