foundry
Foundry OS: the operating system built on the Rustbelt kernel
| author | Grok Bot <grokbot@localhost> | 2026-10-31 20:27:26 -0700 |
|---|---|---|
| commit | 8c5294825551990c470bee8aad8779c984a3e70b | |
| parent | 2cf3033360cd036502ae2d0da7ffd980c5407628 | |
| tree | browse files at this commit | |
rbrt: make the runtime a real library crate (imported as ulib)
Programs now depend on rbrt (ulib = { package = "rbrt" }) instead of
including rbrt/ulib.rs with #[path] mod ulib. print!/println!/eprintln!
are #[macro_export]ed, the panic handler and allocator come with the
crate, and ulib::entry!(main) exports a program's main as rbrt_main,
which _start calls. rbrt/README.md explains the pattern.30 files changed, 153 insertions, 69 deletions
@@ -5,19 +5,38 @@ version = 4 [[package]] name = "foundry-coreutils" version = "0.1.0"+dependencies = [+ "rbrt",+] [[package]] name = "foundry-init" version = "0.1.0"+dependencies = [+ "rbrt",+] [[package]] name = "foundry-net" version = "0.1.0"+dependencies = [+ "rbrt",+] [[package]] name = "foundry-rbsh" version = "0.1.0"+dependencies = [+ "rbrt",+] [[package]] name = "foundry-sys" version = "0.1.0"+dependencies = [+ "rbrt",+]++[[package]]+name = "rbrt"+version = "0.1.0"
@@ -3,12 +3,12 @@ # Every program is a `no_std` binary for the built-in `x86_64-unknown-none` # target (no operating-system standard library), linked as a static ET_EXEC # at Rustbelt's user base 0x80_0040_0000 (see link.ld). The shared runtime-# (syscall wrappers, println!, heap, _start) is rbrt/ulib.rs, which every-# program includes as a module with `#[path = ...] mod ulib;` -- exactly as-# in the kernel repo. Turning rbrt into a real library crate is milestone M1b.+# (syscall wrappers, println!, heap, _start) is the library crate rbrt/+# (imported as `ulib`); see rbrt/README.md. Since M1b it is a real crate,+# no longer a file every program includes with `#[path = ...] mod ulib;`. [workspace] resolver = "3"-members = ["rbsh", "coreutils-rs", "net", "sys", "init"]+members = ["rbrt", "rbsh", "coreutils-rs", "net", "sys", "init"] [workspace.package] version = "0.1.0"
@@ -8,6 +8,9 @@ publish.workspace = true build = "../rbrt/build.rs" autobins = false +[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+ [[bin]] name = "ls" path = "src/bin/ls.rs"
@@ -2,9 +2,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -5,9 +5,8 @@ extern crate alloc; -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use alloc::{format, string::String}; use ulib::*;
@@ -5,9 +5,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -10,9 +10,8 @@ extern crate alloc; -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use alloc::{format, string::String, vec::Vec}; use ulib::*;
@@ -2,9 +2,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -3,9 +3,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -3,9 +3,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -3,9 +3,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -3,9 +3,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -8,6 +8,9 @@ publish.workspace = true build = "../rbrt/build.rs" autobins = false +[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+ [[bin]] name = "init" path = "src/main.rs"
@@ -34,9 +34,8 @@ extern crate alloc; -#[macro_use]-#[path = "../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -8,6 +8,9 @@ publish.workspace = true build = "../rbrt/build.rs" autobins = false +[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+ [[bin]] name = "ifconfig" path = "src/bin/ifconfig.rs"
@@ -13,8 +13,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use core::fmt::Write;
@@ -9,8 +9,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); fn main() -> i64 { let Some(name) = ulib::arg(1) else {
@@ -17,8 +17,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); extern crate alloc; use alloc::format;
@@ -7,8 +7,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::Ip;
@@ -10,8 +10,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); const PAYLOAD: usize = 56; // like Linux's ping: 56 + 8 header = 64 bytes
@@ -0,0 +1,13 @@+[package]+name = "rbrt"+description = "The Foundry OS Rust runtime: syscalls, print!, heap, _start (imported as `ulib`)"+version.workspace = true+edition.workspace = true+license.workspace = true+publish.workspace = true++[lib]+name = "ulib"+path = "ulib.rs"+test = false+bench = false
@@ -5,10 +5,38 @@ raw Rustbelt/Linux syscall wrappers, `print!`/`println!`/`eprintln!`, a `brk` heap (so `Vec` and `String` work), the `_start` entry point that calls the program's `fn main() -> i64`, and the panic handler. -For milestone M1 it is still included as a *module* (`#[path = ...] mod ulib;`),-exactly as in the kernel repo, so the programs compile unchanged. Milestone-M1b turns it into a real library crate (`#[macro_export]` macros,-`#[panic_handler]`, `#[global_allocator]`).+Since milestone M1b it is a real **library crate** (package `rbrt`, imported+under the shorter name `ulib`). A program uses it like this:++```toml+# Cargo.toml of the program's package+[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+```++```rust+#![no_std]+#![no_main]++#[macro_use] // brings in print!, println!, eprintln!+extern crate ulib;+ulib::entry!(main); // tells _start which function is main++use ulib::*; // the syscall wrappers: open, read, write, ...++fn main() -> i64 {+ println!("hello");+ 0 // the exit code+}+```++How the pieces fit: `_start` (in `ulib.rs`) reads argc/argv/envp from the+stack and calls a function named `rbrt_main`. `ulib::entry!(main)` defines+`rbrt_main` in your program and makes it call your `main`. The panic handler+and the heap allocator (`#[global_allocator]`) also live in the crate, so a+program gets them just by depending on it. (Before M1b, every program pulled+the file in as a module with `#[path = "...ulib.rs"] mod ulib;`; the kernel+repo still does that for its own test programs.) `build.rs` here is the build script shared by all packages: it adds `-T rust/link.ld` to the link.
@@ -2,14 +2,19 @@ //! eprintln!, a small heap (so `Vec` and `String` work), the `_start` entry //! point and a panic handler. //!-//! Each user program includes it with-//! #[macro_use] #[path = "ulib.rs"] mod ulib;-//! and defines `fn main() -> i64` (the exit code).+//! It is a library crate: package `rbrt`, imported as `ulib`. Each program+//! depends on it (`ulib = { package = "rbrt", path = "../rbrt" }`) and starts+//! with+//! #[macro_use] extern crate ulib;+//! ulib::entry!(main);+//! where `fn main() -> i64` returns the exit code. `entry!` exports that+//! function under the fixed name `rbrt_main`, which `_start` calls. //! //! User programs are built for the `x86_64-unknown-none` target, which has //! SSE/floating point disabled. That matters: the kernel doesn't save SSE //! registers on a context switch. +#![no_std] #![allow(dead_code, unused_macros)] extern crate alloc;@@ -1091,10 +1096,11 @@ impl Drop for LineWriter { } } +#[macro_export] macro_rules! print { ($($arg:tt)*) => {{ use core::fmt::Write;- let mut out = $crate::ulib::LineWriter::new(1);+ let mut out = $crate::LineWriter::new(1); let _ = write!(out, $($arg)*); }}; }@@ -1118,18 +1124,20 @@ impl fmt::Write for Fd { } } +#[macro_export] macro_rules! eprintln { ($($arg:tt)*) => {{ use core::fmt::Write;- let mut out = $crate::ulib::LineWriter::new(2);+ let mut out = $crate::LineWriter::new(2); let _ = writeln!(out, $($arg)*); }}; } +#[macro_export] macro_rules! println { ($($arg:tt)*) => {{ use core::fmt::Write;- let mut out = $crate::ulib::LineWriter::new(1);+ let mut out = $crate::LineWriter::new(1); let _ = writeln!(out, $($arg)*); }}; }@@ -1159,7 +1167,22 @@ extern "C" fn start_rust(sp: *const usize) -> ! { } AUXV = p.add(1) as *const [u64; 2]; }- exit(crate::main())+ unsafe extern "Rust" {+ fn rbrt_main() -> i64; // the program's main, exported by `entry!`+ }+ exit(unsafe { rbrt_main() })+}++/// `ulib::entry!(main);` in a program: export its `fn main() -> i64` as+/// `rbrt_main`, the function `_start` calls.+#[macro_export]+macro_rules! entry {+ ($main:path) => {+ #[unsafe(no_mangle)]+ fn rbrt_main() -> i64 {+ $main()+ }+ }; } #[panic_handler]
@@ -8,6 +8,9 @@ publish.workspace = true build = "../rbrt/build.rs" autobins = false +[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+ [[bin]] name = "rbsh" path = "src/main.rs"
@@ -24,9 +24,8 @@ extern crate alloc; -#[macro_use]-#[path = "../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); #[path = "parse.rs"] mod shparse;
@@ -8,6 +8,9 @@ publish.workspace = true build = "../rbrt/build.rs" autobins = false +[dependencies]+ulib = { package = "rbrt", path = "../rbrt" }+ [[bin]] name = "getty" path = "src/bin/getty.rs"
@@ -20,9 +20,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -10,9 +10,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); use ulib::*;
@@ -9,8 +9,8 @@ #![no_main] #[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); fn main() -> i64 { let before = ulib::sysinfo();
@@ -18,9 +18,8 @@ #![no_std] #![no_main] -#[macro_use]-#[path = "../../../rbrt/ulib.rs"]-mod ulib;+extern crate ulib;+ulib::entry!(main); extern crate alloc; use alloc::vec;