Skip to content

ci: C++ repro vs cmake-out libmlx.a + standalone counter-probe #19

ci: C++ repro vs cmake-out libmlx.a + standalone counter-probe

ci: C++ repro vs cmake-out libmlx.a + standalone counter-probe #19

name: MLX PR check (fork)
# REPRO C++ CONTRE L'ARTEFACT — trois sondes en un run :
# 1. repro_gather_mm.cpp lié contre le libmlx.a de cmake-out (l'artefact
# exact qui échoue dans op_test_runner) — SANS l'interpréteur ET.
# 2. Contre-épreuve : le MÊME repro contre un libmlx.a rebâti standalone
# avec les MÊMES args (source déjà patchée par l'ExternalProject).
# 3. Dumps des CMakeCache des deux builds pour comparaison.
#
# Grille :
# cmake-out DIVERGE + standalone DIVERGE -> repro minimal amont en main,
# cause dans (args de build x source patchée), bisectable sans ET.
# cmake-out DIVERGE + standalone OK -> spécifique à l'ExternalProject
# (env/toolchain/generator) -> comparer les deux CMakeCache dumpés.
# cmake-out OK -> l'artefact est sain ; le bug est
# dans la LIAISON d'op_test_runner (ODR/symboles) -> dossier à metascroy.
#
# Branche : ci-mlx-check = tête de PR (avec fix mémo, SANS jit-off.patch) +
# ce workflow (en .github/workflows/mlx-fork-check.yml) +
# repro_gather_mm.cpp à la racine.
on:
workflow_dispatch:
push:
branches:
- ci-mlx-check
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
cpp-repro:
runs-on: macos-14
timeout-minutes: 300
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Preuve — commit et flag JIT (doit être ON = état PR)
run: |
set -eux
git log --oneline -3
grep -n "MLX_METAL_JIT" backends/mlx/CMakeLists.txt
- name: Install ExecuTorch
run: |
set -eux
python -m pip install --upgrade pip
python install_executorch.py
- name: Configure + build op_test_runner
id: build
run: |
set -eux
cmake --preset mlx-release \
-DEXECUTORCH_BUILD_TESTS=ON \
-DEXECUTORCH_MLX_ENABLE_SANITIZERS=OFF
cmake --build cmake-out --target op_test_runner -j2
df -h /
- name: Dump — CMakeCache du build MLX (ExternalProject)
if: steps.build.outcome == 'success'
run: |
set -eux
CACHE=$(find cmake-out -path "*mlx*/CMakeCache.txt" | head -1)
echo "cache: $CACHE"
grep -E "CMAKE_BUILD_TYPE|CMAKE_CXX_STANDARD|CMAKE_CXX_FLAGS|CMAKE_CXX_COMPILER:|OSX_DEPLOYMENT|OSX_SYSROOT|MLX_METAL_JIT|MLX_BUILD_CPU|CMAKE_GENERATOR:" "$CACHE" | sort
# ------------------------------------------------------------------
# SONDE 1 — l'artefact exact (cmake-out), sans interpréteur ET.
# ------------------------------------------------------------------
- name: SONDE 1 — repro C++ vs libmlx.a de cmake-out
if: steps.build.outcome == 'success'
continue-on-error: true
run: |
set -eux
MLXA=$(find cmake-out -name libmlx.a | head -1)
METALLIB=$(find cmake-out -name mlx.metallib | head -1)
ls -la "$MLXA" "$METALLIB"
clang++ -std=c++17 -O2 repro_gather_mm.cpp \
-I backends/mlx/third-party/mlx \
-I "$(dirname "$MLXA")" \
"$MLXA" \
-framework Metal -framework Foundation -framework QuartzCore \
-o repro_cmakeout
cp "$METALLIB" .
./repro_cmakeout
# ------------------------------------------------------------------
# SONDE 2 — mêmes args, même source (déjà patchée par PATCH_COMMAND),
# build standalone hors ExternalProject. JIT=ON pour coller à l'état PR.
# ------------------------------------------------------------------
- name: SONDE 2 — repro C++ vs libmlx.a standalone (mêmes args)
if: steps.build.outcome == 'success'
continue-on-error: true
run: |
set -eux
# PATCH_COMMAND a déjà patché l'arbre source du sous-module :
git -C backends/mlx/third-party/mlx status --short | head -5
cmake -S backends/mlx/third-party/mlx -B /tmp/mlxsa \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DMLX_BUILD_METAL=ON \
-DMLX_BUILD_CPU=OFF \
-DMLX_BUILD_SHARED_LIBS=OFF \
-DMLX_BUILD_PYTHON_BINDINGS=OFF \
-DMLX_BUILD_TESTS=OFF -DMLX_BUILD_EXAMPLES=OFF \
-DMLX_BUILD_BENCHMARKS=OFF -DMLX_BUILD_GGUF=OFF \
-DMLX_BUILD_SAFETENSORS=OFF \
-DMLX_METAL_JIT=ON
cmake --build /tmp/mlxsa -j3
grep -E "CMAKE_BUILD_TYPE|CMAKE_CXX_FLAGS|OSX_DEPLOYMENT|OSX_SYSROOT|CMAKE_GENERATOR:" /tmp/mlxsa/CMakeCache.txt | sort
MLXA=/tmp/mlxsa/libmlx.a
METALLIB=$(find /tmp/mlxsa -name mlx.metallib | head -1)
clang++ -std=c++17 -O2 repro_gather_mm.cpp \
-I backends/mlx/third-party/mlx \
-I /tmp/mlxsa \
"$MLXA" \
-framework Metal -framework Foundation -framework QuartzCore \
-o repro_standalone
rm -f ./mlx.metallib && cp "$METALLIB" .
./repro_standalone
# ------------------------------------------------------------------
# SONDE 3 — signature de contrôle via op_test_runner (le binaire de CE
# run exhibe bien le bug pendant que les sondes tournent).
# ------------------------------------------------------------------
- name: SONDE 3 — gather_mm/gather_qmm via op_test_runner
if: steps.build.outcome == 'success'
continue-on-error: true
run: |
set -eux
python -m executorch.backends.mlx.test.run_all_tests \
gather_mm gather_qmm -v --clean-after
- name: Diagnostics finaux
if: always()
run: df -h /