//! 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"); } }