跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 不同版本的 Linux 编译的 c/c++程序是否通用
未分類
15 1 月 2021

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

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

資深大佬 : lbmjsls1 3

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

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

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

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

大佬有話說 (49)

  • 資深大佬 : QBugHunter

    可以
    不过如果要调用本地的.so 的话回有点问题,

  • 資深大佬 : chenzhekl

    没有问题,因为都是 Linux 内核。自己稍微管理好一下依赖就行。

  • 資深大佬 : v2webdev

    动态链接库会有问题。

  • 資深大佬 : paoqi2048

    不同版本的编译器可能存在 ABI 不兼容的问题

  • 資深大佬 : codehz

    不一定,有很多因素可以导致差异,有些好解决,有些只能规避
    比如前面提到的共享库版本问题,这个解决起来就是整一个容器或者最简单一个 chroot 环境,在里面编译就肯定兼容了
    必须规避的就是由于 cpu 指令集的差异造成的问题,这个时候就得对着目标设备的 cpu 特性开编译选项了。。。

  • 資深大佬 : wangkun025

    不同版本的 debian 估计都会有问题吧。更别提不同的发行版了。
    玩玩都可以。工作就算了。

  • 資深大佬 : northisland

    能跑是巧合。。。

    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

    弄成 appimage 就行

  • 資深大佬 : pkookp8

    不同 libc 编译出来的都不一定不能用
    某些接口如果变化了会出现 crash 或异常,如果没有,则能正常运行

  • 資深大佬 : chinvo

    动态库有差异的话比较麻烦

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

    当然你可以静态编译或者打包动态库进去

  • 資深大佬 : northisland

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

  • 資深大佬 : Rasphino

    用 Musl 加静态链接,基本不会有问题

  • 資深大佬 : 3dwelcome

    写简单的 C++肯定没问题,中等的会有各种小问题(比如上提到的 libc,so 问题),超大型项目的 Cross Compile 就算了吧。
    老老实实装一个 debian gcc/clang,比什么都好。

  • 資深大佬 : azenk

    内核版本也是有限制的,你 file 一下可执行文件就可以看到可运行这个程序的内核的最低版本,只不过这个版本一般都很低,发行版本通常都可以满足

  • 資深大佬 : bruce0

    不用动态链接库, 项目中没有太多外部依赖,应该问题不大

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

    主要写 go C++不太熟悉 可能说的不专业

  • 資深大佬 : guo4224

    musl

  • 資深大佬 : ipwx

    1 、如果你有本事重新编译一遍所有依赖库(并带上,就好像带了一堆 dll 的 windows 程序那样),或者静态链接依赖库,感觉内核版本差不多的话,哪个发行版都能随便用你编译出来的程序。
    2 、你可以用 docker

  • 資深大佬 : xcstream

    问题不大

  • 資深大佬 : biochen

    影响兼容性的原因大概有动态链接库、glibc 版本、内核版本等,不过很多时候都是能兼容的。

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

    你的应该是生产环境不想安装那么多的开发库,开发环境编译好之后,直接运行在生产环境中,这个没有问题的。怕不兼容,尽量 静态链接 + 开发环境和生产环境使用同一个 linux 发行版。

  • 資深大佬 : jim9606

    系统调用(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 。

  • 資深大佬 : xd314697475

    cpu 一样的话( x86-64 和 arm 不能混用)是可以的
    最好 gcc 版本也一样

  • 資深大佬 : qbqbqbqb

    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

    大部分都直接兼容的。glibc 貌似还能直接静态链接。然后就可以执行了

  • 資深大佬 : qbqbqbqb

    总的来说就是,第三方库跨版本,可能会有 API 或 ABI 兼容问题

    如果不考虑第三方库版本的问题,那么 C 语言一般不会有 ABI 不兼容(虽然 C 语言没有官方规定的 ABI,但是作为操作系统基础语言,事实上具有较强的兼容性),但 C++可能会有 ABI 不兼容(确实存在不兼容的情况)

  • 資深大佬 : DOLLOR

    linux 平台的软件也有二进制发布形式的,不一定非要把源码拿到自己的电脑上重新编译。

  • 資深大佬 : laminux29

    就连高度统一的 Windows,在一个版本的 OS 上编译的程序,换个版本都有可能出问题,更何况 Linux 。

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

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

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

    3.如果客户的环境,和你们的预编译的所有版本都不一样,你可以建议客户,把他们的系统发给你们,可以是光盘、镜像文件、甚至整个虚拟机的打包。你们针对客户的系统版本,出个编译版本。

  • 資深大佬 : jinliming2

    编译出来的程序用 ldd 工具查看一下动态链接的库,一般会受动态库的版本的影响。影响比较多的是 glibc 的版本,版本不一样就会导致跑不起来。
    一般来说,ldd 之后,只要把所有动态链接的 .so 文件一并拷贝走,并在运行时用 LD_LIBRARY_PATH 替换掉系统的不兼容版本,大部分程序应该就能正常起来了。
    所以很多二进制发布的程序,都会在压缩包里把所有动态库都带上,防止版本问题。
    除非还涉及到 Linux 内核的一些选项。
    另外,还要注意 CPU 架构不通用,x86 的程序不能在 arm 上跑。

  • 資深大佬 : ETiV

    我会用 Alpine 编个静态的可执行文件出来(编译环境直接写成 Dockerfile ),到处拿着用

    手上的项目有几个用 CoreOS 跑的(它没有包管理器),虽说有 toolbox 但是一些常用的工具还是喜欢跑原生的,比如:tmux 、htop 、甚至 xtrabackup 。我就都用 Alpine 编译出来个静态执行文件,直接运行就好了

  • 資深大佬 : mybyons

    如果是应用程序 不要想了 直接 AppImage 否则就是自己折腾自己

  • 資深大佬 : wzhy

    如果是有动态调用,不要做任何能够兼容的假设,或者说期待。
    这一点 C++就跟 go 差远了。

  • 資深大佬 : lucifer9

    glibc 版本不同有时候会遇到吧

  • 資深大佬 : wzzzx

    @superrichman #8 appimage 也是存在动态链接的

  • 資深大佬 : zeroDev

    静态编译或者 docker?

  • 資深大佬 : pwli

    @jim9606 大佬,我在 cgo 编译时就遇到了 glibc 版本不兼容的问题,编译环境是 gcc8,glibc2.28 ;运行环境 glibc 的版本是 2.27 就运行不了了,请问编译的时候可以指定 glibc 的版本吗?

  • 資深大佬 : orafy

    推荐 zig 语言的编译器,对交叉编译支持很叼,原生支持编译 c 语言。
    用它来编译 wasm,各种嵌入式平台,以及 freestanding 的很容易。
    https://ziglang.org

  • 資深大佬 : LeeReamond

    看到这个问题就想到,同一个 exe 安装包能在 2001 年发布的 xp 上跑,又能在 2021 年的 win10 上跑,真是太强大了

  • 資深大佬 : nicebird

    – 动态库问题会比较多,尽量静态编译
    – 即使静态编译,一般还会依赖一些动态库,比如 glibc,不同版本有兼容性问题

  • 資深大佬 : feast

    file 一下你会发现一个 target kernel version 2.6.25 居多,这个东西怎么来的我前不久刚好研究过,似乎跟编译的工具链和编译环境的链接库都有关系

  • 資深大佬 : DinoStray

    我觉得这个问题和 C++ 没关系, 应该是操作系统可执行文件的范畴
    除非 java 一样有虚拟机支持, 否则直接运行在操作系统上的可执行文件, 都有类似的问题: ABI 兼容问题

  • 資深大佬 : feast

    想有便携性编译成纯静态的 elf 就行了,几乎只跟内核 ABI 有关系了,有误请大佬指出,另外这个版本跟 GCC 有关系吗,似乎从 vc 编译逻辑上讲会定义一个 WINNT_VER 的 marco,而这个值跟 VC 里的头文件有关系,或者 include windows SDK 的,不知道 Linux 又是什么关系,没有深究过

  • 資深大佬 : BrettD

    @DinoStray 操作系统可执行文件都是 ELF 格式,主的这个问题算是运行时库的问题

  • 資深大佬 : FrankHB

    Linux 系统调用看 11L 。
    glibc:
    https://abi-laboratory.pro/?view=timeline&l=glibc
    libstdc++ 在 GCC 5 以后是明确有 ABI brakage 的(为了 C++11 conformance )。比起 MSVC 已经靠谱得多了,但考虑到 Linux 上 C++ 运行时基本是当系统库部署的,基本不会打包(除非 nix/guix 那种)。但如果你已经会自己对付这种部署问题,就问不出来问通用不通用的问题了。所以凉拌。
    还有库的各种 ABI bug 得看具体版本。

  • 資深大佬 : jim9606

    @pwli 操作有点复杂,参考这个 ( https://tldp.org/HOWTO/Glibc2-HOWTO-6.html )
    通过 -nostdinc -nostdlib 等开关禁止自动引入基础库,然后手动加入旧版 glibc 的包含目录和链接库。
    一般还是用 docker 或者 chroot 解决比较省事

  • 資深大佬 : zeroxia

    开发机器开发完,拿到运行机器上编译一个不就行了。或者准备一台和运行机器一样软件环境的编译机。Linux 软件分发不都是源代码级别的吗?

  • 資深大佬 : jinliming2

    @LeeReamond 你也不看看你电脑上装了多少个版本的 C++ 运行库……

  • 資深大佬 : wangxn

    @LeeReamond Win Vista/7/10 添加的 Win32API 实在太多了,一个现在开发的程序跑不起来不是什么奇怪的事情。例如 Chrome 这些就不支持 XP 。

  • 資深大佬 : wslzy007

    小心选择交叉编译环境就行了。重点在于 glibc 、内核及 gcc 版本。。。
    我的 SG 项目编译后基本就是“系统+cpu 架构”,也就是 linux-x86_64 通用、linux-arm 通用等。。。
    github.com/lazy-luo/smarGate

  • 資深大佬 : Lemeng

    可行

  • 資深大佬 : libook

    多数情况下可以通用。

    需要注意的就是,CPU 架构要一样,且调用的系统 API 两边都有,最后就是依赖的动态链接库两边都有。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具