Skip to content

Gate NAX JIT sources by macOS SDK version#3426

Open
ausimian wants to merge 1 commit intoml-explore:mainfrom
ausimian:fix/gate-jit-nax-by-sdk
Open

Gate NAX JIT sources by macOS SDK version#3426
ausimian wants to merge 1 commit intoml-explore:mainfrom
ausimian:fix/gate-jit-nax-by-sdk

Conversation

@ausimian
Copy link
Copy Markdown

@ausimian ausimian commented Apr 19, 2026

Proposed changes

When MLX_METAL_JIT=ON, backend/metal/CMakeLists.txt unconditionally invokes make_jit_source() on the NAX kernel sources. Those headers transitively #include <MetalPerformancePrimitives/MetalPerformancePrimitives.h>, which only ships with the macOS 26.2+ SDK, so JIT builds currently fail on older SDKs (e.g. Xcode 15.x on GitHub-hosted macos-14 runners):

fatal error: 'MetalPerformancePrimitives/MetalPerformancePrimitives.h' file not found
  included from vendor/mlx/mlx/backend/metal/kernels/steel/gemm/nax.h:12

The AOT branch in kernels/CMakeLists.txt already gates NAX by the same SDK check (MLX_METAL_VERSION GREATER_EQUAL 400 AND MACOS_SDK_VERSION GREATER_EQUAL 26.2). This PR mirrors that gate in the JIT branch:

  • When the SDK gate passes: no behavioural change — NAX JIT sources are emitted as before.
  • When it fails: define MLX_METAL_NO_NAX (so is_nax_available() returns false at runtime) and emit a tiny generated nax_stubs.cpp with empty-string stubs for the NAX JIT source providers (metal::gemm_nax, metal::quantized_nax, …). The stubs are needed only so jit_kernels.cpp still links; they are never exercised at runtime because the NAX code paths are guarded by is_nax_available().

On older SDKs, MLX_METAL_JIT=ON now produces the same no-NAX binary that MLX_METAL_JIT=OFF already does — it just uses the JIT path for the non-NAX kernels.

Context

Discovered while plumbing MLX_METAL_JIT=ON through a downstream consumer's CI (GitHub-hosted macos-14 / Xcode 15.x). MLX's own CI builds JIT on a self-hosted runner with Xcode 26, so the upstream CI does not currently exercise the JIT path on older SDKs.

Tested

  • Local build on macOS 26.4 / Xcode 26 — SDK gate passes, all NAX JIT sources emitted, behaviour identical to current main.
  • Build + run the downstream consumer's full test suite with MLX_METAL_JIT=ON on GitHub-hosted macos-14 — previously broken at the nax.h preprocess step, now links and passes after this patch.

Checklist

  • I have read the CONTRIBUTING document
  • I have run pre-commit run --all-files to format my code / installed pre-commit prior to committing changes — CMake-only change; happy to run cmake-format if the maintainers prefer a specific output.
  • I have added tests that prove my fix is effective or that my feature works — no test changes; this is a build-system guard mirroring an existing one.
  • I have updated the necessary documentation (if needed) — no public doc change.

MLX's JIT branch in backend/metal/CMakeLists.txt unconditionally runs
make_jit_source() on the NAX kernel sources. Those headers
transitively include <MetalPerformancePrimitives/...>, which only
ships with the macOS 26.2+ SDK, so MLX_METAL_JIT=ON currently fails
to build on older SDKs (e.g. Xcode 15.x on GitHub-hosted macos-14
runners), stopping at:

    fatal error: 'MetalPerformancePrimitives/MetalPerformancePrimitives.h'
    file not found

Mirror the same SDK gate the AOT branch already applies in
kernels/CMakeLists.txt (MLX_METAL_VERSION >= 400 AND
MACOS_SDK_VERSION >= 26.2). When the gate fails, define
MLX_METAL_NO_NAX so is_nax_available() returns false at runtime, and
emit a small generated .cpp with empty-string stubs for the NAX JIT
source providers (metal::gemm_nax, metal::quantized_nax, ...) so
jit_kernels.cpp still links. The stubs are never exercised because
the callers are guarded by is_nax_available().

No behavioural change on macOS 26.2+ SDK builds (gate passes; NAX JIT
sources are emitted as before). On older SDKs, JIT=ON now builds a
binary without NAX support, exactly mirroring how JIT=OFF already
behaves on the same SDK.
@ausimian ausimian force-pushed the fix/gate-jit-nax-by-sdk branch from 2251c30 to 1089f64 Compare April 19, 2026 02:42
ausimian added a commit to ausimian/emily that referenced this pull request Apr 19, 2026
Note the MetalPerformancePrimitives SDK gap on older Xcodes (e.g.
GitHub's macos-14 runner) and point to the upstream fix at
ml-explore/mlx#3426 so the patches/ directory can be retired once
the submodule is bumped past it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant