请教各位 centos 7.9 通过 devtoolset 启用 c++14/17 时遇到的链接问题

4 月 1 日
 Noicdi

这是一个 Linux c++ 程序,编译和部署均在 centOS 7.9/gcc 4.8.5 的环境上。这个程序需要对接多种证券交易柜台提供的交易 sdk (头文件和动态库),这些动态库大多是 gcc 4.8.5 编译出来的。根据 cmake 配置,程序在编译期决定最终链接哪种交易 sdk 的动态库,完成编译链接。也就是说,虽然要适配多种 sdk ,但实际上运行期只加载了某一家的动态库。

基于 gcc 4.8.5 ,只能使用 c++11 ,如果想使用 c++14/17 ,那么可能需要考虑在高版本发行版中编译程序,同时打包对应的 gcc 相关的动态库。我的理解是二进制程序所需的动态库依赖的 glibc 可能与 centos 7.9 提供的不符。那么这个场景下,可以考虑 rhel/centos 提供的 devtoolset ,他们使用的是当前发行版提供的 glibc 。

devtoolset 9/10/11 提供了高版本的 gcc ,支持了 c++11/14/17 ,使用的也是发行版对应的 glibc 。但是 libstdc++.so 呢?在询问 ai 时,提到的方案就是说把 devtoolset 提供的 libstdc++.so 和二进制程序打包部署,设置 library rpath 来加载。我考虑说,如果我使用的是 devtoolset 中提供的 libstdc++.so ,那么程序在运行时加载的就是这个版本的,又会与交易 sdk 的动态库所需的版本不符,可能会产生问题。ai 也说是这么个理儿。我就放弃了使用 c++14/17 的念头。

但是我今天想起这个事情,又想折腾一下,我发现 ai 提到 devtoolset-9 的 libstdc++.so.6 在 /opt/rh/devtoolset-9/root/usr/lib64,我在这个目录下面根本没翻到 libstdc++.so.6 ,而是翻到了 /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/libstdc++.so,这玩意儿不是动态库,而是个 ASCII text ,内容如下:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
INPUT ( /usr/lib64/libstdc++.so.6 -lstdc++_nonshared )

也就是说,实际上 devtoolset 并不提供 libstdc++.so ,而是使用的发行版默认的;同时通过 /opt/rh/devtoolset-9/root/usr/lib/gcc/x86_64-redhat-linux/9/libstdc++_nonshared.a 来补充高版本 c++ 标准库所需的实现?

那我是不是可以通过 devtoolset 来使用 c++14/17 ,同时链接 centos 7.9 提供的 libstdc++.so.6 给二进制程序和交易 sdk 动态库使用,不需要担心冲突问题,顶多在用个 GLIBCXX_USE_CXX11_ABI 来处理问题?

1791 次点击
所在节点    C++
6 条回复
Noicdi
4 月 1 日
我只找到了 devtoolset 的使用,没找到啥文档来说明这玩意儿的工作原理是啥,所以不知道这么搞会不会有啥问题
whenov
4 月 1 日
你关于 libstdc++.so 的猜想应该是对的,但网上的资料很少,我只找到这个评论 https://stackoverflow.com/questions/50712896/devtoolset-6-is-using-system-libstdc-and-cant-link#comment88490376_50712896
elechi
4 月 1 日
这个测试一下就知道了
Noicdi
4 月 1 日
@whenov #2 从这里的只言片语、我对 devtoolset 的观察、观察结果提交给 ai 纠错,运行逻辑似乎就是依赖本地动态库+静态库补充缺失符号。那感觉可能可以这么玩。

另外提一嘴,我发现我的情况(第三方库依赖本地 libstdc++)比帖子里的情况(第三方库依赖高版本 libstdc++),好处理很多
xinyu391
4 月 8 日
C++ 库,可以静态链接,
你可以把 需要 C++14/17 的代码,独立编译为动态库,并静态链接 devtool 带的 C++静态库,主要需要把对外接口封装为 C 接口,同时最好把非导出符号隐藏掉。
这样,你主程序,就可以就 gcc485 编译 链接三方库,和你这个库了。
haohaolee
7 天前
devtooset 被发明出来的目的之一就是复用系统的 glibc 和 libstdc++,继而兼容系统原有的 libraries 。
原理是把符号分开处理,如果系统里面原来就有的符号(比如 libstdc++ 的 C++11 )就直接动态链接,如果是不存在的符号( C++14/C++17 ),就静态链接到生成的二进制文件里面

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1202807

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX