fix(install): address Codex round-2 review (WSL1 distros, build-failure restore, libcurl, shim quoting, opt-out forwarding)
- install.ps1: detect a PRE-EXISTING WSL1 distro up-front (kernel string +
libcuda probe inside the distro; encoding-proof vs UTF-16 `wsl -l -v`) and
convert it with `wsl --set-version 2`, failing early with instructions if
conversion does not take -- instead of completing a full install that only
fails at the final torch.cuda check (no GPU passthrough under WSL1).
- install.ps1: quote the distro name in the generated unsloth.cmd shim and in
the copy-pasteable hint commands so UNSLOTH_WSL_DISTRO values with spaces
("Ubuntu Preview") keep working.
- install.ps1: forward UNSLOTH_NO_LLAMA_CUDA=1 into the WSL install env; the
inner setup.sh otherwise defers its llama.cpp build to a background builder
this script then never dispatches (the same opt-out skips it), leaving no
llama-server and a misleading "building in background" footer. Also add
libcurl4-openssl-dev to the WSL bootstrap apt line.
- provision_llama_cuda.sh: install libcurl4-openssl-dev with the base tools --
_cmake_configure forces -DLLAMA_CURL=ON and on the deferred WSL path this
script is the only build path (setup.sh's GGUF dep install was skipped), so
configure failed on fresh hosts without the headers.
- provision_llama_cuda.sh: keep the pre-existing llama.cpp backup until the
fresh build is CONFIRMED (was: dropped right after a successful clone), and
restore it on configure/build failure or when no server binary was produced
-- a failed CUDA build no longer destroys a previously working (CPU) server.
- setup.sh: when provisioning fails and NO llama-server is present, set
_LLAMA_CPP_DEGRADED=true so the arm64 CPU-prebuilt last resort and the
installer failure exit fire instead of reporting a working install.
Round-2 comments verified already fixed in ad77ae6 (anchored to its parent
d161ff5): the torch probe already passes --reinstall; the WSL uninstall is
already scoped to /root only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
53de77b007
commit
8e51d18a6c
3 changed files with 68 additions and 19 deletions
43
install.ps1
43
install.ps1
|
|
@ -1563,6 +1563,29 @@ shell.Run cmd, 0, False
|
|||
if (-not $haveDistro) {
|
||||
substep "installing WSL distro '$distro' (first time only)..." "Cyan"
|
||||
try { & wsl.exe --install -d $distro --no-launch } catch {}
|
||||
} else {
|
||||
# A PRE-EXISTING distro may be WSL1, which has no GPU passthrough: the existence
|
||||
# probe passes but the full install would only fail at the final torch.cuda
|
||||
# check. Detect WSL1 up-front from inside the distro (kernel string + libcuda --
|
||||
# encoding-proof, unlike parsing UTF-16 `wsl -l -v` output) and convert in place;
|
||||
# `wsl --set-version` preserves the distro's files. Freshly installed distros
|
||||
# are WSL2 (default version 2), so only the pre-existing case needs this.
|
||||
$_wsl2Probe = 'grep -qiE ''microsoft-standard|WSL2'' /proc/version 2>/dev/null || test -e /usr/lib/wsl/lib/libcuda.so'
|
||||
$_isWsl2 = $false
|
||||
$global:LASTEXITCODE = -1
|
||||
try { & wsl.exe -d $distro -u root -- bash -c $_wsl2Probe *> $null; $_isWsl2 = ($LASTEXITCODE -eq 0) } catch {}
|
||||
if (-not $_isWsl2) {
|
||||
substep "distro '$distro' looks like WSL1 (no GPU passthrough) -- converting to WSL2 (one-time; can take a few minutes)..." "Yellow"
|
||||
$global:LASTEXITCODE = -1
|
||||
try { & wsl.exe --set-version $distro 2 } catch {}
|
||||
$global:LASTEXITCODE = -1
|
||||
try { & wsl.exe -d $distro -u root -- bash -c $_wsl2Probe *> $null; $_isWsl2 = ($LASTEXITCODE -eq 0) } catch {}
|
||||
if (-not $_isWsl2) {
|
||||
Restore-StudioVenvRollback
|
||||
return (Exit-InstallFailure "WSL distro '$distro' is WSL1 and automatic conversion failed; NVIDIA GPU passthrough needs WSL2. Convert it, then re-run the installer: wsl --set-version `"$distro`" 2" 1)
|
||||
}
|
||||
substep "'$distro' converted to WSL2." "Green"
|
||||
}
|
||||
}
|
||||
substep "installing Unsloth Studio inside WSL '$distro' with full GPU (this downloads PyTorch)..." "Cyan"
|
||||
# For a non-main ref, fetch + export THAT ref so the WSL venv gets the branch's
|
||||
|
|
@ -1575,10 +1598,16 @@ shell.Run cmd, 0, False
|
|||
# itself instead of leaving them with no GGUF server.)
|
||||
# apt stderr is kept visible (only stdout -> /dev/null) so network/DNS/repo failures inside
|
||||
# WSL are diagnosable rather than silently swallowed.
|
||||
# Forward the CUDA llama.cpp opt-out into WSL: without it the inner setup.sh would
|
||||
# defer its build to a background builder this script then never starts (the same
|
||||
# opt-out skips the dispatch below), leaving no llama-server and a misleading
|
||||
# "building in background" footer. Forwarded, setup.sh keeps its own build instead.
|
||||
$_fwdEnv = ''
|
||||
if ($env:UNSLOTH_NO_LLAMA_CUDA -eq '1') { $_fwdEnv = 'export UNSLOTH_NO_LLAMA_CUDA=1; ' }
|
||||
if ($_instRef -eq 'main') {
|
||||
$wslInstall = 'export DEBIAN_FRONTEND=noninteractive UNSLOTH_WSL_LLAMA_DEFERRED=1; apt-get update -y >/dev/null; apt-get install -y build-essential cmake git curl pciutils >/dev/null; curl -fsSL https://unsloth.ai/install.sh | sh'
|
||||
$wslInstall = $_fwdEnv + 'export DEBIAN_FRONTEND=noninteractive UNSLOTH_WSL_LLAMA_DEFERRED=1; apt-get update -y >/dev/null; apt-get install -y build-essential cmake git curl pciutils libcurl4-openssl-dev >/dev/null; curl -fsSL https://unsloth.ai/install.sh | sh'
|
||||
} else {
|
||||
$wslInstall = 'export DEBIAN_FRONTEND=noninteractive UNSLOTH_WSL_LLAMA_DEFERRED=1; export UNSLOTH_INSTALL_REF=' + $_instRef + '; apt-get update -y >/dev/null; apt-get install -y build-essential cmake git curl pciutils >/dev/null; curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/' + $_instRef + '/install.sh | sh'
|
||||
$wslInstall = $_fwdEnv + 'export DEBIAN_FRONTEND=noninteractive UNSLOTH_WSL_LLAMA_DEFERRED=1; export UNSLOTH_INSTALL_REF=' + $_instRef + '; apt-get update -y >/dev/null; apt-get install -y build-essential cmake git curl pciutils libcurl4-openssl-dev >/dev/null; curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/' + $_instRef + '/install.sh | sh'
|
||||
}
|
||||
# install.sh may exit non-zero on the optional llama.cpp prebuilt step (no aarch64 prebuilt)
|
||||
# though torch + unsloth + Studio still install, so lower EAP so it doesn't abort under Stop.
|
||||
|
|
@ -1651,7 +1680,9 @@ shell.Run cmd, 0, False
|
|||
New-Item -ItemType Directory -Force -Path $shimDir *> $null
|
||||
$shimLines = @(
|
||||
'@echo off',
|
||||
"wsl.exe -d $distro -u root -- /root/.unsloth/studio/unsloth_studio/bin/unsloth %*"
|
||||
# Quote the distro: an UNSLOTH_WSL_DISTRO with spaces (e.g. "Ubuntu Preview")
|
||||
# would otherwise split after -d and break every `unsloth ...` invocation.
|
||||
"wsl.exe -d `"$distro`" -u root -- /root/.unsloth/studio/unsloth_studio/bin/unsloth %*"
|
||||
)
|
||||
Set-Content -LiteralPath (Join-Path $shimDir "unsloth.cmd") -Value $shimLines -Encoding ASCII
|
||||
# A fresh Windows profile may have no HKCU 'Path' value at all -> $userPath is null
|
||||
|
|
@ -1668,7 +1699,7 @@ shell.Run cmd, 0, False
|
|||
substep " unsloth studio # runs in WSL; opens http://localhost:8888" "Cyan"
|
||||
substep " unsloth studio run # also forwarded into WSL" "Cyan"
|
||||
} catch {
|
||||
substep "(shim creation failed; launch manually): wsl -d $distro -u root -- bash -lic 'unsloth studio -p 8888'" "Yellow"
|
||||
substep "(shim creation failed; launch manually): wsl -d `"$distro`" -u root -- bash -lic 'unsloth studio -p 8888'" "Yellow"
|
||||
}
|
||||
# Desktop + Start Menu shortcuts: launch the WSL Studio and open the browser when ready.
|
||||
try {
|
||||
|
|
@ -1768,13 +1799,13 @@ shell.Run cmd, 0, False
|
|||
Start-Process -WindowStyle Hidden -FilePath 'wsl.exe' -ArgumentList @('-d', $distro, '--cd', '/root', '-u', 'root', '--', 'bash', '/root/.unsloth/run_llama_build.sh') | Out-Null
|
||||
step "llama.cpp" "building CUDA llama.cpp for GGUF inference in the background (a few min); log: ~/.unsloth/llama_cuda_build.log" "Green"
|
||||
} else {
|
||||
substep "(GGUF inference needs a CUDA llama.cpp build; build later: wsl -d $distro -u root -- bash ~/.unsloth/provision_llama_cuda.sh)" "Yellow"
|
||||
substep "(GGUF inference needs a CUDA llama.cpp build; build later: wsl -d `"$distro`" -u root -- bash ~/.unsloth/provision_llama_cuda.sh)" "Yellow"
|
||||
}
|
||||
} catch {} finally { $ErrorActionPreference = $prevEapL }
|
||||
}
|
||||
} else {
|
||||
step "wsl" "WSL Studio install did not finish cleanly (torch.cuda not detected; inner exit $wslRc) -- see log above." "Yellow"
|
||||
substep "retry, or launch manually: wsl -d $distro -u root -- bash -lic 'unsloth studio -p 8888'" "Cyan"
|
||||
substep "retry, or launch manually: wsl -d `"$distro`" -u root -- bash -lic 'unsloth studio -p 8888'" "Cyan"
|
||||
}
|
||||
if ($torchOk) {
|
||||
# WSL GPU install succeeded. On this path the Windows venv is vestigial (everything
|
||||
|
|
|
|||
|
|
@ -49,8 +49,11 @@ HAVE_APT=0; command -v apt-get >/dev/null 2>&1 && HAVE_APT=1
|
|||
# without the basic build tools needed to clone/configure llama.cpp.
|
||||
if [ "$HAVE_APT" -eq 1 ]; then
|
||||
$SUDO apt-get update -y >/dev/null 2>&1 || true
|
||||
# libcurl4-openssl-dev: _cmake_configure forces -DLLAMA_CURL=ON, and on the WSL
|
||||
# deferred path this script is the only build path -- setup.sh's GGUF dep install
|
||||
# (which covers libcurl) was skipped, so configure would fail without the headers.
|
||||
$SUDO apt-get install -y --no-install-recommends \
|
||||
build-essential cmake git curl ca-certificates >/dev/null 2>&1 || true
|
||||
build-essential cmake git curl ca-certificates libcurl4-openssl-dev >/dev/null 2>&1 || true
|
||||
$SUDO apt-get install -y --no-install-recommends gcc-14 g++-14 >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
|
|
@ -112,11 +115,17 @@ if [ -n "$CC_CAP" ]; then CUDA_ARCH="$CC_CAP"; else CUDA_ARCH="native"; fi
|
|||
# the user's request instead of always tracking ggml-org main.
|
||||
mkdir -p "$(dirname "$LLAMA_DIR")"
|
||||
_LLAMA_REF="${UNSLOTH_LLAMA_TAG:-}"
|
||||
# Preserve any existing (e.g. CPU-only) llama.cpp so a failed clone OR a failed CUDA
|
||||
# build doesn't leave the user with NO server: the backup is restored on any failure
|
||||
# exit and only dropped once a server from the fresh build is confirmed.
|
||||
_LLAMA_BAK=""
|
||||
_restore_prev() {
|
||||
if [ -n "$_LLAMA_BAK" ] && [ -e "$_LLAMA_BAK" ]; then
|
||||
rm -rf "$LLAMA_DIR" 2>/dev/null
|
||||
mv "$_LLAMA_BAK" "$LLAMA_DIR" 2>/dev/null && log "restored previous llama.cpp install"
|
||||
fi
|
||||
}
|
||||
if [ ! -d "$LLAMA_DIR/.git" ]; then
|
||||
# Preserve any existing (e.g. CPU-only) llama.cpp so a FAILED clone doesn't leave the user
|
||||
# with NO server -- restore it on clone failure. A successful clone makes it obsolete (the
|
||||
# fresh CUDA build replaces it), so the backup is dropped then.
|
||||
_LLAMA_BAK=""
|
||||
if [ -e "$LLAMA_DIR" ]; then
|
||||
_LLAMA_BAK="${LLAMA_DIR}.prev.$$"
|
||||
rm -rf "$_LLAMA_BAK" 2>/dev/null
|
||||
|
|
@ -131,12 +140,11 @@ if [ ! -d "$LLAMA_DIR/.git" ]; then
|
|||
fi
|
||||
if [ "$_clone_ok" -ne 1 ]; then
|
||||
log "git clone failed"
|
||||
[ -n "$_LLAMA_BAK" ] && mv "$_LLAMA_BAK" "$LLAMA_DIR" 2>/dev/null # restore previous server
|
||||
_restore_prev
|
||||
exit 0
|
||||
fi
|
||||
[ -n "$_LLAMA_BAK" ] && rm -rf "$_LLAMA_BAK" 2>/dev/null
|
||||
fi
|
||||
cd "$LLAMA_DIR" || exit 0
|
||||
cd "$LLAMA_DIR" || { _restore_prev; exit 0; }
|
||||
|
||||
log "building CUDA llama.cpp (arch=$CUDA_ARCH, host=$HCXX) - this takes a few minutes..."
|
||||
_cmake_configure() {
|
||||
|
|
@ -153,7 +161,7 @@ _cmake_configure() {
|
|||
if ! _cmake_configure; then
|
||||
log "stale/incompatible CMake cache detected; wiping build dir for a clean CUDA configure"
|
||||
rm -rf build
|
||||
_cmake_configure || { log "cmake configure failed"; exit 0; }
|
||||
_cmake_configure || { log "cmake configure failed"; cd /; _restore_prev; exit 0; }
|
||||
fi
|
||||
# Build the full target set unsloth-zoo's GGUF exporter also needs (llama-mtmd-cli,
|
||||
# llama-gguf-split) so one build serves both Studio inference and save_pretrained_gguf.
|
||||
|
|
@ -192,13 +200,19 @@ if ! _cmake_build; then
|
|||
# Wipe build/ and rebuild clean once before giving up.
|
||||
log "build failed (likely interrupted/partial); wiping build dir and rebuilding clean"
|
||||
rm -rf build
|
||||
_cmake_configure || { log "cmake configure failed"; exit 0; }
|
||||
_cmake_build || { log "cmake build failed"; exit 0; }
|
||||
_cmake_configure || { log "cmake configure failed"; cd /; _restore_prev; exit 0; }
|
||||
_cmake_build || { log "cmake build failed"; cd /; _restore_prev; exit 0; }
|
||||
fi
|
||||
|
||||
if is_cuda_server "$SERVER"; then
|
||||
log "CUDA llama-server ready: $SERVER"
|
||||
else
|
||||
[ -n "$_LLAMA_BAK" ] && rm -rf "$_LLAMA_BAK" 2>/dev/null
|
||||
elif [ -x "$SERVER" ]; then
|
||||
# A server exists but isn't CUDA-confirmed; still better than the old backup.
|
||||
log "build finished but CUDA llama-server could not be confirmed"
|
||||
[ -n "$_LLAMA_BAK" ] && rm -rf "$_LLAMA_BAK" 2>/dev/null
|
||||
else
|
||||
log "build finished but no llama-server was produced"
|
||||
cd /; _restore_prev
|
||||
fi
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -1488,7 +1488,11 @@ if [ "$_HOST_SYSTEM" = "Linux" ] \
|
|||
elif [ -f "$LLAMA_SERVER_BIN" ]; then
|
||||
substep "CUDA build unavailable; keeping existing (CPU) llama-server" "$C_WARN"
|
||||
else
|
||||
substep "CUDA build unavailable; see ~/.unsloth/llama.cpp build output" "$C_WARN"
|
||||
substep "CUDA build unavailable and no llama-server present; see $LLAMA_CPP_DIR build output" "$C_WARN"
|
||||
# No server at all (e.g. the provisioner replaced a previous build and then
|
||||
# failed): mark degraded so the arm64 CPU-prebuilt last resort below and the
|
||||
# installer failure exit fire instead of reporting a working install.
|
||||
_LLAMA_CPP_DEGRADED=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue