Rust bindings for Apple's Virtualization framework, for creating and running Linux and macOS virtual machines on a Mac.
This project provides safe access to Apple's APIs, as close to the upstream API as possible. Types and methods mirror Virtualization, without providing extra functionality.
It also binds other frameworks that virtual machines need: DiskImageKit for disk images, vmnet for networks, AccessoryAccess for USB accessories, and IOUSBHost for the USB devices AccessoryAccess opens.
examples/ has programs using the crates.
boot_linux.rs starts a Linux virtual machine from a
kernel image:
cargo build -p virtualization-test --example boot_linux
bin/dev/sign target/debug/examples/boot_linux
target/debug/examples/boot_linux /path/to/vmlinuxVirtualization won't start a machine without the
com.apple.security.virtualization entitlement, so binaries must be signed
after each build:
codesign --force --entitlements virtualization.entitlements \
--sign - target/debug/your-binary- macOS 27 or later. Every Virtualization API is available, without availability checks.
- Xcode, for the Swift toolchain used by the build (found via
xcrun). - Rust 1.98 or later.
Crates compile on other platforms, but stub each API call to fail with
Error::Unsupported.
Much of Apple's API is Swift-only (DiskImageKit has no Objective-C at all), so bindings go through Swift rather than through the Objective-C runtime. Each framework has a small Swift package that forwards calls one-for-one, connected to Rust via swift-bridge. Foundation types come from objc2 and dispatch queues from dispatch2.
Each framework is a pair of crates: a -sys crate that holds the Swift
package, the bridge, and all the unsafe code, and a safe crate on top that
forbids unsafe.
| Crate | What it is |
|---|---|
virtualization |
Virtualization: configurations, virtual machines, devices, boot loaders. |
disk-image-kit |
DiskImageKit: creating and opening disk images. |
vmnet-framework |
vmnet's networks, which a virtual machine can attach to. (vmnet on crates.io is a different project.) |
accessory-access |
AccessoryAccess: finding USB accessories and passing them through to a virtual machine. |
io-usb-host |
IOUSBHost's IOUSBHostDevice, which AccessoryAccess opens. |
*-sys |
The Swift package and swift-bridge FFI behind each of the above. Use the safe crate instead. |
apple-bridge-foundation |
The Foundation glue the -sys crates share: objc2 objects, and NSError, NSMutableData, and property list values as plain Rust. |
apple-bridge-build |
Build scripts shared by -sys crates: generates swift-bridge's glue, builds the Swift package, and links it. |
virtualization-test |
Integration test suites, and the owner of examples/. Not published. |
Depend on virtualization, plus the safe crates whose types you use with it.
Development tasks run through medic, which checks that your machine has what the project needs and specifies all checks required to ship changes. It is available via a custom Homebrew tap:
brew bundleThen let medic check your setup:
medic doctor
medic test
medic audit
medic update
medic shipitCheck out its config in .config/medic.toml.
You'll also need Xcode, and swift-format on your PATH for formatting and
linting the Swift.
Integration suites in crates/virtualization-test boot real virtual
machines, so require a Mac and some setup, which medic test handles:
- Signing. Cargo builds test binaries unsigned, and Virtualization refuses
to run without its entitlement.
bin/dev/test-integrationbuilds the suites, signs each binary withvirtualization.entitlements, and runs them with nextest. Extra arguments go to nextest, so one test runs withbin/dev/test-integration -E 'test(name)'. Signing is ad hoc unless you setDEVELOPMENT_TEAMto your team ID. SetDEVELOPMENT_TEAMto keep code identity stable across builds. - A kernel and busybox. The first run downloads a Linux kernel and a static
busybox into
~/.cache/virtualization-tests, checked against pinned hashes. Guests boot from them. - Network access. Some suites fetch Apple's catalog of macOS restore images to learn the latest hardware model. No restore image is downloaded.
- A screen. A few tests use AppKit and need a logged-in Mac with a display.
They're named
screen::…, skipped by default, and run withbin/dev/test-integration --profile screen.
Suites are signed only with com.apple.security.virtualization. So bridged
networking, which needs a provisioning profile from Apple, is tested only
failing validation. USB passthrough, which needs a real accessory and an
app entitlement, is automatically tested only as far as possible without
entitlement.
bin/dev/swift-interfaceprints how Swift imports a framework from the macOS SDK, for APIs Apple documents only in Objective-C.bin/dev/format-swift --allformats the Swift sources;bin/dev/lint-swiftlints them.bin/dev/sign <binary>signs any binary with the virtualization entitlement.
docs/ holds a copy of Apple's documentation for each framework, which is the
reference for what each type has.
MIT. See LICENSE.md.