为龙芯笔记本交叉编译 Rust
在龙芯笔记本上安装好 Gentoo 之后,接下来我要在它上面安装 Rust。主要的原因是我习惯使用的一些命令,比如 fd
、rg
和 bat
都需要使用 Rust 编译。
Rust 对 MIPS 提供 Tier 3 级别的支持,并且对 mips64el-unknown-linux-gnuabi64
的 target 提供 host 支持,可以在上面运行 Rust 编译器。因此我们可以直接在龙芯笔记本上安装 Rust,然后在本地编译需要的软件。
不过,直接安装 dev-lang/rust-bin 是不行的,因为 Rust 默认使用 mips64r2 架构进行编译,而龙芯 2F 芯片是基于 mips3 架构的,因此不能直接运行,需要交叉编译 dev-lang/rust 的二进制包。
1. 交叉编译 Rust 编译器
目前 Wiki 对于这部分内容的说明已经过时了,根据今年 2 月份 869a67e 的提交,目前可以直接使用 crossdev 交叉编译 Rust 编译器。
首先在宿主机上安装 Rust。
1 | ## 如果只需要交叉编译 Rust 编译器,直接使用 dev-lang/rust-bin 即可 |
根据 ebuild 文件的说明,在进行交叉编译的时候,需要启用 system-bootstrap 的 USE flag,并禁用 system-llvm,还需要启用宿主机的 LLVM target。
1 | dev-lang/rust system-bootstrap -system-llvm |
接下来要把目标架构从 mips64r2 改为 mips3,可以使用 patch:
1 | diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs |
也可以使用 env 文件:
1 | function post_src_unpack() { |
另外还有一点,在编译 Rust 的时候,有一步会有 -DCMAKE_ASM_COMPILER=/usr/bin/mips64el-linux-gnuabi64-gcc
的参数,没有找到原因,不过解决方法很简单,补一个软连接就可以了。
1 | ln -sv /usr/bin/mips64el-unknown-linux-gnuabi64-gcc /usr/local/bin/mips64el-linux-gnuabi64-gcc |
接下来直接安装即可。
1 | mips64el-unknown-linux-gnuabi64-emerge -av dev-lang/rust |
这里面有两点需要注意:
sys-libs/glibc
不得使用-march=loongson2f
编译,否则会提示链接错误;- 此时
/usr/mips64el-unknown-linux-gnuabi64/etc/portage/make.conf
中的 CFLAGS 要还原最原始配置(crossdev 安装时默认的即可),不能有-march
、-mtune
、-mabi
还有-Wa,...
的选项。
可以通过 package.env
进行配置:
1 | CFLAGS="-O2 -pipe -fomit-frame-pointer" |
1 | CFLAGS="-O2 -march=mips3 -mtune=loongson2f -mabi=64 -Wa,-mfix-loongson2f-nop -pipe" |
1 | sys-libs/glibc mips3 |
然后把编译好的二进制包复制到龙芯笔记本上
1 | ssh yeeloong 'mkdir -p /var/cache/binpkgs/dev-lang/rust' |
在龙芯笔记本上:
1 | ## 保持编译时的 USE flag |
接下来就可以安装常用的几个软件了:
1 | cat <<-EOF >> /etc/portage/package.accept_keywords/rust |
需要注意的是,在安装 lsd 的时候,CFALGS
的设置不能是 -march=loongson2f
,否则会导致编译失败。
使用 -march=mips3
可以正常编译。
这样编译得到的 lsd
执行文件,虽然显示是 mips64r2 架构的:
1 | file /usr/bin/lsd |
但是可以正常运行。
2. 交叉编译用 Rust 写的软件
上面的方法比较简单,但是由于 Rust 编译的速度本身就比较慢,再加上弱鸡的龙芯 CPU,基本上编译一个软件都得一小时起步:
1 | qlop -v bat fd ripgrep tailspin lsd |
因此,也可以选择直接在宿主机上交叉编译所需要的软件,不过相对来说比较麻烦,需要处理的问题比较多。
根据 Bug 679878 的说明,目前直接通过 crossdev 直接编译 Rust 编写的软件还有一些问题没有解决。实测也是如此,大部分软件都需要一些 hacking 才能成功交叉编译安装。
首先在宿主机上安装 rust:
1 | ## 这是因为之前已经安装了 `rust-bin` 和 `llvm`,否则不选也可以。 |
然后安装 rust-std。首先需要将 sys-devel/rust-std 链接到 crossdev 的仓库中:
1 | ln -sv /var/db/repos/gentoo/sys-devel/rust-std \ |
跟前面类似,这里也要使用 mips3 编译 rust-std,而且需要在编译时禁止下载 LLVM:
1 | function post_src_unpack() { |
然后就可以安装了。
1 | emerge -avq cross-mips64el-unknown-linux-gnuabi64/rust-std |
接下来,我们就可以交叉编译所需要的软件了。
2.1. tailspin
直接安装即可。
2.2. lsd、fd
lsd、fd 都可以成功编译,不过需要禁用 lto:
1 | function post_src_prepare() { |
而且 lsd 不能使用 -march=loongson2f
编译,要改为使用 -march=mips3
才可以:
1 | sys-apps/lsd mips3 |
2.3. git-delta
git-delta 需要禁用 RUSTONIG_DYNAMIC_LIBONIG:
1 | function post_src_configure() { |
另外,它和 lsd 一样,也不能用 -march=loongson2f
编译:
1 | sys-apps/git-delta mips3 |
2.4. bat
bat 需要同时禁用 lto 和 RUSTONIG_DYNAMIC_LIBONIG:
1 | function post_src_prepare() { |
2.5. ripgrep
ripgrep 需要使用 QEMU User Mode Emulation,因为在安装的时候直接运行了 rg
命令。
按照 Wiki 中的指示,使用 USE=static-usr
和 QEMU_USER_TARGETS:mips64el
安装好 qemu 之后,启用 binfmt 服务:
1 | ## 配置 QEMU_LD_PREFIX |
也可以直接 使用 wrapper,然后手动配置 binfmt:
1 | echo ':qemu-mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-wrapper-hard-loongson-n64:OC' > /proc/sys/fs/binfmt_misc/register |
最后对比一下在宿主上交叉编译所需要的时间:
1 | 2024-08-06T18:26:40 >>> sys-apps/lsd-1.1.2-r1: 33s |