不同版本的 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 上正常运行性。

7988 次点击
所在节点    Linux
49 条回复
xd314697475
2021-01-29 21:33:24 +08:00
cpu 一样的话( x86-64 和 arm 不能混用)是可以的
最好 gcc 版本也一样
qbqbqbqb
2021-01-29 21:48:12 +08:00
C++的话有一个要注意,gcc 的 C++库有两种 ABI,一种是 gcc4.x 版本普遍使用的旧 ABI,还有一种是 gcc5.0 版本引入的 C++11 ABI (主要是为了符合 C++11 规范,STL 中 string 和 list 的实现有修改;但是新版 GCC 也可能会使用旧版 ABI,要看具体发行版的情况),如果 C++ ABI 不兼容的库被链接在一起,编译出来的程序运行以后会 crash 。

另外也有的发行版启用了 dual ABI,默认是 C++11 ABI,如果有需要的话,可以用-D_GLIBCXX_USE_CXX11_ABI=0 就可以让编译出来的程序使用旧版 ABI 。
Gcourage
2021-01-29 21:51:01 +08:00
大部分都直接兼容的。glibc 貌似还能直接静态链接。然后就可以执行了
qbqbqbqb
2021-01-29 21:53:13 +08:00
总的来说就是,第三方库跨版本,可能会有 API 或 ABI 兼容问题

如果不考虑第三方库版本的问题,那么 C 语言一般不会有 ABI 不兼容(虽然 C 语言没有官方规定的 ABI,但是作为操作系统基础语言,事实上具有较强的兼容性),但 C++可能会有 ABI 不兼容(确实存在不兼容的情况)
DOLLOR
2021-01-29 21:58:26 +08:00
linux 平台的软件也有二进制发布形式的,不一定非要把源码拿到自己的电脑上重新编译。
laminux29
2021-01-30 00:04:20 +08:00
就连高度统一的 Windows,在一个版本的 OS 上编译的程序,换个版本都有可能出问题,更何况 Linux 。

这个话题牵涉的东西太多了,可以讲好几天。

建议:
1.把主流的 Linux 版本,都编译一个版本出来,方便测试。

2.针对方便客户,甚至可以直接做一个配置好的虚拟化版本,方便客户测试。

3.如果客户的环境,和你们的预编译的所有版本都不一样,你可以建议客户,把他们的系统发给你们,可以是光盘、镜像文件、甚至整个虚拟机的打包。你们针对客户的系统版本,出个编译版本。
jinliming2
2021-01-30 01:07:50 +08:00
编译出来的程序用 ldd 工具查看一下动态链接的库,一般会受动态库的版本的影响。影响比较多的是 glibc 的版本,版本不一样就会导致跑不起来。
一般来说,ldd 之后,只要把所有动态链接的 .so 文件一并拷贝走,并在运行时用 LD_LIBRARY_PATH 替换掉系统的不兼容版本,大部分程序应该就能正常起来了。
所以很多二进制发布的程序,都会在压缩包里把所有动态库都带上,防止版本问题。
除非还涉及到 Linux 内核的一些选项。
另外,还要注意 CPU 架构不通用,x86 的程序不能在 arm 上跑。
ETiV
2021-01-30 02:38:08 +08:00
我会用 Alpine 编个静态的可执行文件出来(编译环境直接写成 Dockerfile ),到处拿着用

手上的项目有几个用 CoreOS 跑的(它没有包管理器),虽说有 toolbox 但是一些常用的工具还是喜欢跑原生的,比如:tmux 、htop 、甚至 xtrabackup 。我就都用 Alpine 编译出来个静态执行文件,直接运行就好了
mybyons
2021-01-30 04:55:57 +08:00
如果是应用程序 不要想了 直接 AppImage 否则就是自己折腾自己
wzhy
2021-01-30 07:16:47 +08:00
如果是有动态调用,不要做任何能够兼容的假设,或者说期待。
这一点 C++就跟 go 差远了。
lucifer9
2021-01-30 09:37:59 +08:00
glibc 版本不同有时候会遇到吧
wzzzx
2021-01-30 09:50:17 +08:00
@superrichman #8 appimage 也是存在动态链接的
zeroDev
2021-01-30 09:52:04 +08:00
静态编译或者 docker?
pwli
2021-01-30 10:09:18 +08:00
@jim9606 大佬,我在 cgo 编译时就遇到了 glibc 版本不兼容的问题,编译环境是 gcc8,glibc2.28 ;运行环境 glibc 的版本是 2.27 就运行不了了,请问编译的时候可以指定 glibc 的版本吗?
orafy
2021-01-30 10:37:40 +08:00
推荐 zig 语言的编译器,对交叉编译支持很叼,原生支持编译 c 语言。
用它来编译 wasm,各种嵌入式平台,以及 freestanding 的很容易。
https://ziglang.org
LeeReamond
2021-01-30 10:46:30 +08:00
看到这个问题就想到,同一个 exe 安装包能在 2001 年发布的 xp 上跑,又能在 2021 年的 win10 上跑,真是太强大了
nicebird
2021-01-30 12:06:59 +08:00
- 动态库问题会比较多,尽量静态编译
- 即使静态编译,一般还会依赖一些动态库,比如 glibc,不同版本有兼容性问题
feast
2021-01-30 13:35:08 +08:00
file 一下你会发现一个 target kernel version 2.6.25 居多,这个东西怎么来的我前不久刚好研究过,似乎跟编译的工具链和编译环境的链接库都有关系
DinoStray
2021-01-30 13:37:19 +08:00
我觉得这个问题和 C++ 没关系, 应该是操作系统可执行文件的范畴
除非 java 一样有虚拟机支持, 否则直接运行在操作系统上的可执行文件, 都有类似的问题: ABI 兼容问题
feast
2021-01-30 13:38:17 +08:00
想有便携性编译成纯静态的 elf 就行了,几乎只跟内核 ABI 有关系了,有误请大佬指出,另外这个版本跟 GCC 有关系吗,似乎从 vc 编译逻辑上讲会定义一个 WINNT_VER 的 marco,而这个值跟 VC 里的头文件有关系,或者 include windows SDK 的,不知道 Linux 又是什么关系,没有深究过

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

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

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

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

© 2021 V2EX