您应该注意以下几点。最重要的是,如果您从 rustup 或发行版包管理器获取 rustc 默认使用的 LLVM 版本,它/不是/实际的 LLVM 版本,并且实际上可能与特定的 llvm 版本不兼容位码。我们在我的项目中通过使用以下命令从源代码构建 Rust 来解决这个问题--llvm-root
要配置的标志。然后你可以使用rustup toolchain link
将您构建的 rustc 链接到自定义 rustup 工具链中。
其次,如果您至少使用 rustc 1.34 并将 -C linker-plugin-lto 标志传递给 rustc,则可以使 rustc 发出包含 llvm 位代码而不是机器代码的 .rlib 文件。我还编写了以下脚本,如果上述方法不适合您,它可以解压包含目标代码的 rlib 文件并将其打包为包含 llvm 位代码的 rlib 文件。
#!/bin/bash
dir="$(mktemp -d)"
trap "rm -rf $dir" INT TERM EXIT
archive=$(realpath -m $1)
cd "$dir"
ar x "$archive"
rm ./*.rcgu.o
for file in *.bc.z; do
len=`od -An -t u4 -j 15 -N4 $file`
blen=`od -An -t u8 -j $((len+19)) -N8 $file`
tail -c+$((len+28)) $file | head -c $blen > $file.bc.gz
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00" |cat - $file.bc.gz |gzip -dc > ${file%.bc.z}.o
done
rm *.bc.z
rm *.gz
rm "$archive"
llvm-ar rs "${archive}" ./*
获得 rlib 文件后,您可以在它们上使用任何 llvm 工具链工具,就像使用包含 llvm 位代码的 .a 文件一样。
在执行最后的链接方面,有一些事情需要牢记。首先,rustc自动生成符号__rust_alloc
, __rust_alloc_zeroed
, __rust_dealloc
, and __rust_realloc
并向他们指出__rg_alloc
(以及类似的__rg_
分别是符号),这是默认使用jemalloc的GlobalAlloc实现,或者__rdl_alloc
(以及类似的__rdl_
符号),这是由 libc malloc 支持的系统分配器。如果您不使用 rustc 进行最终链接,则必须自己实现这些符号。
其次,libstd 和 libcore 依赖于您可能还必须链接的其他一些库。根据您使用的标准库的哪个部分,您可能会发现需要不同的库集,因此如果没有特定的错误消息,我无法帮助您,但我可以告诉您我的应用程序的库列表最终要求按顺序:std, core, alloc, unwind, compiler_builtins, panic_abort, backtrace_sys, rustc_demangle
。如果你使用panic=unwind,你显然必须使用它。如果您发现仍然缺少符号,我建议使用 nm 查找包含缺少符号的库,并通过反复试验找出它在链接器顺序中的位置。
希望这会有所帮助,因为我花了相当多的精力来设计这个确切问题的解决方案(尽管不是为了交叉编译的目的)。