C++动态库向前兼容的能力,真是一言难尽。

2023-01-17 09:48:13 +08:00
 tool2d
公司有个运行在外网的生产环境,是 linux 早期版本,本着只要代码能运行,就没人去动的原则,内核一直比较老。

然后我想加一点小功能,想着现在 clang 那么强大了,跨平台编译应该轻轻松松,然而测试结果让我大跌眼镜。

目前几乎所有的 clang 交叉编译环境,都是基于新版本的 GLIBC ,相当于 VC 的 Runtime Lib ,而这货竟然严重依赖于系统内核版本?测试了好几个打包编译器,都是顺利生成 ELF ,可运行报错,提示让先升级内核。

无奈,一点点换老款编译器,从 2022 年的 clang ,到 2020 年的 clang ,到 2012 年的 gcc, 再到 2007 年的 gcc ,最后一个终于运行成功!

硬着头皮,用最原始的编译器,写最炫酷的 2023 新代码。
7501 次点击
所在节点    C++
53 条回复
uiosun
2023-01-17 09:51:12 +08:00
路过,向前兼容?那个不是 JAVA 的 Slogan 之一吗——JAVA8 永远的神……
lichao
2023-01-17 09:52:59 +08:00
这方面无敌的还是 M$
Crawping
2023-01-17 09:54:12 +08:00
c++ 一大特点
生产环境与编译环境绑定..
tool2d
2023-01-17 09:55:42 +08:00
@uiosun 是向后兼容,不停的换编译器,脑袋都快裂开了。

内心非常不愿意用老款 GCC ,又不得不用的那种感觉,不知道怎么形容。
ysc3839
2023-01-17 09:59:07 +08:00
glibc 按理来说不依赖内核吧?不过只能新版本 glibc 兼容旧版本编译的程序,不能反过来。
MSVC 这边,之前是只能同版本兼容,但是能多版本共存。VS2015 开始可以跨版本兼容,但是如果程序使用了新版本加入的函数那就不兼容旧版本。不过 MSVC 一直可以静态链接。
besto
2023-01-17 10:01:27 +08:00
1, C++11 之前的 C++ 真的忍不了;
2, clang 这种有很多默认检查,但基本可以关,这甚至直接导致 github 上一大堆开源代码拉下来编不过;
3, 一般 gcc 都是谈版本不谈年份。。。交叉编译,难道是嵌入式? linaro 最新的才 7.5...arm 官网有 9.x 的,不过 2012 年的 gcc 不能用是什么鬼
wingkwanli888
2023-01-17 10:03:55 +08:00
2023 年了为什么 c++ 还没有 npm, maven 之类的包管理器
DsuineGP
2023-01-17 10:04:56 +08:00
@ysc3839 glibc 是内核向用户态暴露的接口, 肯定依赖内核啊
tool2d
2023-01-17 10:04:57 +08:00
@ysc3839 依赖的,你 google 搜一下"glibc kernel compatibility",遇到这种问题,完全无解。

好像可以通过修改 GLIBC 里的 MIN_KERNEL_SUPPORTED 来屏蔽一些功能,支持老内核的 linux ,可这货一般没人去自己编译。

而且 GLIBC 和 VC Runtime 不一样,加了太多东西,静态编译会有各种奇怪问题,真是心力交瘁。
lhbc
2023-01-17 10:08:32 +08:00
想要不依赖系统提供的库,不想用内核的 API ,就自己整齐一套
又想调用系统库,又要调用系统 API ,还想不依赖版本,这种好事哪有这么容易

自己把东西整齐活了,就不依赖了
ysc3839
2023-01-17 10:09:41 +08:00
@DsuineGP 是吗?不是 C 运行库吗?按理来说应该不太依赖系统功能的。

@tool2d 那我就不知道了,我只遇到过新 glibc 版本编译的程序拿到旧系统里运行不了的情况。
Noicdi
2023-01-17 10:11:06 +08:00
最近在搞公司项目一个老模块依赖的 openssl 升级,体会到了这种兼容问题,整得我狗脑子要炸了
iold
2023-01-17 10:18:19 +08:00
@wingkwanli888 #7 vcpkg ,巨硬的,我一直在用
bitdepth
2023-01-17 10:23:14 +08:00
試過靜態編譯?
其實是你 toolchains 有問題
luvroot
2023-01-17 10:24:18 +08:00
用 Go 把,静态依赖编译,让你不用考虑环境的问题
DsuineGP
2023-01-17 10:25:24 +08:00
@tool2d 如果依赖不多编译不麻烦的话, 可以尝试一下静态链接 musl(替换 glibc) 和 libc++(替换 libstdc++)

@ysc3839 称为「 C 运行库」是因为 libc 会提供大量接口给用户态程序, 比如说 open 等等, 实际上底层就是将内核的 syscall 进行封装并暴露 abi 接口. 并且程序也是可以不依赖「 C 运行库」的, 比如 linux 内核.
tool2d
2023-01-17 10:27:46 +08:00
@bitdepth 静态编译后运行,运行也报内核太低,这点就很迷了。

toolchains 应该没问题,因为能正常生成 ELF ,我想在放到普通桌面 linux 上,大概率也能顺利运行。只是服务器比较特殊,不敢随便动内核。

想想还是 MS 好啊,静态编译 CRT ,基本上就没什么负担了。
Reficul
2023-01-17 10:31:01 +08:00
@luvroot #15 Go 也有内核版本依赖,1.18 已经去掉了很多对很多老内核的系统调用兼容。
bitdepth
2023-01-17 10:34:06 +08:00
你只是 ABI 相容,不代表 sysycall 相容
你大過是 timestamp 之類轉換為 64bits 這種 ioctl 出問題了
junmoxiao
2023-01-17 11:09:25 +08:00
有一说一上面提到的问题都可以解决,看看 vc-ltl 那个项目,xp 到最新的 win11 ,就算 api 有变化,一样能兼容。从原理上来说 linux 下也能做到,只是没人做

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

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

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

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

© 2021 V2EX