Skip to content

build: pin explicit per-variant macOS deployment targets - #203

Merged
ausimian merged 1 commit into
mainfrom
build/pin-macos-deployment-target
Jul 8, 2026
Merged

build: pin explicit per-variant macOS deployment targets#203
ausimian merged 1 commit into
mainfrom
build/pin-macos-deployment-target

Conversation

@ausimian

@ausimian ausimian commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Closes #202.

Problem

Neither the MLX build (scripts/build-mlx.sh) nor the NIF link (mix.exs) sets a macOS deployment target, so:

  • MLX's objects inherit the build host's OS version (MLX's CMake "builds for the host" when CMAKE_OSX_DEPLOYMENT_TARGET is unset), while the NIF links at the SDK-major .0 → the ld: … built for newer 'macOS' version (26.4) than being linked (26.0) warnings.
  • The shipped precompiled NIF's minimum-macOS drifts with the runner OS. Worse, an aot build done on a macOS-26 host silently links the macOS-26 libSystem _Float16 helpers __fmaxf16/__fminf16 as hard (non-weak) imports — it would fail to dyld-load on the older macOS the aot variant is supposed to support. The aot artifact is portable today only because it happens to build on macos-14.

Change

Pin an explicit, per-variant floor and thread it through both halves of the build from one source of truth (macos_deployment_target/0 in mix.exs):

  • MLX build → -DCMAKE_OSX_DEPLOYMENT_TARGET (build-mlx.sh, new 5th arg).
  • NIF compile+link → MACOSX_DEPLOYMENT_TARGET (make_env/0; clang honours it for both).

Floors: aot = 14.0 (the older-macOS path; MLX's own floor), jit = 26.2 (its NAX kernels + JACCL are gated on macOS SDK ≥ 26.2). The floor is folded into the MLX cache-dir name so changing it can't reuse a stale build.

scripts/verify-nif-floor.sh asserts the built NIF's LC_BUILD_VERSION matches the pinned floor and that a sub-26 floor imports no macOS-26 _Float16 symbols. Wired into ci.yml (per variant) and release-nif.yml (guards the shipped artifact before packaging).

Verification (on a macOS 26.5 host)

Before → after for the aot build, same host:

__fmaxf16/__fminf16 LC_BUILD_VERSION ld mismatch warnings
host-default target imported (needs macOS 26) minos 26.0 many
pinned 14.0 none minos 14.0 0
  • scripts/verify-nif-floor.sh … 14.0 passes; correctly rejects a wrong floor (26.2).
  • mix precommit green — 737 tests / 40 doctests / 79 properties, 0 failures.
  • mix test --only conformance green — 52 tests, 0 failures.

Notes

  • Build/packaging only; no source or API change. jit's 26.2 floor matches the existing rationale in ci.yml/release-nif.yml (NAX includes MetalPerformancePrimitives.h, first shipped in the 26.2 SDK).
  • CI will now build both variants on their target hosts (macos-14/macos-26) and assert each floor — the definitive runtime check the codebase already had, now with a declared, verified minimum.

The MLX build and NIF link set no deployment target, so MLX's objects
inherited the build host's OS (CMake "build for host") while the NIF
linked at the SDK-major .0 — producing `ld` version-mismatch warnings
and a shipped floor that drifts with the runner OS. An aot build done on
a macOS-26 host silently linked the macOS-26 libSystem `_Float16` helpers
(`__fmaxf16`/`__fminf16`) as hard imports, so it would fail to dyld-load
on the older macOS the aot variant is meant to support.

Pin an explicit per-variant floor (aot 14.0; jit 26.2, since its NAX
kernels and JACCL are gated on macOS SDK >= 26.2) and thread it through
both the MLX CMake build (CMAKE_OSX_DEPLOYMENT_TARGET) and the NIF
compile/link (MACOSX_DEPLOYMENT_TARGET) from one source of truth in
mix.exs. The floor is folded into the MLX cache dir name so a change
can't reuse a stale build. scripts/verify-nif-floor.sh asserts the built
NIF's LC_BUILD_VERSION and that a sub-26 floor imports no macOS-26
symbols; CI and the release workflow run it per variant.

Closes #202.
@ausimian

ausimian commented Jul 8, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 36d531bc1e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ausimian
ausimian merged commit dcb4cf8 into main Jul 8, 2026
3 checks passed
@ausimian
ausimian deleted the build/pin-macos-deployment-target branch July 8, 2026 10:44
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.

Pin explicit per-variant macOS deployment targets for the MLX build and NIF link

1 participant