# macOS macOS is out of scope for v1 ([requirements.md](requirements.md)), and nobody working on DarkRoom has a Mac. This page records what exists anyway, and how a macOS build is set up so that someone who does have one can send back enough to fix what they hit. ## 1. What exists - **Inference** ([inference.md §2](inference.md)). The macOS ladder is CoreML, then ONNX Runtime's CPU provider, then tract. CoreML is unmeasured. The probe decides whether it is used, and the crash guard (§4, `attempt`) covers the case where the provider takes the process down. The device fingerprint is the chip (`machdep.cpu.brand_string`) and the OS release, because CoreML ships with the OS. - **Where files go** ([`dr_plat::dirs`](../../platform/dr-plat/src/dirs.rs)). The Unix rules, except the state directory (the log and crash records), which is `~/Library/Logs/darkroom`. - **A diagnostic build**, described in §3. The rest is not built, packaged or run on macOS by anyone here. This covers the window, Metal through wgpu, the display profile (FR-DSP-8 asks X11 and Wayland), the keyring, the bundle, and signing. `dr-plat` sends every non-Android Unix to the X11/Wayland dependencies. ## 2. Building `docker/macos` compiles and links for macOS from Linux, using zig as the linker (`cargo-zigbuild`). Zig carries libSystem's stubs and the C headers, so tract's SIMD kernels compile and anything that needs only libSystem links: ./docker/macos/build.sh cargo zigbuild --target aarch64-apple-darwin -p dr-inference-engine --features native --all-targets ./docker/macos/build.sh cargo-zigbuild clippy --target aarch64-apple-darwin -p dr-inference-engine --features native --all-targets -- -D warnings That produces Mach-O arm64 test binaries and the `ladder` and `ep_probe` examples. Nothing runs them. Anything that links an Apple framework needs the Xcode SDK, which zig does not carry. That includes `dr-plat` (through the keyring's Security and CoreFoundation) and so the desktop app, and its link fails with `unable to find framework`. `cargo check` for those still works in the container. Linking the app needs Apple's SDK, which means a Mac. On one: cargo build --profile diagnostic -p darkroom-desktop ./tools/fetch-desktop-runtime.sh # ONNX Runtime 1.29.0 with CoreML, Apple silicon only The fetch script puts `libonnxruntime.dylib` in the user's `runtime/` directory, next to the models. The app also looks in `Contents/Frameworks` of its own bundle, and in Homebrew's `/opt/homebrew/lib` and `/usr/local/lib`. Homebrew's build may not include CoreML; the probe reports that as a failed rung and uses the CPU. **For whoever packages it.** A notarised app runs with the hardened runtime, whose library validation refuses to `dlopen` a library signed by another team. A bundled `Contents/Frameworks/libonnxruntime.dylib` must be signed with the app. A runtime the user fetched needs the `com.apple.security.cs.disable-library-validation` entitlement, or it will not load, and the app will be the tract build without saying why beyond one log line. ## 3. The diagnostic build Every macOS build is in the hands of someone who can send a log but cannot attach a debugger, so it is set up to log like a debug build while running at release speed. - **The log says more.** With no `RUST_LOG`, the desktop's default filter is `debug` for every `dr_*` crate, for `darkroom_desktop`, and for `onnxruntime`. That last one is ONNX Runtime's own session log, which the engine forwards into `log` on every platform (`session.rs`, `with_runtime_log`). At `debug` it includes how many nodes each provider took. At `trace` (`RUST_LOG=onnxruntime=trace`) it lists every node's placement, which is long. The log cap is the same as everywhere (two files of 4 MiB). - **Backtraces have line numbers.** `--profile diagnostic` is release plus line tables. On macOS the tables go into a `.dSYM` beside the executable, and the backtrace in a crash record finds them only if the `.dSYM` stays next to the binary. Keep it in the bundle. ## 4. What to ask a Mac user for `~/Library/Logs/darkroom/darkroom.log`, plus `darkroom.log.1` if present, after the first launch and after the first scan with faces. Console.app lists it under *Log Reports*. The Settings diagnostics bundle collects the same files. The lines that answer the open questions are: | Line | What it tells us | |---|---| | `inference: ONNX Runtime … from …` / `inference: runtime tract` | Whether a runtime was found, and which one | | `inference: floor … ms on the CPU provider` | The CPU number for §2's table | | `inference: CoreML session built in … s` | CoreML's first compile of the probe model | | `inference: CoreML rejected: …` / `failed: …` | Why the CPU was kept | | `onnxruntime` lines naming `CoreMLExecutionProvider::GetCapability` | How much of the graph CoreML took | | `inference: the app died during …` | The crash guard fired, and on what | | `inference: compiling … for CoreML` / `ready on CoreML in … s` | Each model's compile, and any that CoreML refused | Also ask for the settings row (*Settings › About › Inference*), which is one line and says the same in short. When one of these logs comes back with CoreML numbers, they go into [inference.md §1–2](inference.md), and footnote ⁵ becomes a measurement.