Boot XNU/Darwin with a native Mach-O userland on x86_64 and ARM64. Three root images are available: an interactive minimal shell, an Xfce4 desktop, and an Xfce4 desktop with native Chromium and ANGLE/SwiftShader WebGL. The supported kernel is XNU 12377.121.6 / Darwin 25.5.0. Guest applications use Darwin and Mach APIs directly.
Darwin Embedded is derived from PureDarwin, including its PC platform/storage support and compatibility headers. The supported hardware paths use the project's Pi 4B platform module and PC UEFI loader.
| Setup | Guest applications | Root image | QEMU machine |
|---|---|---|---|
| Minimal x86_64 | dash, native uname, BusyBox with 111 applets | 64 MiB HFS+ | q35 / Penryn |
| Minimal ARM64 | dash, native uname, BusyBox with 111 applets | 64 MiB HFS+ | raspi4b / Cortex-A72 |
| Xfce4 x86_64 | Xorg, Xfce session, xfwm4, settings, panels, desktop and original Xfce terminal/VTE | 128 MiB HFS+ | q35 / Penryn |
| Xfce4 ARM64 | The same native desktop stack | 128 MiB HFS+ | raspi4b / Cortex-A72 |
| Chromium ARM64 | Xfce4 desktop profile + native Chromium (ANGLE/SwiftShader software Vulkan) displaying live web pages (e.g. Yahoo!) | 384 MiB HFS+ | raspi4b / Cortex-A72 |
| Chromium x86_64 | Xfce4 desktop profile + native Chromium (ANGLE/SwiftShader software Vulkan) displaying live web pages (e.g. Yahoo!) | 384 MiB HFS+ | q35 / Penryn |
The screenshots below show actual Darwin runtime evidence from QEMU execution.
The minimal captures show Darwin kernel identity and a guest Mach-O header.
The Xfce captures show a hardware-typed challenge through the native Darwin PTY,
then uname -a and the Mach-O header of /bin/busybox typed into the terminal.
Both Chromium captures show live Yahoo! page content without that identity
output. Both browser roots passed fresh HTTP/JavaScript, WebGL, framebuffer,
full Yahoo document-completion and hardware mouse-wheel scroll checks. The
browser profile now selects CPU page compositing from startup and keeps
SwiftShader for WebGL. ARM64 probes the actual CPU features before enabling
V8 JIT. See validation for the context-loss history,
current test results and measured startup times. ARM64 remains slow under
TCG, including interaction after page load.
The desktop captures and Chromium browser captures are QEMU framebuffer dumps;
the minimal captures show their serial consoles.
Validation details explain the kernel, architecture,
process and executable checks and provide commands to reproduce them.
Both captures show genuine live Yahoo! content, taken
after QEMU mouse-wheel events scrolled the page down (it was then scrolled back
up). Both architectures
reached readyState: complete. See docs/VALIDATION.md.
Use Bazel for all builds. The build cross-compiles the guest applications and
runtime from source. Firmware is fetched from a pinned publisher package and
checked against recorded SHA-256 digests.
The Chromium executables use Git LFS. Install Git LFS before cloning, or run
git lfs install and git lfs pull in an existing checkout before packaging
the browser images.
Put LLVM 20's binary directory on PATH (for example,
export PATH=/usr/lib/llvm-20/bin:$PATH on Debian/Ubuntu), including ld64.lld.
bazel build //minimal_rootfs:images //rootfs:images
# Interactive minimal serial consoles; Ctrl-] exits.
bazel run //userland/apps/init:verify_arm64 -- --interactive
bazel run //userland/apps/init:verify_x86_64 -- --interactive
# Graphical desktops with a serial console; Ctrl-] exits.
bazel run //rootfs:boot_arm64
bazel run //rootfs:boot_x86_64
# Package the 3rd rootfs (Xfce4 + Chromium) using in-tree prebuilts:
python3 userland/apps/chromium/package_browser_rootfs.py --arch x86_64
python3 userland/apps/chromium/package_browser_rootfs.py --arch arm64Desktop targets open a QEMU GTK window. The browser launcher checks the two
architectures one at a time and uses KVM for x86_64 when the launching session
has access to /dev/kvm. Newly added KVM group membership takes effect after
a new login, or through sg kvm -c 'python3 scripts/bring_up_gui.py'.
ARM64 uses TCG on an x86 host; measured startup times and remaining limits are
recorded in VALIDATION.md. Add -- --verify-before-interactive to check native
utilities, desktop startup and hardware keyboard input before retaining the
running desktop. Headless verification commands appear in
VALIDATION.md.
The build requires Bazel, LLVM/Clang/LLD 20, GCC/G++, Python 3 with pexpect,
Pillow and websocket-client, Tesseract OCR, QEMU with raspi4b and GTK
support, and standard Unix build tools.
It also uses GNU Make for the XNU build, tcsh, m4, bison, flex, binutils, GLib
generators, gdisk, mtools, xxd, zstd and HFS+ formatting/checking tools.
Host tools need development libraries for zlib, OpenSSL, libxml2 and UUID.
Application compilation and linking are driven by Bazel actions.
Inside either guest, use ls, cp, grep, find, df -h, ps aux, vi,
less, bc, and archive/checksum commands. busybox --list shows the selected
applets. /bin/sh is dash; the Darwin ps and df implementations query real
kernel process and filesystem information.
This is an embedded Darwin port with verified shell and desktop startup in QEMU. Physical hardware, ARM SMP, broad peripheral support and a complete macOS service environment have not been verified. The embedded profile omits optional desktop services and Apple's complete trust-cache infrastructure. The desktop profile omits the Thunar file manager. ARCHITECTURE.md describes the runtime and its limits.
Original project code is BSD-2-Clause, matching PureDarwin's original-code license. Imported and derived code retains its upstream licenses. Read NOTICE and THIRD_PARTY_NOTICES.md, including the remaining binary redistribution assessment for GPL and APSL components, before publishing built image releases. The repository supplies source and notices.





