Skip to content

Commit fcd17f1

Browse files
dpsoftcspinetta
andauthored
add: macOS native support (#3)
* add: Enhance compatibility and extend tests for cross-platform support - Updated `load_module_file` to handle built-in kernel modules, improving resilience in aarch64/VZ environments. - Introduced comprehensive backend conformance test suite to validate KVM and VZ implementations. - Added macOS Virtualization.framework (VZ) backend with detailed configuration support. - Reorganized shared constants and structures for cross-platform reuse. - Enhanced protocol with optional version negotiation for better backward compatibility. * refactor: Simplify control flow, formatting, and function signatures across core components - Consolidated redundant control flow in `guest-agent`, `control_channel`, and `backend` modules. - Applied consistent formatting and compact function signatures for improved readability and maintainability. - Adjusted pre-commit hook path for streamlined formatting validation. - Enhanced Rust API's argument structures and handling for better clarity. * refactor: streamline conformance tests and enhance CI for cross-platform support - Unified backend availability checks with `backend_available` to improve readability and maintainability. - Replaced KVM-specific checks with a generic VM backend check across conformance tests. - Expanded GitHub Actions CI matrix to include macOS builds and tests for cross-platform compatibility. - Introduced dedicated E2E test workflow for macOS Virtualization.framework (VZ) backend. - Updated test image script to support musl cross-compilation and macOS environment. * refactor: implement `Default` for `KvmBackend`, simplify control flow, and enhance pre-commit hooks - Added `Default` implementation for `KvmBackend` to streamline initialization. - Simplified `is_running` with `is_some_and` and adjusted response handling in async task. - Enhanced pre-commit hooks to enforce `cargo clippy` checks with warnings as errors. * update: enforce Linux-only restriction for `guest-agent` and exclude it from macOS CI tasks - Added compile-time check to ensure `guest-agent` runs only on Linux (as PID 1 inside micro-VMs). - Updated GitHub Actions workflows to exclude `guest-agent` from macOS builds, tests, and documentation generation. * update: add `Send + Sync` safety guarantees for `VzBackend` and refactor socket device handling - Introduced `SendSyncDevice` wrapper for `VZVirtioSocketDevice` to ensure thread safety. - Implemented `Send` and `Sync` traits for `VzBackend`, with safe access guarantees. - Refactored connector and initialization logic to utilize the new `SendSyncDevice`. * update: improve type safety and refactor completion handler logic in `VzBackend` - Replaced generic `AnyObject` usage with specific `VZSocketDeviceConfiguration` and `VZNetworkDeviceConfiguration` types. - Ensured thread-safe wrappers for `SendSyncDevice` using `Arc`. - Refactored completion handler implementation with scoped variables to reduce mutex contention. - Addressed platform-specific code warnings for non-Linux builds. * refactor: use `block_in_place` for synchronous `VzBackend` VM setup and improve channel handling - Replaced async `oneshot` channels with synchronous `std::sync::mpsc::channel` for VM start/stop operations. - Refactored VM setup logic to execute synchronously via `tokio::task::block_in_place` for ObjC type safety. - Enhanced logging and streamlined configuration flow for better maintainability. * remove: drop `boot_diag.rs` example and update related configurations - Removed the `boot_diag.rs` Linux-specific example to simplify codebase and maintenance. - Adjusted CI documentation build command to use the `--workspace` flag for consistency. - Minor cleanup in `VzBackend` to remove unnecessary cast for file descriptor. * refactor: implement `Default` for `VzBackend` and update inconsistent doc links - Added `Default` implementation for `VzBackend` to simplify initialization. - Fixed inconsistent references to `ControlChannel` and `VmmBackend` in documentation comments for improved clarity. * fix: mark Low-Level VM Access doctest as ignored for macOS compatibility The doctest references MicroVm and VoidBoxConfig which are Linux-only types, causing doc-test failures on macOS CI. * update: add caching for musl-cross toolchain in macOS E2E workflow and increase timeout to 60 mins - Implemented caching of the musl-cross toolchain to optimize workflow execution. - Updated timeout for macOS E2E tests to 60 minutes to accommodate longer runs. - Improved musl-cross installation process with cache utilization and verification steps. * fix: make Virtualization.framework backend work end-to-end on macOS Apple Silicon - VZ backend: fix DispatchQueue thread affinity, vsock FD ownership (libc::dup), async streaming exec - Guest agent: DHCP-first networking for VZ NAT, tmpfs /tmp for sandbox user, relax RLIMIT_AS for Bun - Cross-build: auto-detect musl toolchain, download ARM64 glibc/busybox from Ubuntu packages - Refactor build_guest_image.sh into platform-specific modules (lib/guest_{common,linux,macos}.sh) - Add voidbox.entitlements and .cargo/config.toml for code-signing and cross-compilation - README: macOS prerequisites and run instructions * update: streamline kernel download process with helper script and adjust README setup steps - Added `scripts/download_kernel.sh` for simplified and reusable kernel downloads. - Refactored README setup steps to utilize the new script, improving clarity and organization. - Updated test image script to align with musl cross-compilation changes. - Removed hardcoded kernel version from macOS E2E workflow, delegating version control to the helper script. * update: improve `VzBackend` VM lifecycle management, add checksum verification, and enhance kernel script - Refactored `VzBackend` VM lifecycle to ensure thread safety and prevent dangling pointers on timeout or failure. - Introduced checksum verification for kernel downloads to ensure data integrity. - Enhanced kernel script with customizable `KERNEL_UPLOAD` version, updated URLs to HTTPS, and added SHA256 checks. - Adjusted pre-commit hooks to exclude `guest-agent` on macOS for compatibility. * update: improve kernel extraction to handle zstd-compressed `.deb` packages - Added support for zstd-compressed archives (`data.tar.zst`) in `scripts/download_kernel.sh`. - Enhanced error handling for missing or unsupported archive formats. - Improved compatibility with macOS and older GNU tar versions lacking native zstd support. * update: refine kernel extraction script, clean imports, and improve pre-commit checks - Simplified kernel extraction logic with added compatibility for macOS `bsdtar` and refined error handling for `.deb` packages. - Removed unused `AnyThread` import from `VzBackend`. - Adjusted pre-commit hook to remove unnecessary stderr redirection for better feedback during Clippy checks. * add: include `AnyThread` import in `VzBackend` for thread safety improvements * update: enhance kernel extraction script with improved file detection and error clarity - Replaced `ls` with `find` for more reliable `data.tar*` detection, ensuring cross-platform compatibility. - Refined error message for missing `data.tar` to improve user feedback during `.deb` extraction. * update: configure `tokio::test` to use multi-threaded runtime in conformance tests - Added `flavor = "multi_thread", worker_threads = 2` to all `tokio::test` annotations, improving test execution scalability. --------- Co-authored-by: Cristian Spinetta <cebspinetta@gmail.com>
1 parent f8e54b8 commit fcd17f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3538
-560
lines changed

.cargo/config.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[target.aarch64-unknown-linux-musl]
2+
linker = "aarch64-linux-musl-gcc"
3+
4+
[target.x86_64-unknown-linux-musl]
5+
linker = "x86_64-linux-musl-gcc"

.githooks/pre-commit

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
#!/usr/bin/env bash
22
set -e
3-
cd "$(git rev-parse --show-toplevel)/void-box"
3+
cd "$(git rev-parse --show-toplevel)"
44
if ! cargo fmt --all -- --check 2>/dev/null; then
55
echo "cargo fmt check failed. Run 'cargo fmt --all' and re-commit."
66
exit 1
77
fi
8+
CLIPPY_EXCLUDE=""
9+
if [[ "$(uname -s)" == "Darwin" ]]; then
10+
CLIPPY_EXCLUDE="--exclude guest-agent"
11+
fi
12+
if ! cargo clippy --workspace --all-targets --all-features $CLIPPY_EXCLUDE -- -D warnings; then
13+
echo "clippy check failed. Fix warnings and re-commit."
14+
exit 1
15+
fi

.github/workflows/ci.yml

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ env:
1212

1313
jobs:
1414
test:
15-
name: Test
16-
runs-on: ubuntu-latest
15+
name: Test (${{ matrix.os }} / ${{ matrix.rust }})
16+
runs-on: ${{ matrix.os }}
1717
strategy:
18+
fail-fast: false
1819
matrix:
19-
rust: [stable, beta]
20+
include:
21+
- os: ubuntu-latest
22+
rust: stable
23+
- os: ubuntu-latest
24+
rust: beta
25+
- os: macos-latest
26+
rust: stable
2027

2128
steps:
2229
- uses: actions/checkout@v4
@@ -46,14 +53,28 @@ jobs:
4653
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
4754

4855
- name: Run tests
49-
run: cargo test --workspace --all-features --verbose
56+
run: |
57+
if [[ "${{ runner.os }}" == "macOS" ]]; then
58+
cargo test --workspace --exclude guest-agent --all-features --verbose
59+
else
60+
cargo test --workspace --all-features --verbose
61+
fi
5062
5163
- name: Run doc tests
52-
run: cargo test --doc --workspace --all-features
64+
run: |
65+
if [[ "${{ runner.os }}" == "macOS" ]]; then
66+
cargo test --doc --workspace --exclude guest-agent --all-features
67+
else
68+
cargo test --doc --workspace --all-features
69+
fi
5370
5471
lint:
55-
name: Lint
56-
runs-on: ubuntu-latest
72+
name: Lint (${{ matrix.os }})
73+
runs-on: ${{ matrix.os }}
74+
strategy:
75+
fail-fast: false
76+
matrix:
77+
os: [ubuntu-latest, macos-latest]
5778

5879
steps:
5980
- uses: actions/checkout@v4
@@ -64,17 +85,24 @@ jobs:
6485
components: rustfmt, clippy
6586

6687
- name: Check formatting
88+
if: matrix.os == 'ubuntu-latest'
6789
run: cargo fmt --all -- --check
6890

6991
- name: Run clippy
70-
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
92+
run: |
93+
if [[ "${{ runner.os }}" == "macOS" ]]; then
94+
cargo clippy --workspace --exclude guest-agent --all-targets --all-features -- -D warnings
95+
else
96+
cargo clippy --workspace --all-targets --all-features -- -D warnings
97+
fi
7198
7299
build:
73-
name: Build
100+
name: Build (${{ matrix.os }})
74101
runs-on: ${{ matrix.os }}
75102
strategy:
103+
fail-fast: false
76104
matrix:
77-
os: [ubuntu-latest]
105+
os: [ubuntu-latest, macos-latest]
78106
rust: [stable]
79107

80108
steps:
@@ -95,8 +123,12 @@ jobs:
95123
run: cargo build --release --examples
96124

97125
docs:
98-
name: Documentation
99-
runs-on: ubuntu-latest
126+
name: Documentation (${{ matrix.os }})
127+
runs-on: ${{ matrix.os }}
128+
strategy:
129+
fail-fast: false
130+
matrix:
131+
os: [ubuntu-latest, macos-latest]
100132

101133
steps:
102134
- uses: actions/checkout@v4
@@ -105,13 +137,22 @@ jobs:
105137
uses: dtolnay/rust-toolchain@stable
106138

107139
- name: Build documentation
108-
run: cargo doc --no-deps --all-features
140+
run: |
141+
if [[ "${{ runner.os }}" == "macOS" ]]; then
142+
cargo doc --workspace --no-deps --all-features --exclude guest-agent
143+
else
144+
cargo doc --no-deps --all-features
145+
fi
109146
env:
110147
RUSTDOCFLAGS: -D warnings
111148

112149
msrv:
113-
name: Minimum Supported Rust Version
114-
runs-on: ubuntu-latest
150+
name: MSRV (${{ matrix.os }})
151+
runs-on: ${{ matrix.os }}
152+
strategy:
153+
fail-fast: false
154+
matrix:
155+
os: [ubuntu-latest, macos-latest]
115156

116157
steps:
117158
- uses: actions/checkout@v4
@@ -122,7 +163,12 @@ jobs:
122163
toolchain: "1.83"
123164

124165
- name: Check build with MSRV
125-
run: cargo build --workspace --all-features
166+
run: |
167+
if [[ "${{ runner.os }}" == "macOS" ]]; then
168+
cargo build --workspace --exclude guest-agent --all-features
169+
else
170+
cargo build --workspace --all-features
171+
fi
126172
127173
security:
128174
name: Security Audit

.github/workflows/e2e-macos.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: E2E macOS (Virtualization.framework)
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
RUST_BACKTRACE: 1
12+
13+
jobs:
14+
e2e-macos:
15+
name: E2E VZ (macOS Apple Silicon)
16+
runs-on: macos-14
17+
timeout-minutes: 60
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
# ---- System dependencies ----
23+
- name: Cache musl-cross toolchain
24+
id: cache-musl
25+
uses: actions/cache@v4
26+
with:
27+
path: |
28+
/opt/homebrew/Cellar/musl-cross
29+
/opt/homebrew/opt/musl-cross
30+
/opt/homebrew/bin/aarch64-linux-musl-*
31+
key: ${{ runner.os }}-musl-cross-1
32+
33+
- name: Install musl cross-compilation toolchain
34+
if: steps.cache-musl.outputs.cache-hit != 'true'
35+
run: |
36+
brew install filosottile/musl-cross/musl-cross
37+
38+
- name: Relink musl-cross from cache
39+
if: steps.cache-musl.outputs.cache-hit == 'true'
40+
run: |
41+
brew link musl-cross 2>/dev/null || true
42+
43+
- name: Verify musl-cross
44+
run: |
45+
which aarch64-linux-musl-gcc
46+
aarch64-linux-musl-gcc --version
47+
48+
# ---- Rust toolchain ----
49+
- name: Install Rust stable + aarch64 musl target
50+
uses: dtolnay/rust-toolchain@stable
51+
with:
52+
targets: aarch64-unknown-linux-musl
53+
54+
# ---- Cargo cache ----
55+
- name: Cache cargo registry + build
56+
uses: actions/cache@v4
57+
with:
58+
path: |
59+
~/.cargo/registry
60+
~/.cargo/git
61+
target
62+
key: ${{ runner.os }}-e2e-vz-${{ hashFiles('**/Cargo.lock') }}
63+
restore-keys: |
64+
${{ runner.os }}-e2e-vz-
65+
66+
# ---- Build test initramfs ----
67+
- name: Build test initramfs (guest-agent + claudio)
68+
run: scripts/build_test_image.sh
69+
70+
# ---- Download prebuilt arm64 Linux kernel ----
71+
- name: Download arm64 Linux kernel
72+
run: |
73+
scripts/download_kernel.sh
74+
cp target/vmlinuz-arm64 /tmp/void-box-kernel
75+
76+
# ---- Run conformance tests ----
77+
- name: Run conformance E2E tests
78+
env:
79+
VOID_BOX_KERNEL: /tmp/void-box-kernel
80+
VOID_BOX_INITRAMFS: /tmp/void-box-test-rootfs.cpio.gz
81+
run: |
82+
echo "Kernel: $VOID_BOX_KERNEL"
83+
echo "Initramfs: $VOID_BOX_INITRAMFS"
84+
ls -la "$VOID_BOX_KERNEL"
85+
ls -la "$VOID_BOX_INITRAMFS"
86+
87+
# Run conformance tests (--ignored to include VM tests, sequential to avoid resource contention)
88+
cargo test --test conformance -- --ignored --test-threads=1

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Thank you for your interest in contributing to void-box! This document provides
2929
Enable the project's pre-commit hook to catch formatting issues before they reach CI:
3030

3131
```bash
32-
git config core.hooksPath void-box/.githooks
32+
git config core.hooksPath .githooks
3333
```
3434

3535
This runs `cargo fmt --all -- --check` on every commit.

Cargo.lock

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)