Write native AmigaOS 4.1 applications, device drivers, and shared libraries in Rust.
Status: Beta — 31 safe wrapper modules, 129 SDK interface bindings, ~365 tests, 3 build modes. Tested on QEMU (-M amigaone) and real X5000 hardware.
Made with AI — This project (code, bindings, build infrastructure, and documentation) was built using Claude Code by Anthropic.
- Full
no_stdRust —coreandalloccrates compile to PowerPC Vec,String,format!,Box— heap allocation via global allocator- Three build modes — application (clib4), driver (ExecAllocator), shared library (Resident + interface vectors)
- 31 safe wrapper modules — GUI (ReAction), menus, ASL file requesters, networking (TCP/DNS/HTTP/HTTPS), async runtime, timer device, clipboard (IFFParse), DOS, file I/O, threads, and more
- 129 AmigaOS SDK interface bindings — Exec, DOS, Intuition, Graphics, Timer, IFFParse, and 123 more, all feature-gated
- Direct vtable dispatch — call any interface method from Rust via
#[repr(C)]structs (no overhead) - RAII everywhere —
AmigaWindow,AmigaTimer,AmigaLock,AmigaVec,TcpStream,PubScreen, and 14 more auto-cleanup on drop - Checked OS strings —
amstr!("text")builds null-terminated strings at compile time; every wrapper validates at the FFI boundary - ReAction GUI —
LayoutBuilderDSL,event_loop, button/string/checkbox/integer/slider/chooser/listbrowser gadgets - Menus —
MenuBuilderDSL over the OS4 menuclass, withMM_NEXTSELECTpick decoding - ASL file requester — Open/Save/Drawer dialogs with pattern filters
- application.library — RAII registration with single-instance enforcement
- Networking —
TcpStream,TcpListener,SocketAddrparser, DNS resolution, HTTP/1.1 GET client with redirects + chunked decoding - Async runtime — cooperative executor with Exec signal-based waking; awaitable timer delays and IDCMP window events
- Timer device —
AmigaTimerRAII withdelay(),get_sys_time(),get_up_time(),micro_delay(), asyncdelay_async() - Clipboard —
read_text()/write_text()via IFFParse FTXT/CHRS format - Shared library output — template with Resident struct, RTF_AUTOINIT, interface vector tables
- Exec device support —
examples/ram-deviceis a complete.device(BeginIO/AbortIO, quick I/O) in Rust;DmaBufferpairs MEMF_SHARED with cache maintenance - Third-party crates just work —
examples/gameboy-testruns Blargg's CPU tests inside padme-core, a complete no_std Game Boy emulator pulled straight from crates.io - PPC inline assembly — cache flush/invalidate, MMIO read/write (8/16/32-bit), memory barriers
- ~365 tests — host-side per-crate unit tests, doctests, and the black-box suite in
Tests/, plus 60 target-side integration tests run on QEMU - CI pipeline — GitHub Actions cross-compiles all 3 crates + 28 examples, runs host tests, publishes rustdoc
This project was developed and tested with the following exact versions. Other versions are not tested and are not supported.
| Component | Version | Notes |
|---|---|---|
| Rust | nightly-2026-03-01 |
Pinned in rust-toolchain.toml (nightly required for -Zbuild-std) |
| AmigaOS SDK | 54.16 (22.08.2022) |
AmigaOS 4.1 Final Edition SDK |
| Cross-compiler | ppc-amigaos-gcc 11.5.0 (adtools build) |
Inside Docker image |
| C library | clib4 commit 778afb03 (2026-05-14, upstream development / nightly) |
Source pinned as submodule in clib4-src/; pre-built binaries in clib4-nightly/ overlay at link time |
| Docker image | walkero/amigagccondocker:os4-gcc11 (built 2025-08-18) |
Contains GCC + SDK + clib4 |
| QEMU | qemu-system-ppc -M amigaone |
Test target |
| Software | Purpose | Link |
|---|---|---|
| Rust (rustup) | Host compiler | https://rustup.rs/ |
| adtools (ppc-amigaos-gcc) | AmigaOS cross-compiler | https://github.com/sba1/adtools |
| clib4 | POSIX-compatible C library for AmigaOS 4 | https://github.com/AmigaLabs/clib4 |
| Docker | Container runtime for cross-compiler | https://www.docker.com/ |
| amigagccondocker | Pre-built Docker image with GCC + SDK | https://hub.docker.com/r/walkero/amigagccondocker |
| AmigaOS 4.1 SDK | Headers, libraries, autodocs | https://www.hyperion-entertainment.com/ |
| QEMU | PPC emulator for testing | https://www.qemu.org/ |
git clone --recurse-submodules https://github.com/<user>/rust-for-amigaos4.git
# or, if you already cloned without --recurse-submodules:
git submodule update --init --recursiveThe clib4-src/ submodule pins the exact clib4 source (commit 778afb03, tip of the upstream development branch) the pre-built clib4-nightly/ binaries were produced from. Checkout is required for reproducible local rebuilds; it is not needed to run build.sh, which uses the pre-built binaries directly.
# Linux / macOS
chmod +x setup.sh && ./setup.sh
# Windows
setup.batThis installs the pinned Rust toolchain (read from rust-toolchain.toml) with rust-src, initialises submodules, and pulls the Docker cross-compiler image.
# Application
./build.sh examples/hello
# Driver
./build.sh examples/hello-driver
# Shared library
./build.sh examples/hello-library# Application (clib4, -lauto)
cp -r templates/app myproject
# Driver / Handler (no CRT)
cp -r templates/driver mydriver
# Shared Library (.library)
cp -r templates/library mylibEdit Cargo.toml (name), Makefile (TARGET, RUST_LIB), and src/main.rs (your code), then:
./build.sh myprojectApplication-mode binaries (built with -mcrt=clib4 -lauto, the default in templates/app/) are linked against a specific clib4 build and open clib4.library at runtime. Driver and shared-library modes do not need clib4 at all. Two concerns to keep straight:
build.sh overlays the contents of clib4-nightly/ onto the cross-compiler's SDK inside the Docker container on every link:
cp -r /repo/clib4-nightly/lib/* /opt/ppc-amigaos/ppc-amigaos/SDK/clib4/lib/
cp -r /repo/clib4-nightly/include/* /opt/ppc-amigaos/ppc-amigaos/SDK/clib4/include/You do not need to install anything into the Docker image yourself — the overlay is applied by the build script. The clib4 binaries that ship in clib4-nightly/ are reproducible from the clib4-src/ submodule at commit 778afb03 (see "Rebuilding clib4" below).
If you want to replace the overlaid clib4 with your own build, drop new lib/, include/, and clib4.library / clib4.library.debug files into clib4-nightly/ and re-run ./build.sh <project>. Nothing else needs to change.
The submodule is pinned to the exact source the pre-built clib4-nightly/ binaries came from:
# Build clib4.library + clib4.library.debug + lib*.a + CRT objects inside Docker
docker run --rm \
-v "$(pwd)":/repo \
-w /repo/clib4-src \
walkero/amigagccondocker:os4-gcc11 \
gmake -f GNUmakefile.os4 -j"$(nproc)"
# Outputs land in clib4-src/build/
ls clib4-src/build/clib4.library clib4-src/build/clib4.library.debug
ls clib4-src/build/lib/To use that build as the overlay, copy clib4-src/build/lib/* and clib4-src/build/clib4.library* into clib4-nightly/ (replacing the shipped binaries). Versions reported by the freshly-built library will match clib4.library 2.1 (<build-date>).
clib4.library for Rust programs must be placed in PROGDIR: — the same directory as the executable.
Checklist for application mode:
- Build your project:
./build.sh myproject - Copy into the target directory on the Amiga:
- The executable (
myproject/myproject) clib4-nightly/clib4.library(or your own build of it)
- The executable (
- Run from a Shell and observe with
dumpdebugbufferto seeserial_println!output.
Driver-mode (hello-driver) and shared-library-mode binaries do not need clib4.library at runtime — they use ExecAllocator and talk to IExec directly.
- No
stdcrate — this isno_stdonly; the Rust standard library does not support AmigaOS - No stack unwinding — panic strategy is
abort - No 64-bit atomics — PPC G3/G4 supports only 32-bit atomic operations
- TLS without verification by default —
httpsworks (OpenSSL via thetlsfeature), but AmigaOS has no system CA store, so peer verification is opt-in via a CA bundle - No Rust-native varargs — 5 varargs methods require C glue wrappers (provided)
- Audio needs an AHI-supported card —
audio-toneplays on QEMU; on machines where AHI finds no sound card,OpenDevice("ahi.device")fails cleanly
rust-for-amigaos4/
amigaos4-sys/ Raw FFI bindings (129 feature-gated interfaces, C glue, PPC asm)
amigaos4-alloc/ Global allocator backends (Clib4Allocator, ExecAllocator)
amigaos4/ Safe wrappers: 31 modules (GUI, menus, ASL, networking, async, DOS, timer, clipboard, POSIX)
clib4-nightly/ Pre-built clib4 C library overlay (binaries only)
clib4-src/ clib4 source pinned via submodule at commit 778afb03 (development tip)
rust-toolchain.toml Pins the exact Rust nightly (2026-03-01) used for all builds
target-spec/ Custom Rust target JSON + fake linker scripts
templates/ app/, driver/, and library/ starter templates
examples/ 28 examples (hello, hello-driver, hello-library, test-harness,
test-harness-gui, test-harness-net, file-io-demo, timer-demo,
thread-demo, gui-demo, net-demo, async-demo,
thread-amissl-probe, http-client, zlib-roundtrip,
picture-viewer, wbstartup-hello, xadmaster-list,
async-net-echo, iff-dump, locale-i18n-hello, audio-tone, ram-device, aminet-browser, https-client, sqlite3-demo, json-config, gameboy-test)
docs/ Roadmap, 10 phase progress logs, nostd-ecosystem guide
.github/workflows/ CI pipeline (builds all crates + 28 examples, runs host tests)
cargo-amiga.sh/.bat Project scaffolding, build, and run/test wrapper
Core (always available, no clib4 needed): application, asl, cstr, datatypes, error, tag, mem, port, screen, boopsi, window, gfx, requester, reaction, dos, locale, io, fmt, menu, panic, async_rt, timer, clipboard
Application-only (clib4, feature-gated): fs, time, env, thread, net, dns, http, https (tls feature)
| Application | Driver | Shared Library | |
|---|---|---|---|
| CRT | clib4 | None | None |
| Entry point | main() |
_start() → rust_handler_main() |
Resident + libInit() |
| Allocator | Clib4Allocator |
ExecAllocator |
ExecAllocator |
| POSIX modules | fs, time, env, thread, net, dns, http | Not available | Not available |
| Link flags | -mcrt=clib4 -lauto |
-nostartfiles -nodefaultlibs -lgcc |
-nostartfiles -nodefaultlibs -Wl,--undefined=RomTag -lgcc |
| Output | Executable | Handler/device | .library file |
All three modes support Vec, String, format!, Box via the global allocator.
Stage 1 (Your Machine) Stage 2 (Docker)
+---------------------+ +------------------------------+
| Rust source code | | ppc-amigaos-gcc links: |
| v | | C glue (.o) |
| cargo build | | + Rust staticlib (.a) |
| v | | + clib4 / SDK libs |
| libmyapp.a (PPC) |--->| v |
+---------------------+ | Native AmigaOS binary |
+------------------------------+
// Direct vtable call (no wrapper needed)
unsafe { ((*IExec).FindTask)(IExec, core::ptr::null()) }
// Or using convenience wrapper
unsafe { exec_find_task(core::ptr::null()) }// RAII — auto-cleanup on drop
let win = AmigaWindow::open(&tags)?;
let msg = win.wait_msg(); // copies and replies IDCMP message
// GUI builder DSL
let layout = LayoutBuilder::vertical()
.add(button(1, b"OK\0")?)
.add(button(2, b"Cancel\0")?)
.build()?;
// Networking
let mut stream = TcpStream::connect(&addr)?;
stream.write_all(b"Hello")?;
// Async
let mut exec = Executor::new()?;
let answer: u32 = exec.block_on(async { 42 });
// Timer
let mut timer = AmigaTimer::open(TimerUnit::MicroHz)?;
timer.delay(TimerVal::from_millis(500))?;
// Clipboard
clipboard::write_text(b"Copied from Rust!")?;
let text = clipboard::read_text()?;Already included in all templates. Add to .cargo/config.toml:
[unstable]
json-target-spec = trueAlready included in all templates. Add to .cargo/config.toml:
[unstable]
build-std-features = ["compiler-builtins-mem"]Check MEMF constants: MEMF_PRIVATE = 1 << 11 (0x800), MEMF_SHARED = 1 << 12 (0x1000).
The default AmigaOS shell stack is 64 KB; Rust code with large by-value structs (e.g. an emulator core with an emb
0 comments
log in to comment.