RUST 交叉编译 arm64 的浮点函数问题

最近在把一个项目迁移到支持 arm64(aarch64) 时,遇到了个 rust 编译器的问题,由于 rust 有部分函数没实现,会出现找不到符号的情况,如

...
vfprintf.c:(.text.fmt_fp+0x178): undefined reference to `__addtf3'
vfprintf.c:(.text.fmt_fp+0x20c): undefined reference to `__multf3'
vfprintf.c:(.text.fmt_fp+0x240): undefined reference to `__subtf3'
vfprintf.c:(.text.fmt_fp+0x250): undefined reference to `__addtf3'
vfprintf.c:(.text.fmt_fp+0x278): undefined reference to `__addtf3'
vfprintf.c:(.text.fmt_fp+0x284): undefined reference to `__subtf3'
vfprintf.c:(.text.fmt_fp+0x33c): undefined reference to `__subtf3'
vfprintf.c:(.text.fmt_fp+0x344): undefined reference to `__multf3'
vfprintf.c:(.text.fmt_fp+0x4e8): undefined reference to `__multf3'
vfprintf.c:(.text.fmt_fp+0x548): undefined reference to `__subtf3'
vfprintf.c:(.text.fmt_fp+0x550): undefined reference to `__multf3'
vfprintf.c:(.text.fmt_fp+0x828): undefined reference to `__addtf3'
...

这个问题是比较普遍的问题,原因在于 rust 的实现中并没有 f128 相关的内容 (tf3 表示 triple float),基本上做 aarch64 时都会遇到。

github 上的 issue 见 https://github.com/rust-lang/rust/issues/46651 。问题来自于 rust 的实现,但是还是要处理掉的,方法是静态链接 c 库实现。

具体操作如下:

1. 把交叉编译器的 libgcc.a 的所在目录添加到 rust 链接时搜索目录
2. 加入链接参数 -lgcc

可以在命令行上加,但是每次都要打命令行不方便,加到项目下的 .cargo/config 中,以下是使用了 musl 工具链的配置,见 https://www.cnblogs.com/fengyc/p/12861259.html

[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-ld"
ar = "aarch64-linux-musl-ar"
rustflags = ["-C", "target-feature=+crt-static", "-L", "/opt/aarch64-linux-musl-cross/lib/gcc/aarch64-linux-musl/9.2.1", "-C", "link-arg=-lgcc"]
strip = {path="aarch64-linux-musl-strip"}
objcopy = {path = "aarch64-linux-musl-objcopy"}

-L 后的参数即为 libgcc.a 所在的目录,可通过 find <交叉编译工具链所在目录> -name libgcc.a 找到。

如果各个路径都正确,加上之后再次 cargo build 问题都会消失。

如果使用了其它的工具链,也基本是这个原理,只要目录和附加的链接参数正确,链接器能正确找到了函数符号,就能解决这个问题。