Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 82 additions & 37 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,15 @@ _find_no_torch_runtime() {
fi
}

_overlay_local_repos() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you have this in your PR? seems like it leaked from another PR i already merged?

substep "overlaying local repo (editable)..."
run_install_cmd "overlay local repo" uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps
substep "overlaying unsloth-zoo from git main..."
run_install_cmd "overlay unsloth-zoo (git main)" uv pip install --python "$_VENV_PY" \
--no-deps --reinstall-package unsloth-zoo \
"unsloth-zoo @ git+https://github.com/unslothai/unsloth-zoo"
}

# ── AMD ROCm GPU detection helper ──
# Returns 0 (true) if an actual AMD GPU is present, 1 (false) otherwise.
# Checks rocminfo for gfx[1-9]* (excludes gfx000 CPU agent) and
Expand All @@ -1195,6 +1204,19 @@ _has_amd_rocm_gpu() {
return 1
}

# ── Intel XPU GPU detection helper ──
# Returns 0 (true) if a Linux x86_64 host exposes an Intel GPU via DRM sysfs.
_has_intel_xpu_gpu() {
_drm_root="${UNSLOTH_DRM_ROOT:-/sys/class/drm}"
for _vendor in "$_drm_root"/card*/device/vendor; do
[ -r "$_vendor" ] || continue
if grep -qi '0x8086' "$_vendor" 2>/dev/null; then
return 0
fi
done
return 1
}

# ── NVIDIA usable-GPU helper ──
# Returns 0 (true) only if nvidia-smi is present AND actually lists a GPU.
# Prevents AMD-only hosts with a stale nvidia-smi on PATH from being routed
Expand All @@ -1211,6 +1233,29 @@ _has_usable_nvidia_gpu() {
"$_nvsmi" -L 2>/dev/null | awk '/^GPU[[:space:]]+[0-9]+:/{found=1} END{exit !found}'
}

_install_intel_xpu_stack() {
_venv_py="$1"
_package_name="$2"
_local_install="$3"

# Required for the current Intel extras path because one preview wheel in the
# dependency set uses a filename uv rejects unless this check is disabled.
substep "installing Intel XPU PyTorch + Unsloth extras..."
if [ "$_local_install" = true ]; then
run_install_cmd "install Intel XPU stack (local)" \
env UV_SKIP_WHEEL_FILENAME_CHECK=1 \
uv pip install --python "$_venv_py" \
--upgrade-package "$_package_name" \
"${_package_name}[intel-gpu-torch290]>=2026.4.8"
else
run_install_cmd "install Intel XPU stack" \
env UV_SKIP_WHEEL_FILENAME_CHECK=1 \
uv pip install --python "$_venv_py" \
--upgrade-package "$_package_name" \
"${_package_name}[intel-gpu-torch290]>=2026.4.8"
fi
Comment thread
andomeder marked this conversation as resolved.
Comment thread
andomeder marked this conversation as resolved.
}

# ── Detect GPU and choose PyTorch index URL ──
# Mirrors Get-TorchIndexUrl in install.ps1.
# On CPU-only machines this returns the cpu index, avoiding the solver
Expand Down Expand Up @@ -1242,6 +1287,9 @@ get_torch_index_url() {
*) echo "$_base/cpu"; return ;;
esac
if ! _has_amd_rocm_gpu; then
if _has_intel_xpu_gpu; then
echo "$_base/xpu"; return
fi
echo "$_base/cpu"; return
fi
# AMD GPU confirmed -- detect ROCm version
Expand Down Expand Up @@ -1461,6 +1509,11 @@ case "$TORCH_INDEX_URL" in
echo ""
fi
;;
*/xpu)
echo ""
echo " Intel GPU detected -- installing Intel XPU-enabled PyTorch and Unsloth extras"
echo ""
;;
*/rocm*)
echo ""
if [ "$_amd_gpu_radeon" = true ]; then
Expand Down Expand Up @@ -1497,12 +1550,7 @@ if [ "$_MIGRATED" = true ]; then
"unsloth>=2026.4.8" unsloth-zoo
fi
if [ "$STUDIO_LOCAL_INSTALL" = true ]; then
substep "overlaying local repo (editable)..."
run_install_cmd "overlay local repo" uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps
substep "overlaying unsloth-zoo from git main..."
run_install_cmd "overlay unsloth-zoo (git main)" uv pip install --python "$_VENV_PY" \
--no-deps --reinstall-package unsloth-zoo \
"unsloth-zoo @ git+https://github.com/unslothai/unsloth-zoo"
_overlay_local_repos
fi
# AMD ROCm: install bitsandbytes even in migrated environments so
# existing ROCm installs gain the AMD bitsandbytes build without a
Expand All @@ -1524,9 +1572,13 @@ if [ "$_MIGRATED" = true ]; then
esac
fi
elif [ -n "$TORCH_INDEX_URL" ]; then
_skip_unsloth_stage2=false
# Fresh: Step 1 - install torch from explicit index (skip when --no-torch or Intel Mac)
if [ "$SKIP_TORCH" = true ]; then
substep "skipping PyTorch (--no-torch or Intel Mac x86_64)." "$C_WARN"
elif [ "${TORCH_INDEX_URL%/xpu}" != "$TORCH_INDEX_URL" ]; then
_install_intel_xpu_stack "$_VENV_PY" "$PACKAGE_NAME" "$STUDIO_LOCAL_INSTALL"
_skip_unsloth_stage2=true
elif [ "$_amd_gpu_radeon" = true ]; then
_radeon_url=$(get_radeon_wheel_url)
if [ -n "$_radeon_url" ]; then
Expand Down Expand Up @@ -1655,40 +1707,33 @@ elif [ -n "$TORCH_INDEX_URL" ]; then
esac
fi
# Fresh: Step 2 - install unsloth, preserving pre-installed torch
tauri_log "STEP" "Installing Unsloth"
substep "installing unsloth (this may take a few minutes)..."
if [ "$SKIP_TORCH" = true ]; then
# No-torch: install unsloth + unsloth-zoo with --no-deps, then
# runtime deps (typer, safetensors, transformers, etc.) with --no-deps.
run_install_cmd "install unsloth (no-torch)" uv pip install --python "$_VENV_PY" --no-deps \
--upgrade-package unsloth --upgrade-package unsloth-zoo \
"unsloth>=2026.4.8" unsloth-zoo
_NO_TORCH_RT="$(_find_no_torch_runtime)"
if [ -n "$_NO_TORCH_RT" ]; then
run_install_cmd "install no-torch runtime deps" uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT"
fi
if [ "$STUDIO_LOCAL_INSTALL" = true ]; then
substep "overlaying local repo (editable)..."
run_install_cmd "overlay local repo" uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps
substep "overlaying unsloth-zoo from git main..."
run_install_cmd "overlay unsloth-zoo (git main)" uv pip install --python "$_VENV_PY" \
--no-deps --reinstall-package unsloth-zoo \
"unsloth-zoo @ git+https://github.com/unslothai/unsloth-zoo"
if [ "$_skip_unsloth_stage2" = false ]; then
substep "installing unsloth (this may take a few minutes)..."
if [ "$SKIP_TORCH" = true ]; then
# No-torch: install unsloth + unsloth-zoo with --no-deps, then
# runtime deps (typer, safetensors, transformers, etc.) with --no-deps.
run_install_cmd "install unsloth (no torch)" uv pip install --python "$_VENV_PY" \
--no-deps --upgrade-package unsloth --upgrade-package unsloth-zoo \
"unsloth>=2026.4.8" unsloth-zoo
_NO_TORCH_RT="$(_find_no_torch_runtime)"
if [ -n "$_NO_TORCH_RT" ]; then
run_install_cmd "install no-torch runtime deps" uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT"
fi
if [ "$STUDIO_LOCAL_INSTALL" = true ]; then
_overlay_local_repos
fi
elif [ "$STUDIO_LOCAL_INSTALL" = true ]; then
run_install_cmd "install unsloth (local)" uv pip install --python "$_VENV_PY" \
--upgrade-package unsloth "unsloth>=2026.4.8" unsloth-zoo
_overlay_local_repos
else
run_install_cmd "install unsloth" uv pip install --python "$_VENV_PY" \
--upgrade-package unsloth "$PACKAGE_NAME"
fi
elif [ "$STUDIO_LOCAL_INSTALL" = true ]; then
run_install_cmd "install unsloth (local)" uv pip install --python "$_VENV_PY" \
--upgrade-package unsloth "unsloth>=2026.4.8" unsloth-zoo
substep "overlaying local repo (editable)..."
run_install_cmd "overlay local repo" uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps
substep "overlaying unsloth-zoo from git main..."
run_install_cmd "overlay unsloth-zoo (git main)" uv pip install --python "$_VENV_PY" \
--no-deps --reinstall-package unsloth-zoo \
"unsloth-zoo @ git+https://github.com/unslothai/unsloth-zoo"
else
run_install_cmd "install unsloth" uv pip install --python "$_VENV_PY" \
--upgrade-package unsloth -- "$PACKAGE_NAME"
_overlay_local_repos
fi
# AMD ROCm: repair torch if the unsloth/unsloth-zoo install pulled in

# CUDA torch from PyPI, overwriting the ROCm wheels installed in Step 1.
if [ "$SKIP_TORCH" = false ]; then
case "$TORCH_INDEX_URL" in
Expand Down
32 changes: 28 additions & 4 deletions tests/sh/test_get_torch_index_url.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ _FAKE_SMI_DIR=$(mktemp -d)
{
sed -n '/^_has_amd_rocm_gpu()/,/^}/p' "$INSTALL_SH"
echo ""
sed -n '/^_has_intel_xpu_gpu()/,/^}/p' "$INSTALL_SH"
echo ""
sed -n '/^_has_usable_nvidia_gpu()/,/^}/p' "$INSTALL_SH"
echo ""
sed -n '/^get_torch_index_url()/,/^}/p' "$INSTALL_SH"
Expand Down Expand Up @@ -95,10 +97,10 @@ run_func() {
_mock_dir="$1"
if [ "$_mock_dir" = "none" ]; then
# Minimal PATH with only basic tools, no nvidia-smi anywhere
PATH="$_TOOLS_DIR" bash -c ". '$_FUNC_FILE'; get_torch_index_url" 2>/dev/null
UNSLOTH_DRM_ROOT="$_FAKE_SMI_DIR/no-drm" PATH="$_TOOLS_DIR" bash -c ". '$_FUNC_FILE'; get_torch_index_url" 2>/dev/null
else
# Put mock nvidia-smi dir first, then basic tools
PATH="$_mock_dir:$_TOOLS_DIR" bash -c ". '$_FUNC_FILE'; get_torch_index_url" 2>/dev/null
UNSLOTH_DRM_ROOT="$_FAKE_SMI_DIR/no-drm" PATH="$_mock_dir:$_TOOLS_DIR" bash -c ". '$_FUNC_FILE'; get_torch_index_url" 2>/dev/null
fi
}

Expand Down Expand Up @@ -190,6 +192,14 @@ rm -rf "$_cuda_dir" "$_amd_dir" "$_combined_dir"
_result=$(run_func "none")
assert_eq "no GPU -> cpu" "https://download.pytorch.org/whl/cpu" "$_result"

# 13b) Intel DRM vendor id -> xpu
_intel_root=$(mktemp -d)
mkdir -p "$_intel_root/card0/device"
printf '0x8086\n' > "$_intel_root/card0/device/vendor"
_result=$(UNSLOTH_DRM_ROOT="$_intel_root" PATH="$_TOOLS_DIR" bash -c ". '$_FUNC_FILE'; get_torch_index_url" 2>/dev/null)
assert_eq "Intel DRM vendor -> xpu" "https://download.pytorch.org/whl/xpu" "$_result"
rm -rf "$_intel_root"

# 14) ROCm 6.1 (no nvidia-smi) -> rocm6.1
_dir=$(make_mock_amd_smi "6.1")
_result=$(run_func "$_dir")
Expand Down Expand Up @@ -218,7 +228,14 @@ rm -rf "$_dir"
_dir=$(mktemp -d)
cat > "$_dir/amd-smi" <<'MOCK'
#!/bin/sh
echo "AMDSMI Tool: 25.0.1 | AMDSMI Library version: 25.0.1.0 | ROCm version: "
case "$1" in
list)
printf 'GPU: 0\n BDF: 0000:03:00.0\n NAME: gfx1100\n'
;;
*)
echo "AMDSMI Tool: 25.0.1 | AMDSMI Library version: 25.0.1.0 | ROCm version: "
;;
esac
MOCK
chmod +x "$_dir/amd-smi"
_result=$(run_func "$_dir")
Expand All @@ -229,7 +246,14 @@ rm -rf "$_dir"
_dir=$(mktemp -d)
cat > "$_dir/amd-smi" <<'MOCK'
#!/bin/sh
echo "AMDSMI Tool: 25.0.1 | AMDSMI Library version: 25.0.1.0 | ROCm version: N/A"
case "$1" in
list)
printf 'GPU: 0\n BDF: 0000:03:00.0\n NAME: gfx1100\n'
;;
*)
echo "AMDSMI Tool: 25.0.1 | AMDSMI Library version: 25.0.1.0 | ROCm version: N/A"
;;
esac
MOCK
chmod +x "$_dir/amd-smi"
_result=$(run_func "$_dir")
Expand Down