编译为裸机目标

优质
小牛编辑
124浏览
2023-12-01

编译为裸机目标

在默认情况下,Rust 尝试适配当前的系统环境,编译可执行程序。举个例子,如果你使用 x86_64 平台的 Windows 系统,Rust 将尝试编译一个扩展名为 .exe 的 Windows 可执行程序,并使用 x86_64 指令集。这个环境又被称作为你的宿主系统(Host System)。

为了描述不同的环境,Rust 使用一个称为目标三元组(Target Triple)的字符串 <arch><sub>-<vendor>-<sys>-<abi>。要查看当前系统的目标三元组,我们可以运行 rustc --version --verbose

运行输出

rustc 1.46.0-nightly (7750c3d46 2020-06-26)
binary: rustc
commit-hash: 7750c3d46bc19784adb1ee6e37a5ec7e4cd7e772
commit-date: 2020-06-26
host: x86_64-unknown-linux-gnu
release: 1.46.0-nightly
LLVM version: 10.0

上面这段输出来自一个 x86_64 平台下的 Linux 系统。我们能看到,host 字段的值为三元组 x86_64-unknown-linux-gnu,它包含了 CPU 架构 x86_64、供应商 unknown、操作系统 linux 和二进制接口 gnu。

Rust 编译器尝试为当前系统的三元组编译,并假定底层有一个类似于 Windows 或 Linux 的操作系统提供 C 语言运行环境,然而这将导致链接器错误。所以,为了避免这个错误,我们可以另选一个底层没有操作系统的运行环境。

这样的运行环境被称作裸机环境,例如目标三元组 riscv64imac-unknown-none-elf 描述了一个 RISC-V 64 位指令集的系统。我们暂时不需要了解它的细节,只需要知道这个环境底层没有操作系统,这是由三元组中的 none 描述的。要为这个目标编译,我们需要使用 rustup 添加它:

运行命令

rustup target add riscv64imac-unknown-none-elf

这行命令将为目标下载一个标准库和 core 库。这之后,我们就能为这个目标成功构建独立式可执行程序了:

运行命令

cargo build --target riscv64imac-unknown-none-elf

编译出的结果被放在了 os/target/riscv64imac-unknown-none-elf/debug 文件夹中。可以看到其中有一个名为 os 的可执行文件。不过由于它的目标平台是 RISC-V 64,我们暂时还不能通过我们的开发环境执行它。

由于我们之后都会使用 RISC-V 作为编译目标,为了避免每次都要加 --target 参数,我们可以使用 cargo 配置文件为项目配置默认的编译选项。

os 文件夹中创建一个 .cargo 文件夹,并在其中创建一个名为 config 的文件,在其中填入以下内容:

os/.cargo/config

# 编译的目标平台
[build]
target = "riscv64imac-unknown-none-elf"

这指定了此项目编译时默认的目标。以后我们就可以直接使用 cargo build 来编译了。

至此,我们完成了在 RISC-V 64 位平台的二进制程序编译,后面我们将通过布局和代码的简单调整实现一个最简单的内核。