Golang
Golang 的交叉编译简直太容易了,只需设置 GOOS=linux 和 GOARCH=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 完败

C/C++的静态交叉编译,glibc 是个坑我得承认,感觉上 musl 静态编译的话应该还好吧?当然 C++动态库 ABI 那就是另一个天坑暂且不提了。

听说把 linker 换成 zig 能解决很多交叉编译中的问题

golang 的交叉编译有坑的,你能编译通过并不意味着你运行正常,之前我用 golang1.22.6 在 macos 上编译一个 windows 版本的程序,时区相关的库各种报错,在 windows 上编译就没问题

请问你是没了解过 rustls 吗,reqwest 也有 rustls 的 feature 呀???

一看 id ,原来又是哥们你呀。。。

aarch64-musl openssl 太难搞。

下次在得出 rust 发展这么久为什么还没有 rust 实现的 tls 的结论之前能不能拜托你去搜一搜,rustls 好歹 crates 上一亿的下载量。

zig 貌似也有一些问题

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

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

(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>

体会过这个现象。不过我的项目用到一些私有库,所以不同平台结果不一样。解决办法就是对应平台编译对应版本。

因为 rust 一直试图去兼容 c/c++ 那一套生态,他生态里面很多 lib 都是直接调用了 c/c++ 的代码,所以把 c/c++ 糟粕的一部分也全盘接收了

不像 go 完全另起炉灶,生态基本上不依赖 c/c++,所以就没有这些问题

如果你的代码没有使用 CGO ,基本上都能顺利编译成功

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

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

结论,楼主很擅长钓鱼。

go 这点还不错,一些基础设施做了实现,cgo is not go

可以试试这个

rustls-rustcrypto - an experimental provider that uses the crypto primitives from RustCrypto for cryptography.

结果就是性能稀烂

你动手试试就知道楼主说的是事实,Golang tls 不需要 cgo ,tls 这种基础库 rust 官方一直没有实现实在说不过去

要用 openssl ,开 vendored 这个 feature 就静态链接了。

cgo 不是 go ,所以 go 交叉编译还是挺好使的。

感觉确实是这个思路,感觉大多数时间花费在搞编译器上了。

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

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

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

一看就是搞过的

看到过这个,但是没测试过,有时间试下

go 的交叉编译确实是最简单好用的

github.com/cross-rs/cross

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

而 go 本身,微软为了给美国政府的软件,不是也 fork 了, github.com/microsoft/go ,并且,很明显,这些 patch 很多都和 tls 有关, github.com/microsoft/go/tree/microsoft/main/patches 。

话说回来,交叉编译对于 rust 的现在很多 大 客户(或者说金主)来说几乎是 0 吸引力的特性,它们现在的基础设施太完善,所以可以预见的未来几年都不会有改善。

#19 另外编译一份 openssl 也不是啥难事吧,对应的工具链配置好,几个命令的事情。

rustls 能算得上活跃的开发者加起来三位…

还有一个原因是 go 调用 cgo 有很大的性能损失,这些东西不自己重写会导致运行效率低下…

只有真正遇到过的才知道有多麻烦,譬如你可以试试找个 MIPS 架构,或者非 glibc 的 SDK ,编译个简单的 quic 客户端

交叉编译确实有点痛苦了,折腾半天最后还是找对应环境直接编译方便快捷

“基础设施太完善”。感觉很有道理。没有推进的动力。

TLS 这块,很多核心代码是汇编的。都不是 C 不 C 的问题了,换个少见点的目标架构,神仙也没法凭空给你变出汇编代码来。

但这又确实是个性能要求很高的场景,做深度优化并没什么问题

#18
go 交叉编译不好使的地方还是很多
但是这些不好使的大多是冷门方向

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

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

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

类似这种东西,golang 的坑超级多

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

这个其实也就是 Go / Rust 的主要区别了,它们设计出来完全就是针对不同场景的
所以我一直没搞懂为什么网上老是有人喜欢把这两个语言拿出来对比 哈哈

Rust 项目几乎就不可能没依赖 C 库的,之前我也是使用 cargo-zigbuild 工具编译,反正这语言我用起来就感觉很奇怪。

其实现阶段的基础设施,交叉编译没啥太大含义了。可能对一些 arm ,交叉编译还是要的。但是 linux ,windows ,mac 这些常见的。。其实无所谓。github 有 action 。自己可以虚拟机。这样反而是最干净的。

#34 是这样的,只是有交叉编译肯定更方便,没有影响也不是特别大

我觉得 rust 更大的问题反而是编译时间 哈哈哈,每次调试的时候,改两行代码得编译十几分钟,有时候气得想砸电脑

交叉编译不如直接起个 qemu

我编译成安卓库的时候也遇到这个 ring 的问题,降低版本就行了

#27 mips 确实没搞过,之前弄鸿蒙的 aarch64 musl 的没觉得太麻烦?

zigbuild 本身没支持 zig 编译 c 文件吧?和这里说的不是一件事,它解决的主要是 glibc 很少 static link 的问题,因为 zig 链接会生成很多 glibc 的 dummy object 文件,省去了自己搞 c 交叉编译工具链的麻烦。如果你先编译一份 rust 标准库,静态链接到 glibc ,和 zigbuild 做的事情就一样,只是这玩意很多系统都有自己的 patch ,最好别干。

不过如果公司内部有用 bazel 之类的系统,现在标准的做法都是外部编译 c 库,直接链接进来即可,build.rs 几乎都不管了

mips 在 llvm 侧都烂成什么样了,rust 这边也是 tier3 ,这对 rust 目前来说是伪命题

#40 现在 mips 的场景主要是什么呢?

确实看错了问题,不过也没差吧,不管需不需要静态链接,rust 交叉编译确实困难……

当时 windows 交叉编译 linux 一直失败就是因为没有对应的工具链的问题,所以才找的 zigbuild

你用 musl 在纯 rust 下就不困难了啊…gnu 下不行的原因就是 rustup 默认下载的标准库是动态链接到 glibc

说一千道一万,rust 不把基础的标准库问题解决,始终就是让人忐忑不安。但是按照社区这种搞法,估计够呛。都是泪。

不知道,所以我才说是伪命题,longarch 都是 tier2 ,那些陈年的东西压根就不会用 rust 来写

其实看一遍龙芯给 rustc 写的文档,你就知道该怎么做了 doc.rust-lang.org/rustc/platform-support/loongarch-linux.html

我这几天搞 CGO 的静态编译同样的遇到 C 库不兼容或者 GCC 编译问题。最后是用 chroot 搞定的,也是比较蛋疼

好吧,但是项目基本上都少不了间接依赖 ring 库,还是需要解决 c 编译问题的😂

看得出来经验丰富啊👍。有个疑问,openssl-sys 为什么不直接映射 openssl 版本号发布,然后提供对应 rustup target list 所有编译后的版本,在 rust 层屏蔽各个平台的差异性,使用这个 crate 的人员就不用关心平台差异性。不然现在的 cargo build 看起来提供了 --target 支持交叉编译,但是大多数项目都会编译失败,tls 依赖的可能性太高了。现在这样--target ,这个参数太鸡肋了。
很多文章上用系统 openssl 编译 ,apt install libssl-dev 类似这种包管理器直接安装,这种编译使用系统 openssl 链接的,编译稳定性大大降低,因为系统各个版本安装的 openssl 版本不尽相同,难道 openssl 兼容性就这么好