【踩坑实录,授人以渔】折腾了半天,windows编译rust程序到linux的那些事

1,435 阅读4分钟

来来回回折腾,总算把Windows上编写的rust项目成功在Linux服务器运行了,坑还是不少,记录一下供大家参考避坑。

1. 安装WSL

wsl --install

傻瓜式安装,装完以后可以进入Ubuntu环境,之后操作都在Ubuntu环境内(其实就是一个shell窗口)

什么是wsl

wsl你可以理解为在Windows里面装的linux系统,至于为什么要用Linux,我在windows平台交叉编译的时候各种问题,网络上也没什么好的案例,反而看到的都是劝退Windows的观点,所以也没去一直折腾原生Windows环境,如果你有方法,欢迎评论区提出~

2. 编译

cargo build

发生not found类型的报错:安装GCC

如果报错error: linker ``cc`` not found 或者其他not found类型的报错大概率是编译工具链不完整,需要自己安装。当然,以你的报错信息为准。

在这个case里,cc指向c编译器,意思是你系统里缺少C编译器,导致rust程序无法完成链接。

sudo apt-get update 
sudo apt-get install gcc

为什么要用GCC

gcc 是GNU Compiler Collection(GNU 编译器集合),包含了多种编程语言的编译器。Rust 编译器在编译过程中需要调用系统的链接器来链接编译生成的对象文件,这个链接器通常是 gccclang

什么是链接

编译 Rust 项目时,rustc会生成.o 文件,然后需要一个链接器将.o文件链接成最终的可执行文件。更多细节可以看CSAPP。在这里gcc 就是负责链接的工具。

依然报错?

先确保你执行了sudo apt-get update 并且试试下面这个命令

sudo apt-get install build-essential

3. 下载target工具链,编译到对应的平台

rustup target add x86_64-unknown-linux-gnu

添加编译参数

cargo build --release --target x86_64-unknown-linux-gnu

编译产物在target/x86_64-unknown-linux-gnu/release里面拿出来放到Linux服务器上。

什么是 x86_64-unknown-linux-gnu

  • x86_64-unknown-linux-gnu 是一个目标三元组,指定了编译目标平台的架构、供应商和操作系统。

    • x86_64 表示 64 位 x86 架构(我的linux服务器的平台)。
    • unknown 表示供应商,在这里不重要。
    • linux-gnu 表示目标操作系统是 Linux,且使用 GNU 工具链。
  • 指定目标三元组是为了确保编译器生成的代码能够在指定的平台上运行。

4. 运行

把构建产出的可执行文件放到服务器上运行,运行的时候注意权限问题。

基础库报错

/lib64/libm.so.6: version `GLIBC_2.29` not found 
/lib64/libc.so.6: version `GLIBC_2.33` not found 
/lib64/libc.so.6: version `GLIBC_2.28` not found 
/lib64/libc.so.6: version `GLIBC_2.32` not found 
/lib64/libc.so.6: version `GLIBC_2.25` not found 
/lib64/libc.so.6: version `GLIBC_2.34` not found

这是因为我们的WSL Ubuntu版本和Linux服务器版本不一致,导致依赖的基础库版本不一致,而GLIBC正是其中之一。

解决办法:

  1. 安装对应版本的GLIBC 。不采用,基础库能不动就不动,这个道理大家都懂。
  2. docker。不采用,麻烦,大炮打蚊子。
  3. 静态链接代替动态链接。采用,虽然构建产物体积会比较大。
静态链接

cargo build默认走的动态链接,取的基础库的引用,所以在不同的运行会有兼容性问题。而静态链接则是一股脑把所有的库文件都打包进来了,不过文件体积会比较大,但是总的来说可以接受。

翻了一下资料,musl工具链十分适合静态链接,轻量以及独立性强,并且设计的时候考虑到了静态链接的需求。

rustup target add x86_64-unknown-linux-musl
sudo apt-get install musl-tools
cargo build --release --target x86_64-unknown-linux-musl

由于编译target变了,所以产物的目录也变成x86_64-unknown-linux-musl了,这点要注意,别拿错文件了。

5. 完成

成功运行,大功告成~