Golang与Rust交叉编译
交叉编译
交叉编译一般是指在一个平台上生成另一个平台上的可执行代码,因为有一些目标平台性能很弱,编译需要花费很长的时间,所以需要在性能较高的平台上通过交叉编译来得到目标程序。
在golang和rust中交叉编译都是很容易实现的。
Golang
golang交叉编译一般不需要额外的工具,只需要在golang编译时指定GOOS
(操作系统)和GOARCH
(CPU架构)即可。
可以使用go tool dist list
来查看所有支持的目标平台。
但是如果代码中使用了cgo,那么通常还需要指定一个CC
(一般为gcc)来进行编译。
如果目标平台使用glibc库,可以快捷的使用xgo来进行交叉编译。
但是有些目标平台是使用的是musl库,或者是使用其他版本的C库,就需要手动安装交叉编译工具链了。
通过CC指定musl-gcc
之后,编译出来的程序就可以在musl库的目标平台下运行了,但是其他版本的C库又不行了,这里要引入一个新的概念,叫做静态编译
,即直接将用到的库链接到目标程序中,这样就不在依赖其他的库了。
二进制程序依赖的库可以通过ldd file
查看。
在golang中,在ldflags
中加入--extldflags '-static -fpic'
参数即可开启静态编译,这时使用musl编译出来的二进制文件就可以在所有的目标平台运行了,无论使用的是什么C库。
为什么不直接使用glibc来进行静态编译呢?
直接使用glibc编译出来的二进制文件用ldd查看也是没有依赖的,但是在musl库系统下就是无法运行,我也不知道为什么。
Rust
rust有专门用于交叉编译的库:cross,使用cross build
命令直接指定target他就可以工作了。
如果需要手动交叉编译,在rust中进行交叉编译通常比golang中多一步,需要使用rustup target add
来添加目标target,同样的所有目标target都可以通过rustup target list
来查看。
然后就是和golang一样需要一个gcc,但是有少数时候又不需要,例如在x86_64-unknown-linux-gnu
上编译目标平台为x86_64-unknown-linux-musl
的hello-world
程序就不需要安装额外的musl-gcc
,至于为什么这样,我也不知道。
另外Rust可能还需要在.cargo/config
中添加一个[target.'x86_64-unknown-linux-gnu'.linker = "xxx"]
来指定使用的gcc,编译时也需要加入--target host
来指定目标平台。
网上很多文章说需要
rustup toolchain install
,其实是错误的(我认为)
交叉编译工具链下载
- musl: https://musl.cc/
- gnu: https://gnutoolchains.com/download/
- all: https://toolchains.bootlin.com/