不同版本的 Linux 编译的 c/c++程序是否通用

2021-01-29 18:04:02 +08:00
 lbmjsls1

一直有个疑问,因为今天推荐的 linux 帖子很多,自己也想试试其他系统,换个口味。

问题就是,公司的线上服务器是 debian,所以开发机也是 debian,c++程序。是否可以在其他版本的 linux 下开发编译,然后在 debian 的系统上运行。

或者退而求其次,在 debian 系的系统上开发编译,然后在 debian 的系统上运行。

不考虑配置编译服务器等情况,只是好奇这种跨 linux 的是否可以通用。比如 ubuntu/suse/arch 上编译的程序是否可以在 debian 上正常运行性。

7983 次点击
所在节点    Linux
49 条回复
QBugHunter
2021-01-29 18:11:16 +08:00
可以
不过如果要调用本地的.so 的话回有点问题,
chenzhekl
2021-01-29 18:12:47 +08:00
没有问题,因为都是 Linux 内核。自己稍微管理好一下依赖就行。
v2webdev
2021-01-29 18:14:59 +08:00
动态链接库会有问题。
paoqi2048
2021-01-29 18:17:12 +08:00
不同版本的编译器可能存在 ABI 不兼容的问题
codehz
2021-01-29 18:27:12 +08:00
不一定,有很多因素可以导致差异,有些好解决,有些只能规避
比如前面提到的共享库版本问题,这个解决起来就是整一个容器或者最简单一个 chroot 环境,在里面编译就肯定兼容了
必须规避的就是由于 cpu 指令集的差异造成的问题,这个时候就得对着目标设备的 cpu 特性开编译选项了。。。
wangkun025
2021-01-29 18:28:45 +08:00
不同版本的 debian 估计都会有问题吧。更别提不同的发行版了。
玩玩都可以。工作就算了。
northisland
2021-01-29 18:31:41 +08:00
能跑是巧合。。。

linux 内核 abi 更新是一方面问题,
编译 c++库异常处理,可以用多种 c++abi,这个不一致,导致各种异常随机坑。

https://cloud.tencent.com/developer/article/1357674
https://maskray.me/blog/2020-12-12-c++-exception-handling-abi#%E4%B8%AD%E6%96%87%E7%89%88
superrichman
2021-01-29 18:31:46 +08:00
弄成 appimage 就行
pkookp8
2021-01-29 18:32:11 +08:00
不同 libc 编译出来的都不一定不能用
某些接口如果变化了会出现 crash 或异常,如果没有,则能正常运行
chinvo
2021-01-29 18:35:46 +08:00
动态库有差异的话比较麻烦

比如在 Fedora 23 上编译的程序,在 RHEL 8 上都不能直接运行,libc 不一样

当然你可以静态编译或者打包动态库进去
northisland
2021-01-29 18:37:05 +08:00
Rasphino
2021-01-29 18:39:34 +08:00
用 Musl 加静态链接,基本不会有问题
3dwelcome
2021-01-29 18:45:38 +08:00
写简单的 C++肯定没问题,中等的会有各种小问题(比如楼上提到的 libc,so 问题),超大型项目的 Cross Compile 就算了吧。
老老实实装一个 debian gcc/clang,比什么都好。
azenk
2021-01-29 19:19:55 +08:00
内核版本也是有限制的,你 file 一下可执行文件就可以看到可运行这个程序的内核的最低版本,只不过这个版本一般都很低,发行版本通常都可以满足
bruce0
2021-01-29 19:26:31 +08:00
不用动态链接库, 项目中没有太多外部依赖,应该问题不大

用了动态链接库, gcc 版本相同, 或者说 很多核心的.so 相同 问题应该也不大

主要写 go C++不太熟悉 可能说的不专业
guo4224
2021-01-29 20:12:07 +08:00
musl
ipwx
2021-01-29 20:15:37 +08:00
1 、如果你有本事重新编译一遍所有依赖库(并带上,就好像带了一堆 dll 的 windows 程序那样),或者静态链接依赖库,感觉内核版本差不多的话,哪个发行版都能随便用你编译出来的程序。
2 、你可以用 docker
xcstream
2021-01-29 20:42:22 +08:00
问题不大
biochen
2021-01-29 20:48:26 +08:00
影响兼容性的原因大概有动态链接库、glibc 版本、内核版本等,不过很多时候都是能兼容的。

我的经验是,单位的超算是 Redhat,没有管理员权限,编译 C++程序经常缺少库,手动安装库又非常麻烦。我的一个办法就是在一台 centOS 虚拟机上编译好,上传到超算上面使用。

你的应该是生产环境不想安装那么多的开发库,开发环境编译好之后,直接运行在生产环境中,这个没有问题的。怕不兼容,尽量 静态链接 + 开发环境和生产环境使用同一个 linux 发行版。
jim9606
2021-01-29 21:19:54 +08:00
系统调用(System Call Interface)是比较稳定的,也就是说你用到的系统调用大概率在十年前的内核上都有。这也是 docker 能好用的原因之一。

目前看来比较容易影响的是 glibc,因为它不推荐使用静态链接,主要涉及 libc.so.6 和 ld.so ,前者必须跟后者版本严格一致,后者通常通过 interpreter path 显式指定使用系统提供的版本。你也没法控制编译器不使用新版 glibc 新增的符号。

另外两个基础库 libstdc++.so 和 libgcc_s.so 倒是可以选择静态链接,问题不大。

如果能用 musl-staic 或者像 go 那样完全不依赖 glibc 也是很好移植的。

所以通常做可移植的做法是把所有用到的 so(包括 glibc)全打包到程序目录下,用 patchelf 修改 interpreter path 和 rpath 。

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

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

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

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

© 2021 V2EX