RustForge

rust-kernel

Rustbelt: a hobby x86_64 kernel written in Rust

rust-kernel / build.rs
1586 bytes ยท raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//! Build script: compile the user programs in user/ into ELF executables in
//! OUT_DIR. The kernel embeds them with `include_bytes!` (src/lib.rs).
//!
//! They're compiled with plain `rustc` for the built-in `x86_64-unknown-none`
//! target (prebuilt `core`, so no build-std needed), as static executables
//! (`relocation-model=static`) linked at a high user address -- which needs
//! the `large` code model (the default ones assume code in the low/high 2 GiB).

use std::{env, path::PathBuf, process::Command};

const PROGRAMS: &[&str] = &["hello", "evil", "spin", "echo"];

fn main() {
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let user_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("user");
    let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
    println!("cargo:rerun-if-changed=user");

    for program in PROGRAMS {
        let status = Command::new(&rustc)
            .args(["--edition", "2024", "--target", "x86_64-unknown-none"])
            .args(["-C", "panic=abort", "-C", "opt-level=2", "-C", "debuginfo=0", "-C", "strip=debuginfo"])
            .args(["-C", "relocation-model=static", "-C", "code-model=large"])
            .arg("-C")
            .arg(format!("link-arg=-T{}", user_dir.join("link.ld").display()))
            .arg("-o")
            .arg(out_dir.join(program))
            .arg(user_dir.join(format!("{program}.rs")))
            .status()
            .expect("failed to run rustc for a user program");
        assert!(status.success(), "building user program {program} failed");
    }
}