studio/setup.sh: cope with fresh CUDA toolkits like 13.3 (#5826)

* Studio setup.sh: cope with fresh CUDA toolkits like 13.3

CUDA 13.3 shipped today. Three loose ends in studio/setup.sh surfaced
during the llama.cpp build path:

1. setup.ps1 already aborts cleanly when the CUDA toolkit is below
   llama.cpp's minimum (12.4) via #4517, but setup.sh still hit the
   generic cmake failure described in #4437. Added a min-version check
   that downgrades to a CPU build for nvcc < 12.4 with a clear message
   pointing to the toolkit archive.
2. The first day a new CUDA toolkit ships, its host-compiler whitelist
   lags whatever gcc/clang the distro is on, so nvcc rejects the host
   compiler with a wall of "#error -- unsupported GNU version" before
   any real compile runs. NVCC_PREPEND_FLAGS now carries
   -allow-unsupported-compiler so the build moves on instead.
3. The Linux CUDA/ROCm configure failure path had no symmetry with the
   macOS Metal fallback: a single nvcc failure left BUILD_OK=false and
   no llama.cpp at all. Generalised the existing Metal -> CPU fallback
   to cover any GPU_BACKEND, so a CUDA configure or build failure now
   transparently retries with the CPU args and the user still ends up
   with a working llama-server.

Pulled the version probe out into _nvcc_meets_llama_minimum so it can
be unit-tested. Added tests/sh/test_nvcc_meets_llama_minimum.sh and two
extra cases in tests/sh/test_get_torch_index_url.sh covering the legacy
"CUDA Version: 13.3" header (driver-reported) and the future 13.7
case. Wired the new test into tests/run_all.sh and the studio-backend
CI workflow.

* tests: relax pr4562 regression to allow generic GPU fallback label

* studio tests: assert setup.sh exports NVCC_PREPEND_FLAGS=-allow-unsupported-compiler

The -allow-unsupported-compiler flag is the core of the fresh-CUDA-toolkit fix
(it lets nvcc accept a host gcc/clang newer than its release-time whitelist, so
CUDA 13.3 day-one builds do not abort on '#error -- unsupported GNU version'),
but it had no automated coverage. Add a source-pattern test asserting the flag
is present, delivered via NVCC_PREPEND_FLAGS so it also covers cmake's CUDA
compiler-id probe, and kept out of CMAKE_ARGS for bash word-splitting safety.

* studio/setup.ps1: allow unsupported host compiler for CUDA build (Windows parity)

Mirror the Linux setup.sh headline fix from this PR on Windows. A freshly
released CUDA toolkit ships with a host-compiler whitelist that lags the
installed toolchain, so nvcc can reject the host with
"#error -- unsupported Microsoft Visual Studio version!" before any real
compile runs (the MSVC analogue of the gcc wall the Linux side hit on
CUDA 13.3). Set NVCC_PREPEND_FLAGS=-allow-unsupported-compiler in the CUDA
build branch so both cmake's configure-time CUDA compiler-id probe and the
cmake --build step proceed. The flag disables the host version check only and
is a no-op when the compiler is already supported.

Set via the process environment (not the $CmakeArgs array), after the
Refresh-Environment calls that re-sanitize CUDA env vars, and appended
idempotently to any value the user already set.

Validated with PowerShell 7.6.2: full setup.ps1 AST parse is clean and the
snippet is idempotent (empty -> set, existing -> append once, no duplicate).
Needs real Windows + CUDA CI to exercise the actual nvcc/MSVC build.

Adds test_setup_ps1_exports_allow_unsupported_compiler asserting the flag is
present, env-delivered, kept out of $CmakeArgs, and scoped to the CUDA-on branch.

* studio: tighten code comments added in this PR

Shorten the verbose multi-line comments and test docstrings introduced by
this PR (setup.sh, setup.ps1, and the shell/python tests) to be succinct
while preserving the rationale. No code or test-assertion changes.
This commit is contained in:
Daniel Han 2026-05-29 05:09:20 -07:00 committed by GitHub
commit a3a0cb1606
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 293 additions and 40 deletions

View file

@ -222,6 +222,7 @@ jobs:
for s in \
tests/sh/test_get_torch_index_url.sh \
tests/sh/test_mac_intel_compat.sh \
tests/sh/test_nvcc_meets_llama_minimum.sh \
tests/sh/test_tauri_install_exit_order.sh \
tests/sh/test_torch_constraint.sh; do
echo "::group::$s"

View file

@ -2589,6 +2589,17 @@ if (-not $NeedLlamaSourceBuild) {
# CUDA flags -- only if GPU available, otherwise explicitly disable
if ($HasNvidiaSmi -and $NvccPath) {
$CmakeArgs += '-DGGML_CUDA=ON'
# Accept a host MSVC newer than nvcc's whitelist; a fresh toolkit
# (e.g. CUDA 13.3) otherwise aborts with "#error -- unsupported
# Microsoft Visual Studio version!". Mirrors the Linux fix. Via env
# (covers the configure probe + build), after Refresh-Environment, idempotent.
$nvccAllowFlag = '-allow-unsupported-compiler'
if ([string]::IsNullOrEmpty($env:NVCC_PREPEND_FLAGS)) {
$env:NVCC_PREPEND_FLAGS = $nvccAllowFlag
} elseif ($env:NVCC_PREPEND_FLAGS -notlike "*$nvccAllowFlag*") {
$env:NVCC_PREPEND_FLAGS = "$($env:NVCC_PREPEND_FLAGS) $nvccAllowFlag"
}
substep "NVCC_PREPEND_FLAGS = $env:NVCC_PREPEND_FLAGS"
$CmakeArgs += "-DCUDAToolkit_ROOT=$CudaToolkitRoot"
$CmakeArgs += "-DCUDA_TOOLKIT_ROOT_DIR=$CudaToolkitRoot"
$CmakeArgs += "-DCMAKE_CUDA_COMPILER=$NvccPath"

View file

@ -130,6 +130,30 @@ run_quiet_no_exit() {
_run_quiet return "$@"
}
_nvcc_meets_llama_minimum() {
# Echo "ok|too_old|unknown" then the parsed "X.Y" version, one per line.
# llama.cpp needs CUDA toolkit >= 12.4 (#4437; setup.ps1 aborts via #4517).
_nvcc_bin=$1
[ -n "$_nvcc_bin" ] || { echo "unknown"; echo ""; return 0; }
_raw=$("$_nvcc_bin" --version 2>/dev/null \
| sed -n 's/.*release \([0-9][0-9]*\.[0-9][0-9]*\).*/\1/p' \
| head -1)
if [ -z "$_raw" ]; then
echo "unknown"; echo ""; return 0
fi
_maj=${_raw%%.*}
_min_raw=${_raw#*.}
_min=${_min_raw%%.*}
if [ "$_maj" -lt 12 ] 2>/dev/null; then
echo "too_old"
elif [ "$_maj" -eq 12 ] && [ "$_min" -lt 4 ] 2>/dev/null; then
echo "too_old"
else
echo "ok"
fi
echo "$_raw"
}
print_llama_error_log() {
local log_file=$1
[ -s "$log_file" ] || return 0
@ -1005,32 +1029,52 @@ else
CPU_FALLBACK_CMAKE_ARGS="$CPU_FALLBACK_CMAKE_ARGS -DGGML_METAL=OFF"
_TRY_METAL_CPU_FALLBACK=true
elif [ -n "$NVCC_PATH" ]; then
CMAKE_ARGS="$CMAKE_ARGS -DGGML_CUDA=ON"
# Returns "ok|too_old|unknown\nX.Y" on stdout.
_NVCC_CHECK="$(_nvcc_meets_llama_minimum "$NVCC_PATH")"
_NVCC_STATUS="$(printf '%s\n' "$_NVCC_CHECK" | sed -n '1p')"
_NVCC_VER="$(printf '%s\n' "$_NVCC_CHECK" | sed -n '2p')"
CUDA_ARCHS=""
if command -v nvidia-smi &>/dev/null; then
_raw_caps=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null || true)
while IFS= read -r _cap; do
_cap=$(echo "$_cap" | tr -d '[:space:]')
if [[ "$_cap" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
_arch="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
# Append if not already present
case ";$CUDA_ARCHS;" in
*";$_arch;"*) ;;
*) CUDA_ARCHS="${CUDA_ARCHS:+$CUDA_ARCHS;}$_arch" ;;
esac
fi
done <<< "$_raw_caps"
fi
if [ -n "$CUDA_ARCHS" ]; then
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHS}"
_BUILD_DESC="building (CUDA, sm_${CUDA_ARCHS//;/+sm_})"
if [ "$_NVCC_STATUS" = "too_old" ]; then
substep "CUDA toolkit $_NVCC_VER is below llama.cpp minimum (12.4)." "$C_ERR"
substep "install a newer CUDA toolkit: https://developer.nvidia.com/cuda-toolkit-archive" "$C_WARN"
substep "falling back to CPU llama.cpp build for this run." "$C_WARN"
NVCC_PATH=""
GPU_BACKEND=""
_BUILD_DESC="building (CPU, CUDA toolkit < 12.4)"
else
_BUILD_DESC="building (CUDA)"
fi
CMAKE_ARGS="$CMAKE_ARGS -DGGML_CUDA=ON"
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CUDA_FLAGS=--threads=0"
CUDA_ARCHS=""
if command -v nvidia-smi &>/dev/null; then
_raw_caps=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null || true)
while IFS= read -r _cap; do
_cap=$(echo "$_cap" | tr -d '[:space:]')
if [[ "$_cap" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
_arch="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
# Append if not already present
case ";$CUDA_ARCHS;" in
*";$_arch;"*) ;;
*) CUDA_ARCHS="${CUDA_ARCHS:+$CUDA_ARCHS;}$_arch" ;;
esac
fi
done <<< "$_raw_caps"
fi
if [ -n "$CUDA_ARCHS" ]; then
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHS}"
_BUILD_DESC="building (CUDA, sm_${CUDA_ARCHS//;/+sm_})"
else
_BUILD_DESC="building (CUDA)"
fi
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CUDA_FLAGS=--threads=0"
# Accept a host gcc/clang newer than nvcc's whitelist; a fresh
# toolkit (e.g. CUDA 13.3) otherwise aborts with "#error --
# unsupported GNU version". Via env, not CMAKE_ARGS, to avoid
# word-splitting.
export NVCC_PREPEND_FLAGS="${NVCC_PREPEND_FLAGS:+$NVCC_PREPEND_FLAGS }-allow-unsupported-compiler"
fi
elif [ "$GPU_BACKEND" = "rocm" ]; then
# Resolve hipcc symlinks to find the real ROCm root
_HIPCC_REAL="$(readlink -f "$ROCM_HIPCC" 2>/dev/null || printf '%s' "$ROCM_HIPCC")"
@ -1100,14 +1144,29 @@ else
CMAKE_GENERATOR_ARGS="-G Ninja"
fi
if ! run_quiet_no_exit "cmake llama.cpp" cmake $CMAKE_GENERATOR_ARGS -S "$_BUILD_TMP" -B "$_BUILD_TMP/build" $CMAKE_ARGS; then
# GPU label for the CPU-fallback message: Metal, else GPU_BACKEND
# (cuda/rocm). Empty on a bare CPU build (nothing to fall back from).
_gpu_fallback_label() {
if [ "$_TRY_METAL_CPU_FALLBACK" = true ]; then
echo "Metal"
elif [ -n "$GPU_BACKEND" ]; then
printf '%s' "$GPU_BACKEND" | tr '[:lower:]' '[:upper:]'
fi
}
if ! run_quiet_no_exit "cmake llama.cpp" cmake $CMAKE_GENERATOR_ARGS -S "$_BUILD_TMP" -B "$_BUILD_TMP/build" $CMAKE_ARGS; then
_FB_LABEL="$(_gpu_fallback_label)"
if [ -n "$_FB_LABEL" ]; then
_TRY_METAL_CPU_FALLBACK=false
substep "Metal configure failed; retrying CPU build..." "$C_WARN"
substep "$_FB_LABEL configure failed; retrying CPU build..." "$C_WARN"
rm -rf "$_BUILD_TMP/build"
run_quiet_no_exit "cmake llama.cpp (cpu fallback)" cmake $CMAKE_GENERATOR_ARGS -S "$_BUILD_TMP" -B "$_BUILD_TMP/build" $CPU_FALLBACK_CMAKE_ARGS || BUILD_OK=false
if [ "$BUILD_OK" = true ]; then
_BUILD_DESC="building (CPU fallback)"
if run_quiet_no_exit "cmake llama.cpp (cpu fallback)" cmake $CMAKE_GENERATOR_ARGS -S "$_BUILD_TMP" -B "$_BUILD_TMP/build" $CPU_FALLBACK_CMAKE_ARGS; then
_BUILD_DESC="building (CPU fallback after $_FB_LABEL configure failed)"
# Now configured for CPU; clear GPU_BACKEND so a later
# build-step failure won't re-enter fallback on this config.
GPU_BACKEND=""
else
BUILD_OK=false
fi
else
BUILD_OK=false
@ -1117,12 +1176,14 @@ else
if [ "$BUILD_OK" = true ]; then
if ! run_quiet_no_exit "build llama-server" cmake --build "$_BUILD_TMP/build" --config Release --target llama-server -j"$NCPU"; then
if [ "$_TRY_METAL_CPU_FALLBACK" = true ]; then
_FB_LABEL="$(_gpu_fallback_label)"
if [ -n "$_FB_LABEL" ]; then
_TRY_METAL_CPU_FALLBACK=false
substep "Metal build failed; retrying CPU build..." "$C_WARN"
substep "$_FB_LABEL build failed; retrying CPU build..." "$C_WARN"
rm -rf "$_BUILD_TMP/build"
if run_quiet_no_exit "cmake llama.cpp (cpu fallback)" cmake $CMAKE_GENERATOR_ARGS -S "$_BUILD_TMP" -B "$_BUILD_TMP/build" $CPU_FALLBACK_CMAKE_ARGS; then
_BUILD_DESC="building (CPU fallback)"
_BUILD_DESC="building (CPU fallback after $_FB_LABEL build failed)"
GPU_BACKEND=""
run_quiet_no_exit "build llama-server (cpu fallback)" cmake --build "$_BUILD_TMP/build" --config Release --target llama-server -j"$NCPU" || BUILD_OK=false
else
BUILD_OK=false

View file

@ -8,6 +8,7 @@ echo "=== Bash tests ==="
sh "$TESTS_DIR/sh/test_get_torch_index_url.sh"
sh "$TESTS_DIR/sh/test_mac_intel_compat.sh"
sh "$TESTS_DIR/sh/test_torch_constraint.sh"
sh "$TESTS_DIR/sh/test_nvcc_meets_llama_minimum.sh"
echo ""
echo "=== Python tests ==="

View file

@ -320,6 +320,18 @@ _result=$(run_func "$_dir")
assert_eq "CUDA UMD Version 11.8 -> cu118" "https://download.pytorch.org/whl/cu118" "$_result"
rm -rf "$_dir"
# 32) Driver-reported "CUDA Version: 13.3" (legacy header) -> cu130.
_dir=$(make_mock_smi "13.3")
_result=$(run_func "$_dir")
assert_eq "CUDA Version 13.3 -> cu130" "https://download.pytorch.org/whl/cu130" "$_result"
rm -rf "$_dir"
# 33) "CUDA Version: 13.7" -> cu130 (until a cu137 wheel index exists).
_dir=$(make_mock_smi "13.7")
_result=$(run_func "$_dir")
assert_eq "CUDA Version 13.7 -> cu130" "https://download.pytorch.org/whl/cu130" "$_result"
rm -rf "$_dir"
rm -f "$_FUNC_FILE"
rm -rf "$_FAKE_SMI_DIR"
rm -rf "$_TOOLS_DIR"

View file

@ -0,0 +1,121 @@
#!/bin/bash
# Unit tests for _nvcc_meets_llama_minimum() from studio/setup.sh.
# llama.cpp needs CUDA toolkit >= 12.4 (#4437); setup.ps1 aborts via #4517,
# the Linux side was silent until this fix.
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SETUP_SH="$SCRIPT_DIR/../../studio/setup.sh"
PASS=0
FAIL=0
# Extract just the helper function. The sed range is the same pattern the
# install.sh tests use.
_FUNC_FILE=$(mktemp)
sed -n '/^_nvcc_meets_llama_minimum()/,/^}/p' "$SETUP_SH" > "$_FUNC_FILE"
assert_eq() {
_label="$1"; _expected="$2"; _actual="$3"
if [ "$_actual" = "$_expected" ]; then
echo " PASS: $_label"
PASS=$((PASS + 1))
else
echo " FAIL: $_label (expected '$_expected', got '$_actual')"
FAIL=$((FAIL + 1))
fi
}
# Fake nvcc printing "release X.Y" in the canonical nvcc -V layout (the helper
# greps for "release X.Y", stable across CUDA 9.x-13.x).
make_mock_nvcc() {
_ver=$1
_dir=$(mktemp -d)
cat > "$_dir/nvcc" <<MOCK
#!/bin/sh
cat <<NV
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2026 NVIDIA Corporation
Cuda compilation tools, release $_ver, V${_ver}.0
NV
MOCK
chmod +x "$_dir/nvcc"
echo "$_dir/nvcc"
}
run_check() {
_nvcc=$1
bash -c ". '$_FUNC_FILE'; _nvcc_meets_llama_minimum '$_nvcc'"
}
echo "=== test_nvcc_meets_llama_minimum ==="
# 1) CUDA 12.4 is the minimum supported -> ok
_bin=$(make_mock_nvcc "12.4")
_out=$(run_check "$_bin")
assert_eq "12.4 status" "ok" "$(echo "$_out" | sed -n '1p')"
assert_eq "12.4 version" "12.4" "$(echo "$_out" | sed -n '2p')"
rm -rf "$(dirname "$_bin")"
# 2) CUDA 12.3 is the highest version that should be rejected.
_bin=$(make_mock_nvcc "12.3")
_out=$(run_check "$_bin")
assert_eq "12.3 status" "too_old" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 3) CUDA 12.1 (matches the original bug report in #4437).
_bin=$(make_mock_nvcc "12.1")
_out=$(run_check "$_bin")
assert_eq "12.1 status" "too_old" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 4) CUDA 11.8 -> too_old (anything < 12.0 is rejected).
_bin=$(make_mock_nvcc "11.8")
_out=$(run_check "$_bin")
assert_eq "11.8 status" "too_old" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 5) CUDA 12.8 -> ok (mid-range supported).
_bin=$(make_mock_nvcc "12.8")
_out=$(run_check "$_bin")
assert_eq "12.8 status" "ok" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 6) CUDA 13.0 -> ok.
_bin=$(make_mock_nvcc "13.0")
_out=$(run_check "$_bin")
assert_eq "13.0 status" "ok" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 7) CUDA 13.3 -> ok (the freshly shipped toolkit this fix targets).
_bin=$(make_mock_nvcc "13.3")
_out=$(run_check "$_bin")
assert_eq "13.3 status" "ok" "$(echo "$_out" | sed -n '1p')"
assert_eq "13.3 version" "13.3" "$(echo "$_out" | sed -n '2p')"
rm -rf "$(dirname "$_bin")"
# 8) Future CUDA 14.0 -> ok (no upper bound).
_bin=$(make_mock_nvcc "14.0")
_out=$(run_check "$_bin")
assert_eq "14.0 status" "ok" "$(echo "$_out" | sed -n '1p')"
rm -rf "$(dirname "$_bin")"
# 9) Empty argument -> unknown (defensive; never block the build on detection).
_out=$(run_check "")
assert_eq "empty path status" "unknown" "$(echo "$_out" | sed -n '1p')"
# 10) Mock nvcc that prints garbage -> unknown.
_dir=$(mktemp -d)
cat > "$_dir/nvcc" <<'MOCK'
#!/bin/sh
echo "totally not nvcc output"
MOCK
chmod +x "$_dir/nvcc"
_out=$(run_check "$_dir/nvcc")
assert_eq "garbage output status" "unknown" "$(echo "$_out" | sed -n '1p')"
rm -rf "$_dir"
rm -f "$_FUNC_FILE"
echo ""
echo "Results: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] || exit 1

View file

@ -727,16 +727,13 @@ class TestSourceCodePatterns:
assert "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON" in content
def test_setup_sh_macos_metal_configure_has_cpu_fallback(self):
"""If Metal configure or build fails, setup should retry with CPU fallback."""
"""If Metal/CUDA/ROCm configure or build fails, setup retries a CPU
build. PR #5826 generalised the Metal-only wording via $_FB_LABEL; this
check stays label-agnostic so new GPU backends don't require edits."""
content = SETUP_SH.read_text()
assert "_TRY_METAL_CPU_FALLBACK=true" in content
assert (
'substep "Metal configure failed; retrying CPU build..." "$C_WARN"'
in content
)
assert (
'substep "Metal build failed; retrying CPU build..." "$C_WARN"' in content
)
assert 'configure failed; retrying CPU build..." "$C_WARN"' in content
assert 'build failed; retrying CPU build..." "$C_WARN"' in content
assert 'run_quiet_no_exit "cmake llama.cpp (cpu fallback)"' in content
assert "-DGGML_METAL=OFF" in content
# _TRY_METAL_CPU_FALLBACK must be reset to false in both fallback branches
@ -745,6 +742,55 @@ class TestSourceCodePatterns:
"_TRY_METAL_CPU_FALLBACK=false should appear at least 3 times "
"(init + configure fallback + build fallback)"
)
# The fallback helper must exist and Metal must reach it via the
# _TRY_METAL_CPU_FALLBACK shortcut so the macOS path stays covered.
assert "_gpu_fallback_label()" in content
assert 'echo "Metal"' in content
def test_setup_sh_exports_allow_unsupported_compiler(self):
"""Headline fix for PR #5826: a fresh CUDA toolkit's host-compiler
whitelist lags the distro gcc/clang, so nvcc rejects the host with
"#error -- unsupported GNU version". setup.sh exports
NVCC_PREPEND_FLAGS=-allow-unsupported-compiler (via env, not CMAKE_ARGS,
for word-splitting safety) so the build and compiler-id probe proceed."""
content = SETUP_SH.read_text()
assert "-allow-unsupported-compiler" in content
# Delivered via NVCC_PREPEND_FLAGS (covers the configure-time compiler
# probe too), not embedded in the word-split CMAKE_ARGS string.
assert "export NVCC_PREPEND_FLAGS=" in content
cmake_args_lines = [
line for line in content.splitlines() if "CMAKE_ARGS=" in line
]
assert all(
"-allow-unsupported-compiler" not in line for line in cmake_args_lines
), "flag must stay out of CMAKE_ARGS (bash word-splitting safety)"
def test_setup_ps1_exports_allow_unsupported_compiler(self):
"""Windows parity for the PR #5826 fix: a fresh CUDA toolkit's whitelist
also lags MSVC, so nvcc can reject the host with "#error -- unsupported
Microsoft Visual Studio version!". setup.ps1 sets
NVCC_PREPEND_FLAGS=-allow-unsupported-compiler in the CUDA branch (via
env, out of $CmakeArgs) so the configure probe + build proceed."""
content = SETUP_PS1.read_text()
assert "-allow-unsupported-compiler" in content
# Delivered via the process environment, not the $CmakeArgs array, so it
# reaches both the configure-time compiler probe and `cmake --build`.
assert "$env:NVCC_PREPEND_FLAGS" in content
cmake_args_lines = [
line for line in content.splitlines() if "$CmakeArgs +=" in line
]
assert all(
"-allow-unsupported-compiler" not in line for line in cmake_args_lines
), "flag must not be pushed into the $CmakeArgs array"
# Must be scoped to the CUDA branch (guarded by the GPU/nvcc check),
# not set unconditionally for CPU-only builds.
flag_idx = content.index("-allow-unsupported-compiler")
cuda_guard_idx = content.index("if ($HasNvidiaSmi -and $NvccPath)")
cuda_disable_idx = content.index("'-DGGML_CUDA=OFF'")
assert cuda_guard_idx < flag_idx < cuda_disable_idx, (
"NVCC_PREPEND_FLAGS must be set inside the CUDA-on branch, "
"before the GGML_CUDA=OFF (CPU) branch"
)
def test_macos_arm64_cpu_fallback_args_exclude_rpath(self):
"""CPU fallback args must NOT contain Metal-only RPATH flags at runtime."""