fix(nix): build risc0 Metal kernels on macOS by fixing xcrun env

risc0 compiles its Metal (GPU) prover kernels by invoking `xcrun metal` /
`xcrun metallib`. Under nix, the darwin stdenv exports DEVELOPER_DIR and
SDKROOT pointing at its own SDK, which makes xcrun look for the `metal`
tool in the wrong place and fail with:

    error: cannot execute tool 'metal' due to missing Metal Toolchain;
           use: xcodebuild -downloadComponent MetalToolchain

...even when a working Metal Toolchain is installed (the same call succeeds
in a clean environment where those vars are unset).

Wrap xcrun with a small shim, placed first in PATH, that clears
DEVELOPER_DIR/SDKROOT for `metal`/`metallib` invocations only — so they
resolve the system Xcode Metal Toolchain — while every other xcrun call
passes through with the nix environment intact. This makes wallet-ffi
build with real GPU prover kernels on macOS, with no --override-input
workaround needed downstream.

Note: on recent macOS the Metal Toolchain is a per-user component, so
`xcodebuild -downloadComponent MetalToolchain` must have been run by the
building user (and builds still require `--option sandbox false`).
This commit is contained in:
r4bbit 2026-06-24 10:09:47 +02:00
parent fce8722d05
commit 4fc1a97db6
No known key found for this signature in database
GPG Key ID: E95F1E9447DC91A9

View File

@ -99,6 +99,28 @@
sha256 = recursionZkrHash;
};
# risc0 compiles its Metal (GPU) prover kernels by invoking
# `xcrun metal` / `xcrun metallib`. Under nix, the darwin stdenv sets
# DEVELOPER_DIR/SDKROOT to its own SDK, which makes `xcrun` look for
# the `metal` tool in the wrong place and fail with
# error: cannot execute tool 'metal' due to missing Metal Toolchain
# even when a working Metal Toolchain is installed. This wrapper, put
# first in PATH, clears those two vars for metal/metallib invocations
# only — so they resolve the real system Xcode Metal Toolchain — while
# every other xcrun call passes through with the nix environment
# intact. (On recent macOS the Metal Toolchain is a per-user component;
# `xcodebuild -downloadComponent MetalToolchain` must have been run.)
metalStub = pkgs.writeShellScriptBin "xcrun" ''
tool=
for a in "$@"; do
case "$a" in metal|metallib) tool=1 ;; esac
done
if [ -n "$tool" ]; then
unset DEVELOPER_DIR SDKROOT
fi
exec /usr/bin/xcrun "$@"
'';
commonArgs = {
inherit src;
buildInputs = [ pkgs.openssl ];
@ -118,13 +140,14 @@
RECURSION_SRC_PATH = "${recursionZkr}";
# Provide a writable HOME so risc0-build-kernel can use its cache directory
# (needed on macOS for Metal kernel compilation cache).
# On macOS, append /usr/bin to PATH so xcrun (Metal compiler) can be found,
# while keeping Nix tools (like gnutar) first in PATH.
# On macOS, put the metalStub xcrun wrapper first so `xcrun metal` /
# `metallib` resolve the system Metal Toolchain (see metalStub above),
# and append /usr/bin for the real xcrun it execs.
# This requires running with --option sandbox false for Metal GPU support.
preBuild = ''
export HOME=$(mktemp -d)
'' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
export PATH="$PATH:/usr/bin"
export PATH="${metalStub}/bin:$PATH:/usr/bin"
'';
};