这两天一直在搞rust的交叉编译,大概花了1天半时间才搞明白。官方的文档说的很简单,始终不起作用,直到看了下面的文章才醍醐灌顶。从原理到详细步骤都有了。
原文链接
RISC-V Bytes: Rust Cross-Compilation · Daniel Mangum
感谢Daniel
我自己也总结了一下,如果有朋友需要的话可以参考
简洁版
在工程目录下建立文件夹和配置文件
mkdir .cargo && cd .cargo && touch config.toml
然后运行即可
cargo build
详解版
原理
以前用过C语言的交叉编译,需要注意的是两个,一个是编译链工具,另一个是sysroot。
主要步骤有两个
- 利用编译链工具中的编译器编译c文件,这一步一般没有问题
- 利用编译链工具中的链接器将.o文件和从其他系统中拷贝过来的sysroot中的库文件链接到一起
rust的交叉编译似乎更简单一点。
首先rust的编译链工具是跨平台的,不需要重新下载。比如你已经有一个编译链工具,使用如下命令显示
rustup show
在我的电脑上得到
Default host: x86_64-unknown-linux-gnu
rustup home: /home/ubuntu/.rustupinstalled toolchains
stable-aarch64-unknown-linux-gnu (default)
stable-x86_64-unknown-linux-gnuactive toolchain
stable-aarch64-unknown-linux-gnu (default)
(error reading rustc version)
说明我拥有两个工具链。但是上述的配置是错误的,应该使用的工具链为stable-x86_64-unknown-linux-gnu(我使用的是ubuntu22, 虚拟机,x86)。
stable-x86_64-unknown-linux-gnu 这个工具链(toolchain)可以再我这个主机(host)上编任何目标(target)平台的程序,而不用像c语言一样,切换一个平台就需要重新下载一次新的toolchain。
其次虽然工具链是单一的,但是target库跟c语言一样,需要链接,所以每一个target都需要下载自己的库文件。比较好的地方是c语言的库文件和头文件需要自己手动从其他系统拷贝过来,但是rust的库文件只需要命令行下载即可!非常方便。
记住这两点,工具链和库,那么交叉编译就基本没问题了。
步骤
说一下环境,vmware下跑的ubuntu22虚拟机,输入
uname -a
Linux ubuntu-virtual-machine 5.15.0-27-generic #28-Ubuntu SMP Thu Apr 14 04:55:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
初始状态下已经安装rustup,如果没有的话,可以访问网站
https://www.rust-lang.org/tools/install
或者输入命令(linux系统有效)安装一下即可
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
确认目标机器。我需要在x86下编译,然后在arm64上跑程序。所以使用的是 aarch64-unknown-linux-gnu 。输入命令即可查看
rustup target list
此时确认一下自己的工具链
rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/ubuntu/.rustupstable-x86_64-unknown-linux-gnu (default)
rustc 1.60.0 (7737e0b5c 2022-04-04)可以看到目前只有一个工具链,没有target(其实有target,但是target是本机,所以不显示)。所以此时编译出来的程序可以在本地跑起来
cargo new hello cd hello cargo run
Compiling hello v0.1.0 (/home/ubuntu/test/hello)
Finished dev [unoptimized + debuginfo] target(s) in 4.94s
Runningtarget/debug/hello
Hello, world! -
下载arm库
rustup target add aarch64-unknown-linux-gnu
运行命令确认
rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/ubuntu/.rustupinstalled targets for active toolchain
aarch64-unknown-linux-gnu
x86_64-unknown-linux-gnuactive toolchain
stable-x86_64-unknown-linux-gnu (default)
rustc 1.60.0 (7737e0b5c 2022-04-04)此时有一个toolchain,两个target;其中aarch64-unknown-linux-gnu就是我需要的
-
下载目标平台gcc,配置target和链接器
这一步非常关键,而且让人迷惑。rust编译程序的过程需要用到自己的工具链,同时还需要用到gcc的链接工具!但是他们的名字非常接近但是又不完全一样。
还有一个我之前屡次失败的原因是:rust安装方式有问题!!!!!!!!!!我之前用的是sudo apt install cargo
这样会导致rustup的路径出现问题,千万要注意如果想正确编译的话必须用官网推荐的安装方法,也就是
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
首先安装gcc
sudo apt-get install -qq gcc-aarch64-linux-gnu
安装完成后如果输入以下命令有结果的话说明安装成功
aarch64-linux-gnu-gcc -v
然后添加配置文件。在刚才建立的工程目录 hello 下
mkdir .cargo && cd .cargo && touch config.toml
将以下内容复制入config.toml内即可
[build]
target = “aarch64-unknown-linux-gnu”[target.aarch64-unknown-linux-gnu]
linker = “aarch64-linux-gnu-gcc” -
编译并运行
cargo clean cargo build cargo run
如果输出以下信息,表示编译成功
Finished dev [unoptimized + debuginfo] target(s) in 0.00s Running `target/aarch64-unknown-linux-gnu/debug/hello`
target/aarch64-unknown-linux-gnu/debug/hello: 1: cannot open @8: No such file
target/aarch64-unknown-linux-gnu/debug/hello: 1: ELF��g@�:: not found
target/aarch64-unknown-linux-gnu/debug/hello: 2: @+*@@@0ppp
�D��������+�-�: not found
target/aarch64-unknown-linux-gnu/debug/hello: 3: �: not found
target/aarch64-unknown-linux-gnu/debug/hello: 4: �: not found
target/aarch64-unknown-linux-gnu/debug/hello: 5: Syntax error: “(” unexpected注意将hello程序拷贝出来后放入目标系统
chmod +x hello ./hello
会产生如下信息
./hello: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.28’ not found (required by ./hello)
说明目标系统的ubuntu版本过低。。。。
两种选择,目标系统升级系统到ubuntu22,或者host系统降级到ubuntu18即可。