V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
lbmjsls1
V2EX  ›  Linux

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

  •  
  •   lbmjsls1 · 81 天前 · 4002 次点击
    这是一个创建于 81 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    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
        8
    superrichman   81 天前 via iPhone
    弄成 appimage 就行
    pkookp8
        9
    pkookp8   81 天前 via Android
    不同 libc 编译出来的都不一定不能用
    某些接口如果变化了会出现 crash 或异常,如果没有,则能正常运行
    chinvo
        10
    chinvo   81 天前 via iPhone
    动态库有差异的话比较麻烦

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

    当然你可以静态编译或者打包动态库进去
    northisland
        11
    northisland   81 天前   ❤️ 1
    Rasphino
        12
    Rasphino   81 天前 via iPhone
    用 Musl 加静态链接,基本不会有问题
    3dwelcome
        13
    3dwelcome   81 天前
    写简单的 C++肯定没问题,中等的会有各种小问题(比如楼上提到的 libc,so 问题),超大型项目的 Cross Compile 就算了吧。
    老老实实装一个 debian gcc/clang,比什么都好。
    azenk
        14
    azenk   81 天前 via Android
    内核版本也是有限制的,你 file 一下可执行文件就可以看到可运行这个程序的内核的最低版本,只不过这个版本一般都很低,发行版本通常都可以满足
    bruce0
        15
    bruce0   81 天前
    不用动态链接库, 项目中没有太多外部依赖,应该问题不大

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

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

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

    你的应该是生产环境不想安装那么多的开发库,开发环境编译好之后,直接运行在生产环境中,这个没有问题的。怕不兼容,尽量 静态链接 + 开发环境和生产环境使用同一个 linux 发行版。
    jim9606
        20
    jim9606   81 天前   ❤️ 1
    系统调用(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
        21
    xd314697475   81 天前
    cpu 一样的话( x86-64 和 arm 不能混用)是可以的
    最好 gcc 版本也一样
    qbqbqbqb
        22
    qbqbqbqb   81 天前   ❤️ 2
    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
        23
    Gcourage   81 天前 via iPhone
    大部分都直接兼容的。glibc 貌似还能直接静态链接。然后就可以执行了
    qbqbqbqb
        24
    qbqbqbqb   81 天前   ❤️ 1
    总的来说就是,第三方库跨版本,可能会有 API 或 ABI 兼容问题

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

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

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

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

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

    手上的项目有几个用 CoreOS 跑的(它没有包管理器),虽说有 toolbox 但是一些常用的工具还是喜欢跑原生的,比如:tmux 、htop 、甚至 xtrabackup 。我就都用 Alpine 编译出来个静态执行文件,直接运行就好了
    mybyons
        29
    mybyons   81 天前
    如果是应用程序 不要想了 直接 AppImage 否则就是自己折腾自己
    wzhy
        30
    wzhy   81 天前 via Android
    如果是有动态调用,不要做任何能够兼容的假设,或者说期待。
    这一点 C++就跟 go 差远了。
    lucifer9
        31
    lucifer9   81 天前
    glibc 版本不同有时候会遇到吧
    wzzzx
        32
    wzzzx   81 天前
    @superrichman #8 appimage 也是存在动态链接的
    zeroDev
        33
    zeroDev   81 天前 via Android
    静态编译或者 docker?
    pwli
        34
    pwli   81 天前 via Android
    @jim9606 大佬,我在 cgo 编译时就遇到了 glibc 版本不兼容的问题,编译环境是 gcc8,glibc2.28 ;运行环境 glibc 的版本是 2.27 就运行不了了,请问编译的时候可以指定 glibc 的版本吗?
    orafy
        35
    orafy   81 天前
    推荐 zig 语言的编译器,对交叉编译支持很叼,原生支持编译 c 语言。
    用它来编译 wasm,各种嵌入式平台,以及 freestanding 的很容易。
    https://ziglang.org
    LeeReamond
        36
    LeeReamond   80 天前
    看到这个问题就想到,同一个 exe 安装包能在 2001 年发布的 xp 上跑,又能在 2021 年的 win10 上跑,真是太强大了
    nicebird
        37
    nicebird   80 天前
    - 动态库问题会比较多,尽量静态编译
    - 即使静态编译,一般还会依赖一些动态库,比如 glibc,不同版本有兼容性问题
    feast
        38
    feast   80 天前 via Android
    file 一下你会发现一个 target kernel version 2.6.25 居多,这个东西怎么来的我前不久刚好研究过,似乎跟编译的工具链和编译环境的链接库都有关系
    DinoStray
        39
    DinoStray   80 天前
    我觉得这个问题和 C++ 没关系, 应该是操作系统可执行文件的范畴
    除非 java 一样有虚拟机支持, 否则直接运行在操作系统上的可执行文件, 都有类似的问题: ABI 兼容问题
    feast
        40
    feast   80 天前 via Android
    想有便携性编译成纯静态的 elf 就行了,几乎只跟内核 ABI 有关系了,有误请大佬指出,另外这个版本跟 GCC 有关系吗,似乎从 vc 编译逻辑上讲会定义一个 WINNT_VER 的 marco,而这个值跟 VC 里的头文件有关系,或者 include windows SDK 的,不知道 Linux 又是什么关系,没有深究过
    BrettD
        41
    BrettD   80 天前
    @DinoStray 操作系统可执行文件都是 ELF 格式,楼主的这个问题算是运行时库的问题
    FrankHB
        42
    FrankHB   80 天前
    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
        43
    jim9606   80 天前
    @pwli 操作有点复杂,参考这个 ( https://tldp.org/HOWTO/Glibc2-HOWTO-6.html )
    通过 -nostdinc -nostdlib 等开关禁止自动引入基础库,然后手动加入旧版 glibc 的包含目录和链接库。
    一般还是用 docker 或者 chroot 解决比较省事
    zeroxia
        44
    zeroxia   80 天前 via iPhone
    开发机器开发完,拿到运行机器上编译一个不就行了。或者准备一台和运行机器一样软件环境的编译机。Linux 软件分发不都是源代码级别的吗?
    jinliming2
        45
    jinliming2   80 天前   ❤️ 1
    @LeeReamond 你也不看看你电脑上装了多少个版本的 C++ 运行库……
    wangxn
        46
    wangxn   80 天前
    @LeeReamond Win Vista/7/10 添加的 Win32API 实在太多了,一个现在开发的程序跑不起来不是什么奇怪的事情。例如 Chrome 这些就不支持 XP 。
    wslzy007
        47
    wslzy007   80 天前
    小心选择交叉编译环境就行了。重点在于 glibc 、内核及 gcc 版本。。。
    我的 SG 项目编译后基本就是“系统+cpu 架构”,也就是 linux-x86_64 通用、linux-arm 通用等。。。
    github.com/lazy-luo/smarGate
    Lemeng
        48
    Lemeng   80 天前
    可行
    libook
        49
    libook   79 天前
    多数情况下可以通用。

    需要注意的就是,CPU 架构要一样,且调用的系统 API 两边都有,最后就是依赖的动态链接库两边都有。
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3733 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:43 · PVG 10:43 · LAX 19:43 · JFK 22:43
    ♥ Do have faith in what you're doing.