Get a Iron checkout building, tested, and emitting a kernel.
- Rust nightly. The workspace is
edition = 2024and uses unstablerustfmtfeatures; the toolchain is pinned inrust-toolchain.toml, sorustupinstalls the right nightly automatically on first build. - macOS + Metal — only needed to run kernels on the GPU (
iron bench, GPU correctness tests). The DSL, codegen passes, and MSL emission build and test on any platform; non-Mac CI exercises everything except GPU dispatch. - Xcode command-line tools (
xcrun metal) on macOS — the codegen smoke step compiles emitted MSL with the Metal toolchain.
If you want to build and install the iron CLI from source rather than using
the release binary:
# From a local clone (recommended for contributors):
cargo install --path crates/wh-iron-cli
# Directly from the repository without cloning:
cargo install --git https://github.com/thewafflehaus/iron wh-iron-cliRequires Rust nightly — the toolchain is pinned in rust-toolchain.toml and
installed automatically by rustup on first build.
git clone git@github.com:thewafflehaus/iron.git
cd wh-iron
./scripts/setup-dev.shsetup-dev.sh verifies the nightly toolchain, the rustfmt and clippy components, and the optional typos-cli / cargo-llvm-cov tools.
make build # debug build of the whole workspace
make test # workspace tests — codegen, runtime, GPU correctness (GPU on a Mac)make is the canonical entry point — it centralises flags and always passes --workspace. See Developing for the full dev loop and the CLI reference for the iron binary.
The workspace is seven crates:
| Crate | Description |
|---|---|
wh-iron-core |
IR types, DType, Shape |
wh-iron-macros |
the #[kernel] proc-macro + body parser |
wh-iron-codegen |
MSL lowering + optimization passes |
wh-iron-runtime |
Metal dispatch, PSO cache |
wh-iron |
facade re-exporting all crates |
wh-iron-std |
kernel stdlib, op files, bench types |
wh-iron-cli |
the iron CLI binary |
The compile pipeline: #[kernel] fn → wh-iron-macros parses the body into Iron IR → wh-iron-codegen runs the optimization passes and emits MSL → wh-iron-runtime dispatches it on the GPU.
A kernel is a Rust function annotated with #[kernel]. The proc-macro parses the body into Iron IR; the codegen lowers it to Metal Shading Language.
use wh-iron::prelude::*;
#[kernel]
fn vector_add(a: Tensor<f32>, b: Tensor<f32>, c: Tensor<f32>) {
let idx = program_id::<0>();
store(c[idx], load(a[idx]) + load(b[idx]));
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let ctx = Context::new()?;
let n = 256usize;
let a: Vec<u8> = (0..n).flat_map(|i| (i as f32).to_le_bytes()).collect();
let b: Vec<u8> = (0..n).flat_map(|_| 1.0f32.to_le_bytes()).collect();
let c = vec![0u8; n * 4];
let result = vector_add::launch(&ctx)
.input("a", a)
.input("b", b)
.input("c", c)
.dispatch()?;
let out: Vec<f32> = result.outputs["c"]
.chunks_exact(4)
.map(|b| f32::from_le_bytes(b.try_into().unwrap()))
.collect();
println!("out[0] = {}", out[0]); // 1.0
Ok(())
}Inspect the generated MSL without running anything:
use wh-iron::codegen::msl::MslGenerator;
let msl = MslGenerator::default().generate(&vector_add::kernel_ir())?;
println!("{msl}");or from the CLI: iron inspect vector_add.
- Developing — repo layout, dev loop, and the kernel-authoring hazards. Read the
⚠️ sections before writing a non-trivial kernel — one of them is "a wrong dispatch can freeze your machine." - Testing — every non-trivial kernel ships a paired GPU correctness test in the same commit; this page explains why and how.