rust vs golang 交叉编译

2024 年 11 月 18 日
 bli22ard

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 完败

6075 次点击
所在节点    程序员
52 条回复
reeco
2024 年 11 月 18 日
c0t
2024 年 11 月 19 日
为什么呢,因为维护者少,必须承认的事情是,就你提到的 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
2024 年 11 月 19 日
@c0t 话说回来,交叉编译对于 rust 的现在很多 大 客户(或者说金主)来说几乎是 0 吸引力的特性,它们现在的基础设施太完善,所以可以预见的未来几年都不会有改善。
Donaldo
2024 年 11 月 19 日
@bli22ard #19 另外编译一份 openssl 也不是啥难事吧,对应的工具链配置好,几个命令的事情。
Trim21
2024 年 11 月 19 日
rustls 能算得上活跃的开发者加起来三位…
Trim21
2024 年 11 月 19 日
@zengxs 还有一个原因是 go 调用 cgo 有很大的性能损失,这些东西不自己重写会导致运行效率低下…
yplam
2024 年 11 月 19 日
@Donaldo 只有真正遇到过的才知道有多麻烦,譬如你可以试试找个 MIPS 架构,或者非 glibc 的 SDK ,编译个简单的 quic 客户端
map1e
2024 年 11 月 19 日
交叉编译确实有点痛苦了,折腾半天最后还是找对应环境直接编译方便快捷
justdoit123
2024 年 11 月 19 日
@c0t “基础设施太完善”。感觉很有道理。没有推进的动力。
InkStone
2024 年 11 月 19 日
TLS 这块,很多核心代码是汇编的。都不是 C 不 C 的问题了,换个少见点的目标架构,神仙也没法凭空给你变出汇编代码来。

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

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

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

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

类似这种东西,golang 的坑超级多
zengxs
2024 年 11 月 19 日
@yplam #16

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

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

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

不过如果公司内部有用 bazel 之类的系统,现在标准的做法都是外部编译 c 库,直接链接进来即可,build.rs 几乎都不管了
c0t
2024 年 11 月 19 日
@Donaldo mips 在 llvm 侧都烂成什么样了,rust 这边也是 tier3 ,这对 rust 目前来说是伪命题

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

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

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

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

© 2021 V2EX