V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bli22ard
V2EX  ›  程序员

rust vs golang 交叉编译

  •  1
     
  •   bli22ard · 2 天前 · 3685 次点击

    Golang

    Golang 的交叉编译简直太容易了,只需设置 GOOS=linuxGOARCH=amd64 这两个环境变量,然后运行 go build。如果你的代码没有使用 CGO ,基本上都能顺利编译成功。

    Rust

    reqwest 这样的 HTTP 库,TLS 实现默认依赖 OpenSSL ,这会让交叉编译变得复杂起来,因为需要用到 C/C++ 的工具链,还要考虑不同的 libc 是 GNU 还是 MUSL 。虽然 Rust 也有一个纯 Rust 实现的 TLS 库 rustls,但它依赖 ring 库,而 ring 又使用了一些 C 代码,据说是为了实现加密算法的硬件加速。这些问题使得使用 TLS 的 Rust 程序交叉编译变得异常困难。

    即使是在架构、系统、libc 都一致的环境下,想要静态链接编译 Rust 程序也非常麻烦。Rust 团队提供了一个工具 cross,但遇到 OpenSSL 时也可能会束手无策。

    Rust 发展了这么久,为什么不能提供一个原生的、零依赖的 TLS 实现呢?

    结论

    Rust 完败

    51 条回复    2024-11-20 17:01:15 +08:00
    pursuer
        1
    pursuer  
       2 天前
    C/C++的静态交叉编译,glibc 是个坑我得承认,感觉上 musl 静态编译的话应该还好吧?当然 C++动态库 ABI 那就是另一个天坑暂且不提了。
    mxT52CRuqR6o5
        2
    mxT52CRuqR6o5  
       2 天前
    听说把 linker 换成 zig 能解决很多交叉编译中的问题
    sunny352787
        3
    sunny352787  
       2 天前
    golang 的交叉编译有坑的,你能编译通过并不意味着你运行正常,之前我用 golang1.22.6 在 macos 上编译一个 windows 版本的程序,时区相关的库各种报错,在 windows 上编译就没问题
    PTLin
        4
    PTLin  
       2 天前   ❤️ 1
    请问你是没了解过 rustls 吗,reqwest 也有 rustls 的 feature 呀???
    PTLin
        5
    PTLin  
       2 天前
    一看 id ,原来又是哥们你呀。。。
    bli22ard
        6
    bli22ard  
    OP
       2 天前
    @pursuer aarch64-musl openssl 太难搞。
    PTLin
        7
    PTLin  
       2 天前
    下次在得出 rust 发展这么久为什么还没有 rust 实现的 tls 的结论之前能不能拜托你去搜一搜,rustls 好歹 crates 上一亿的下载量。
    bli22ard
        8
    bli22ard  
    OP
       2 天前
    @mxT52CRuqR6o5
    zig 貌似也有一些问题

    @sunny352787
    没用 cgo 情况下,golang ,linux 、mac 、windows 互相交叉编译没遇到过问题


    @PTLin
    😄,reqwest = {version = "0.12",default-features = false,features = ["rustls-tls"]} 加了这个, 但是编译时候,需要 gcc 来编译 ring
    bli22ard
        9
    bli22ard  
    OP
       2 天前
    @PTLin


    (base) PS C:\Users\3\RustroverProjects\rs-certbot> cargo tree --target=x86_64-unknown-linux-musl -i ring
    ring v0.17.8
    |-- instant-acme v0.7.2
    | `-- rs-certbot v0.1.0 (C:\Users\3\RustroverProjects\rs-certbot)
    |-- rcgen v0.13.1
    | `-- rs-certbot v0.1.0 (C:\Users\3\RustroverProjects\rs-certbot)
    |-- rustls v0.23.16
    | |-- hyper-rustls v0.27.3
    | | |-- instant-acme v0.7.2 (*)
    | | `-- reqwest v0.12.9
    | | `-- rs-certbot v0.1.0 (C:\Users\3\RustroverProjects\rs-certbot)
    | |-- reqwest v0.12.9 (*)
    | `-- tokio-rustls v0.26.0
    | |-- hyper-rustls v0.27.3 (*)
    | `-- reqwest v0.12.9 (*)
    |-- rustls-webpki v0.102.8
    | `-- rustls v0.23.16 (*)
    `-- x509-parser v0.16.0
    `-- rs-certbot v0.1.0 (C:\Users\3\RustroverProjects\rs-certbot)
    (base) PS C:\Users\3\RustroverProjects\rs-certbot>




    (base) PS C:\Users\3\RustroverProjects\rs-certbot> cargo tree --target=x86_64-unknown-linux-musl -i openssl-sys
    error: package ID specification `openssl-sys` did not match any packages
    (base) PS C:\Users\3\RustroverProjects\rs-certbot>
    Felldeadbird
        10
    Felldeadbird  
       2 天前
    @sunny352787 体会过这个现象。不过我的项目用到一些私有库,所以不同平台结果不一样。解决办法就是对应平台编译对应版本。
    zengxs
        11
    zengxs  
       2 天前
    因为 rust 一直试图去兼容 c/c++ 那一套生态,他生态里面很多 lib 都是直接调用了 c/c++ 的代码,所以把 c/c++ 糟粕的一部分也全盘接收了

    不像 go 完全另起炉灶,生态基本上不依赖 c/c++,所以就没有这些问题
    undeflife
        12
    undeflife  
       2 天前   ❤️ 1
    > 如果你的代码没有使用 CGO ,基本上都能顺利编译成功

    你用这一句话就在 go 里把 rust 里碰到的问题跳过了,至于解决方案楼上已经说了。

    至于你的疑问,但凡搜一下就能知道答案。

    结论,楼主很擅长钓鱼。
    seers
        13
    seers  
       2 天前 via iPhone   ❤️ 1
    go 这点还不错,一些基础设施做了实现,cgo is not go
    Donaldo
        14
    Donaldo  
       2 天前
    可以试试这个
    > rustls-rustcrypto - an experimental provider that uses the crypto primitives from RustCrypto for cryptography.
    MrKrabs
        15
    MrKrabs  
       2 天前
    结果就是性能稀烂
    yplam
        16
    yplam  
       2 天前 via Android   ❤️ 1
    @undeflife 你动手试试就知道楼主说的是事实,Golang tls 不需要 cgo ,tls 这种基础库 rust 官方一直没有实现实在说不过去
    ihciah
        17
    ihciah  
       2 天前 via iPhone   ❤️ 1
    要用 openssl ,开 vendored 这个 feature 就静态链接了。
    ninjashixuan
        18
    ninjashixuan  
       2 天前
    cgo 不是 go ,所以 go 交叉编译还是挺好使的。
    bli22ard
        19
    bli22ard  
    OP
       2 天前
    @zengxs 感觉确实是这个思路,感觉大多数时间花费在搞编译器上了。


    @undeflife golang ,带硬件加速的加密算法,以及 tls ,都是标准库自带,不依赖 cgo 。加密算法,以及 tls ,rust 没有全部原生 rust 实现。


    @Donaldo 这个没试过,我是看到 rustls 里面有用到 ring 库。


    @MrKrabs 性能快的不是特别多,但是带来的麻烦不小


    @yplam 一看就是搞过的



    @ihciah 看到过这个,但是没测试过,有时间试下
    doraemonki
        20
    doraemonki  
       2 天前
    go 的交叉编译确实是最简单好用的
    reeco
        21
    reeco  
       2 天前
    c0t
        22
    c0t  
       2 天前   ❤️ 1
    为什么呢,因为维护者少,必须承认的事情是,就你提到的 ring crate 里有相当多需要 c 编译器的部分都来自 OpenSSL 的汇编代码,不考虑性能问题,用纯 rust 来实现可以吗?当然可以。但是它(大多数时候)只有一个维护者,作为一个每月千万下载量的 crate ,就算不用 unsafe ,保证正确性也是 "i promise" 的问题,包括 tls 实现本身,本来就很大概率会是攻击发生地,密码学可不简单,作者不想做,这个保证转嫁给了 OpenSSL ,仅此而已。事实上,rustls 的性能改进还是花钱委托 ferrous-systems 来完成的。 事实上,rustls 本身过没过国外各大公司的审计呢?我没关注这个问题。

    而 go 本身,微软为了给美国政府的软件,不是也 fork 了,https://github.com/microsoft/go ,并且,很明显,这些 patch 很多都和 tls 有关,https://github.com/microsoft/go/tree/microsoft/main/patches
    c0t
        23
    c0t  
       2 天前
    @c0t 话说回来,交叉编译对于 rust 的现在很多 大 客户(或者说金主)来说几乎是 0 吸引力的特性,它们现在的基础设施太完善,所以可以预见的未来几年都不会有改善。
    Donaldo
        24
    Donaldo  
       2 天前
    @bli22ard #19 另外编译一份 openssl 也不是啥难事吧,对应的工具链配置好,几个命令的事情。
    Trim21
        25
    Trim21  
       2 天前 via Android
    rustls 能算得上活跃的开发者加起来三位…
    Trim21
        26
    Trim21  
       1 天前 via Android
    @zengxs 还有一个原因是 go 调用 cgo 有很大的性能损失,这些东西不自己重写会导致运行效率低下…
    yplam
        27
    yplam  
       1 天前 via Android
    @Donaldo 只有真正遇到过的才知道有多麻烦,譬如你可以试试找个 MIPS 架构,或者非 glibc 的 SDK ,编译个简单的 quic 客户端
    map1e
        28
    map1e  
       1 天前
    交叉编译确实有点痛苦了,折腾半天最后还是找对应环境直接编译方便快捷
    justdoit123
        29
    justdoit123  
       1 天前
    @c0t “基础设施太完善”。感觉很有道理。没有推进的动力。
    InkStone
        30
    InkStone  
       1 天前
    TLS 这块,很多核心代码是汇编的。都不是 C 不 C 的问题了,换个少见点的目标架构,神仙也没法凭空给你变出汇编代码来。

    但这又确实是个性能要求很高的场景,做深度优化并没什么问题
    realpg
        31
    realpg  
       1 天前
    @ninjashixuan #18
    go 交叉编译不好使的地方还是很多
    但是这些不好使的大多是冷门方向

    比如吧,用 windows 的工作站开发,在 linux 的服务器下运行,这是最主流的场景
    在 Mac 下开发,在 linux 的服务器下运行,也是最主流的场景

    这两种场景,编译器几乎毫无 bug ,因为有 bug 也会很快修复

    但是你总会遇到一些标新立异的 geek ,他们非得用 arch linux 开发,开发出来的程序还得跨平台要在 windows 下运行
    这种场景,其实坑是很多的,修复也不及时,之所以说这帮人是 geek 不是大佬,是大佬早就自己提 pr 把这些修复了

    类似这种东西,golang 的坑超级多
    zengxs
        32
    zengxs  
       1 天前   ❤️ 1
    @yplam #16

    如果你站在应用层开发的角度的话 TLS 确实是基础库
    但是如果站在系统层开发的角度,那么 TLS 就只是一个应用库了

    这个其实也就是 Go / Rust 的主要区别了,它们设计出来完全就是针对不同场景的
    所以我一直没搞懂为什么网上老是有人喜欢把这两个语言拿出来对比 哈哈
    AItsuki
        33
    AItsuki  
       1 天前
    Rust 项目几乎就不可能没依赖 C 库的,之前我也是使用 cargo-zigbuild 工具编译,反正这语言我用起来就感觉很奇怪。
    sampeng
        34
    sampeng  
       1 天前
    其实现阶段的基础设施,交叉编译没啥太大含义了。可能对一些 arm ,交叉编译还是要的。但是 linux ,windows ,mac 这些常见的。。其实无所谓。github 有 action 。自己可以虚拟机。这样反而是最干净的。
    zengxs
        35
    zengxs  
       1 天前
    @sampeng #34 是这样的,只是有交叉编译肯定更方便,没有影响也不是特别大

    我觉得 rust 更大的问题反而是编译时间 哈哈哈,每次调试的时候,改两行代码得编译十几分钟,有时候气得想砸电脑
    XiLingHost
        36
    XiLingHost  
       1 天前
    交叉编译不如直接起个 qemu
    githmb
        37
    githmb  
       1 天前
    我编译成安卓库的时候也遇到这个 ring 的问题,降低版本就行了
    Donaldo
        38
    Donaldo  
       1 天前
    @yplam #27 mips 确实没搞过,之前弄鸿蒙的 aarch64 musl 的没觉得太麻烦?
    c0t
        39
    c0t  
       1 天前 via iPhone
    @AItsuki zigbuild 本身没支持 zig 编译 c 文件吧?和这里说的不是一件事,它解决的主要是 glibc 很少 static link 的问题,因为 zig 链接会生成很多 glibc 的 dummy object 文件,省去了自己搞 c 交叉编译工具链的麻烦。如果你先编译一份 rust 标准库,静态链接到 glibc ,和 zigbuild 做的事情就一样,只是这玩意很多系统都有自己的 patch ,最好别干。

    不过如果公司内部有用 bazel 之类的系统,现在标准的做法都是外部编译 c 库,直接链接进来即可,build.rs 几乎都不管了
    c0t
        40
    c0t  
       1 天前 via iPhone
    @Donaldo mips 在 llvm 侧都烂成什么样了,rust 这边也是 tier3 ,这对 rust 目前来说是伪命题
    Donaldo
        41
    Donaldo  
       1 天前
    @c0t #40 现在 mips 的场景主要是什么呢?
    AItsuki
        42
    AItsuki  
       1 天前
    @c0t 确实看错了问题,不过也没差吧,不管需不需要静态链接,rust 交叉编译确实困难……

    当时 windows 交叉编译 linux 一直失败就是因为没有对应的工具链的问题,所以才找的 zigbuild
    c0t
        43
    c0t  
       1 天前 via iPhone
    @AItsuki 你用 musl 在纯 rust 下就不困难了啊…gnu 下不行的原因就是 rustup 默认下载的标准库是动态链接到 glibc
    zhwguest
        44
    zhwguest  
       1 天前
    说一千道一万,rust 不把基础的标准库问题解决,始终就是让人忐忑不安。但是按照社区这种搞法,估计够呛。都是泪。
    c0t
        45
    c0t  
       1 天前 via iPhone
    @Donaldo 不知道,所以我才说是伪命题,longarch 都是 tier2 ,那些陈年的东西压根就不会用 rust 来写
    c0t
        46
    c0t  
       1 天前 via iPhone
    @AItsuki 其实看一遍龙芯给 rustc 写的文档,你就知道该怎么做了 https://doc.rust-lang.org/rustc/platform-support/loongarch-linux.html
    hejw19970413
        47
    hejw19970413  
       1 天前
    我这几天搞 CGO 的静态编译同样的遇到 C 库不兼容或者 GCC 编译问题。最后是用 chroot 搞定的,也是比较蛋疼
    AItsuki
        48
    AItsuki  
       1 天前
    @c0t 好吧,但是项目基本上都少不了间接依赖 ring 库,还是需要解决 c 编译问题的😂
    bli22ard
        49
    bli22ard  
    OP
       16 小时 45 分钟前
    @c0t 看得出来经验丰富啊👍。有个疑问,openssl-sys 为什么不直接映射 openssl 版本号发布,然后提供对应 rustup target list 所有编译后的版本,在 rust 层屏蔽各个平台的差异性,使用这个 crate 的人员就不用关心平台差异性。不然现在的 cargo build 看起来提供了 --target 支持交叉编译,但是大多数项目都会编译失败,tls 依赖的可能性太高了。现在这样--target ,这个参数太鸡肋了。
    很多文章上用系统 openssl 编译 ,apt install libssl-dev 类似这种包管理器直接安装,这种编译使用系统 openssl 链接的,编译稳定性大大降低,因为系统各个版本安装的 openssl 版本不尽相同,难道 openssl 兼容性就这么好
    openmynet
        50
    openmynet  
       15 小时 4 分钟前
    明显是在钓答案的。
    c0t
        51
    c0t  
       9 小时 21 分钟前 via iPhone
    @bli22ard openssl 以前不是 semver 啊…3.0 之后倒是可以这么搞
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1192 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:22 · PVG 02:22 · LAX 10:22 · JFK 13:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.