Building and Testing on macOS¶
This guide explains how to set up a local development environment on macOS so you can build and test ryll interactively without going through the Homebrew release cycle.
Prerequisites¶
Xcode Command Line Tools¶
The Xcode command line tools provide the C compiler and linker that Rust needs. If you haven't already installed them:
Rust toolchain¶
Install Rust via rustup:
Follow the prompts to install the stable toolchain. After
installation, ensure ~/.cargo/bin is on your PATH (the installer
usually adds this to your shell profile).
Verify:
No additional system libraries required¶
Unlike Linux (which needs X11, Wayland, and OpenGL development libraries), macOS builds use native Metal and AppKit backends via eframe. Everything you need comes with the Xcode Command Line Tools.
Clone the repository¶
Or, if you already have a checkout, just cd into it.
Building¶
Debug build (fast compile, slow runtime)¶
The binary lands at target/debug/ryll.
Release build (slow compile, optimised runtime)¶
The binary lands at target/release/ryll.
To match the CI deployment target (macOS 14 Sonoma and newer):
This is only necessary if you plan to distribute the binary to other machines. For local testing it makes no difference.
Running interactively¶
The quickest way during development is cargo run, which builds and
runs in one step:
# Debug build (faster compile)
cargo run -- --file /path/to/connection.vv
# Release build (faster runtime)
cargo run --release -- --file /path/to/connection.vv
# Direct connection
cargo run -- --direct 192.168.1.100:5900
# Headless with cadence mode
cargo run -- --file connection.vv --headless --cadence -v
Or run the binary directly:
Note: everything after -- is passed to ryll, not to cargo.
Running tests¶
Linting¶
To match what CI and the pre-commit hooks check:
# Check formatting
cargo fmt --check
# Auto-fix formatting
cargo fmt
# Run clippy
cargo clippy -- -D warnings
If you want to use the project's pre-commit hooks:
Note: the pre-commit hooks run rustfmt and clippy inside Docker, which will pull and build a container image on first use. If you prefer to run them natively (as shown above), that works too -- CI runs native cargo, not Docker.
Iterative development workflow¶
A typical edit-build-test cycle on macOS:
# 1. Make your changes
# 2. Check formatting and lint
cargo fmt && cargo clippy -- -D warnings
# 3. Run tests
cargo test
# 4. Build and run interactively
cargo run -- --file connection.vv -v
For faster iteration, use the debug build (cargo run without
--release). Compile times are significantly shorter. Switch to
--release when you need to test performance or match production
behaviour.
Verbose logging¶
Add -v to write detailed logs to /tmp/ryll.log:
Capture mode¶
Record protocol traffic and display video for debugging:
This writes per-channel pcap files and an MP4 video to the capture directory. See ARCHITECTURE.md for details on what is captured.
Differences from the devcontainer workflow¶
The devcontainer and Makefile targets (make build, make lint,
etc.) run everything inside a Docker container, which is useful for
consistent Linux builds but cannot run the macOS GUI. On macOS,
building natively with cargo is the right approach.
| Task | Devcontainer (Linux) | Native macOS |
|---|---|---|
| Debug build | make build |
cargo build |
| Release build | make release |
cargo build --release |
| Tests | make test |
cargo test |
| Lint | make lint |
cargo fmt --check && cargo clippy -- -D warnings |
| Lint + fix | make lint-fix |
cargo fmt |
| Run GUI | Not possible (no display) | cargo run -- --file ... |
Troubleshooting¶
Linker errors about missing frameworks¶
Ensure Xcode Command Line Tools are installed:
If you have multiple Xcode versions, make sure the active one is correct:
openh264 build issues¶
The openh264 crate (used by the capture feature) downloads a
pre-built library at build time. If this fails due to network issues,
you can build without capture support:
This disables --capture mode but everything else works normally.
Rust toolchain updates¶
Keep your toolchain current to match CI: