2.4 KiB
Rust on MontaukOS
Phase 1: no_std + alloc programs, cross-compiled from Linux with a
stock nightly toolchain and a custom target spec. No compiler fork.
Setup (once)
curl --proto '=https' -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
~/.cargo/bin/rustup toolchain install nightly --component rust-src
rust-toolchain.toml selects nightly + rust-src for this directory.
make programs builds the Rust programs when that toolchain is present
and prints a notice and skips them otherwise. It never downloads a toolchain
(RUSTUP_AUTO_INSTALL=0).
Building
make -C programs rust # cargo build --release, copies to bin/os/*.elf
cd programs/rust && cargo build --release
Output: target/x86_64-unknown-montauk/release/<name>, installed as
programs/bin/os/<name>.elf. Add new binaries to RUST_PROGRAMS in
programs/GNUmakefile and to the workspace members.
Layout
| Path | Purpose |
|---|---|
x86_64-unknown-montauk.json |
Target spec: static non-PIE ET_EXEC, no red zone, local-exec TLS, panic=abort |
.cargo/config.toml |
-Zbuild-std=core,alloc, linker = x86_64-montauk-gcc |
montauk-rt/ |
Runtime: syscalls, allocator, print!, argv, threads, futex Mutex, panic handler |
rusthello/ |
Smoke test (rusthello, rusthello panic, rusthello panic-thread) |
The GCC driver links crt1/crti/crtbegin, the libc and libgcc from
toolchain/sysroot, the same as ports. After changing programs/lib/libc,
re-run toolchain/build-montauk-toolchain.sh so Rust programs pick it up.
Syscall numbers and status codes are generated at build time by
montauk-rt/build.rs from programs/include/Api/Syscall.hpp and
kernel/src/Common/StatusCodes.hpp, so there is nothing to keep in sync by hand.
Writing a program
#![no_std]
#![no_main]
extern crate alloc;
montauk_rt::entry!(main);
fn main() -> i32 {
montauk_rt::println!("hello from Rust");
0
}
Limits (Phase 1)
- No
std. Nostd::fs,std::net,std::processorstd::thread; usemontauk_rtequivalents where they exist. panic = "abort". A panic on any thread prints the message and kills the whole process.- Thread stacks are owned by the
JoinHandle. An unjoined thread leaks its stack.
Phase 2 (a forked rustc at ~/dev/mtk/rust with a native target_os = "montauk" std) replaces the JSON spec with a built-in target.