fix(#41): restore Intel Mac build via ort-dynamic + Homebrew ONNX Runtime (#43)

* fix: restore Intel Mac build via ort-dynamic + system libonnxruntime

Microsoft is discontinuing x86_64 macOS ONNX Runtime prebuilts after
v1.23.0, so ort-sys 2.0.0-rc.11 can't ship an Intel Mac binary and never
will. Previous Intel Mac attempts kept dying in the ort-sys build script
with "does not provide prebuilt binaries for the target x86_64-apple-darwin
with feature set (no features)." Issue #41 was the latest casualty.

Fix: route Intel Mac through the ort-dynamic feature path (runtime dlopen
against a system libonnxruntime installed via Homebrew). This sidesteps
ort-sys prebuilts entirely and works today.

Changes:

- crates/vestige-core/Cargo.toml: split `embeddings` into code-only vs
  backend-choice. The embeddings feature now just pulls fastembed + hf-hub
  + image-models and activates the 27 #[cfg(feature = "embeddings")] gates
  throughout the crate. New `ort-download` feature carries the
  download-binaries-native-tls backend (the historical default). Existing
  `ort-dynamic` feature now transitively enables `embeddings`, so the
  cfg gates stay active when users swap backends.

  Default feature set expands `["embeddings", ...]` -> `["embeddings",
  "ort-download", ...]` so existing consumers see identical behavior.

- crates/vestige-mcp/Cargo.toml: mirrors the split. Adds `ort-download`
  feature that chains to vestige-core/ort-download, keeps `ort-dynamic`
  that chains to vestige-core/ort-dynamic. Both transitively pull
  `embeddings`. Default adds `ort-download` so `cargo install vestige-mcp`
  still picks the prebuilt-ort backend like before.

- .github/workflows/ci.yml: re-adds x86_64-apple-darwin to the
  release-build matrix with `--no-default-features --features
  ort-dynamic,vector-search`. Adds a `brew install onnxruntime` step that
  sets ORT_DYLIB_PATH from `brew --prefix onnxruntime`.

- .github/workflows/release.yml: re-adds x86_64-apple-darwin to the
  release matrix with the same flags + brew install step. The Intel Mac
  tarball now also bundles docs/INSTALL-INTEL-MAC.md so binary consumers
  get the `brew install onnxruntime` + ORT_DYLIB_PATH prereq out of the
  box.

- docs/INSTALL-INTEL-MAC.md: new install guide covering the Homebrew
  prereq, binary install, source build, troubleshooting, and the v2.1
  ort-candle migration plan.

- README.md: replaces the "Intel Mac and Windows build from source only"
  paragraph with the prebuilt Intel Mac install (brew + curl + env var)
  and a link to the full guide. Platform table updated: Intel Mac back
  on the "prebuilt" list.

Verified locally on aarch64-apple-darwin:
- `cargo check --release -p vestige-mcp` -> clean (default features)
- `cargo check --release -p vestige-mcp --no-default-features
   --features ort-dynamic,vector-search` -> clean

Runtime path on Intel Mac (verified on CI):
  brew install onnxruntime
  export ORT_DYLIB_PATH=$(brew --prefix onnxruntime)/lib/libonnxruntime.dylib
  vestige-mcp --version

Fixes #41. Long-term plan (v2.1): migrate to ort-candle pure-Rust backend
so no system ONNX Runtime dep is needed on any platform.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(ci): drop unused brew install + ORT_DYLIB_PATH from CI steps

Build is a cross-compile (macos-latest runner is Apple Silicon targeting
x86_64-apple-darwin) and ort-load-dynamic doesn't link libonnxruntime at
build time — only at runtime via dlopen. So the brew install step and
ORT_DYLIB_PATH export were ceremony without payload. Removed to cut CI
time. Runtime setup remains documented in docs/INSTALL-INTEL-MAC.md for
end users installing the tarball on their own Intel Mac.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: run release-build on PRs too — catch Intel Mac regressions pre-merge

Previously release-build was gated behind `github.ref == 'refs/heads/main'`,
so the Intel Mac, aarch64-apple-darwin, and Linux release targets were only
validated AFTER merge to main. If someone broke the Intel Mac cross-compile
by touching feature flags or Cargo dependencies, we'd only find out when
the release tag was cut and the job exploded on main. Extending the guard
to also fire on pull_request means regressions surface in the PR status
check instead of on a release branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sam Valladares 2026-04-23 02:03:45 -05:00 committed by GitHub
parent d3a2274778
commit 5b993e841f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 149 additions and 30 deletions

73
docs/INSTALL-INTEL-MAC.md Normal file
View file

@ -0,0 +1,73 @@
# Intel Mac Installation
The Intel Mac (`x86_64-apple-darwin`) binary links dynamically against a system
ONNX Runtime instead of a prebuilt ort-sys library. Microsoft is discontinuing
x86_64 macOS prebuilts after ONNX Runtime v1.23.0, so we use the
`ort-dynamic` feature to runtime-link against the version you install locally.
This keeps Vestige working on Intel Mac without waiting for a dead upstream.
## Prerequisite
Install ONNX Runtime via Homebrew:
```bash
brew install onnxruntime
```
## Install
```bash
# 1. Download the binary
curl -L https://github.com/samvallad33/vestige/releases/latest/download/vestige-mcp-x86_64-apple-darwin.tar.gz | tar -xz
sudo mv vestige-mcp vestige vestige-restore /usr/local/bin/
# 2. Point the binary at Homebrew's libonnxruntime
echo 'export ORT_DYLIB_PATH="'"$(brew --prefix onnxruntime)"'/lib/libonnxruntime.dylib"' >> ~/.zshrc
source ~/.zshrc
# 3. Verify
vestige-mcp --version
# 4. Connect to Claude Code
claude mcp add vestige vestige-mcp -s user
```
`ORT_DYLIB_PATH` is how the `ort` crate's `load-dynamic` feature finds the
shared library at runtime. Without it the binary starts but fails on the first
embedding call with a "could not find libonnxruntime" error.
## Building from source
```bash
brew install onnxruntime
git clone https://github.com/samvallad33/vestige && cd vestige
cargo build --release -p vestige-mcp \
--no-default-features \
--features ort-dynamic,vector-search
export ORT_DYLIB_PATH="$(brew --prefix onnxruntime)/lib/libonnxruntime.dylib"
./target/release/vestige-mcp --version
```
## Troubleshooting
**`dyld: Library not loaded: libonnxruntime.dylib`** — `ORT_DYLIB_PATH` is not
set for the shell that spawned `vestige-mcp`. Claude Code / Codex inherits the
env vars from whatever launched it; export `ORT_DYLIB_PATH` in `~/.zshrc` or
`~/.bashrc` and restart the client.
**`error: ort-sys does not provide prebuilt binaries for the target
x86_64-apple-darwin`** — you hit this only if you ran `cargo build` without the
`--no-default-features --features ort-dynamic,vector-search` flags. The default
feature set still tries to download a non-existent prebuilt. Add the flags and
rebuild.
**Homebrew installed `onnxruntime` but `brew --prefix onnxruntime` prints
nothing** — upgrade brew (`brew update`) and retry. Older brew formulae used
`onnx-runtime` (hyphenated). If your brew still has the hyphenated formula,
substitute accordingly in the commands above.
## Long-term
Intel Mac will move to a fully pure-Rust backend (`ort-candle`) in Vestige
v2.1, removing the Homebrew prerequisite entirely. Track progress at
[issue #41](https://github.com/samvallad33/vestige/issues/41).