diff --git a/install.ps1 b/install.ps1 index 92487f99e9..5df7e16d9c 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1213,7 +1213,26 @@ shell.Run cmd, 0, False $ROCmVersion = $null $ROCmGfxArch = $null if (-not $HasNvidiaSmi) { + # hipinfo: PATH first, then HIP_PATH/ROCM_PATH bin fallback (mirrors NVIDIA smi path resolution). + # AMD HIP SDK sets HIP_PATH but may not add the bin dir to PATH depending on install type. $hipinfoExe = Get-Command hipinfo -ErrorAction SilentlyContinue + if (-not $hipinfoExe) { + $hipRoot = if ($env:HIP_PATH) { $env:HIP_PATH } elseif ($env:ROCM_PATH) { $env:ROCM_PATH } else { $null } + $hipEnvLabel = if ($env:HIP_PATH) { "HIP_PATH" } else { "ROCM_PATH" } + if ($hipRoot) { + $hipinfoCandidate = Join-Path $hipRoot "bin\hipinfo.exe" + if (Test-Path $hipinfoCandidate) { + Write-Host " [WARN] hipinfo not on PATH -- located via ${hipEnvLabel}: $hipinfoCandidate" -ForegroundColor Yellow + Write-Host " Add '$(Join-Path $hipRoot 'bin')' to your PATH to suppress this warning" -ForegroundColor Yellow + Write-Host " Quick fix: [Environment]::SetEnvironmentVariable('PATH',`$env:PATH+';$(Join-Path $hipRoot 'bin')','User')" -ForegroundColor Yellow + $hipinfoExe = [PSCustomObject]@{ Source = $hipinfoCandidate } + } else { + Write-Host " [WARN] ${hipEnvLabel}=$hipRoot is set but hipinfo.exe not found at $hipinfoCandidate" -ForegroundColor Yellow + Write-Host " HIP SDK install may be incomplete -- re-install from:" -ForegroundColor Yellow + Write-Host " https://rocm.docs.amd.com/en/latest/deploy/windows/index.html" -ForegroundColor Yellow + } + } + } if ($hipinfoExe) { try { $hipOut = & $hipinfoExe.Source 2>&1 | Out-String @@ -1225,6 +1244,12 @@ shell.Run cmd, 0, False } else { $ROCmGpuLabel = "AMD ROCm" } + } elseif ($LASTEXITCODE -ne 0) { + # hipinfo ran but returned a HIP runtime error (e.g. "no ROCm-capable device detected") + $firstLine = ($hipOut -split '\r?\n' | Where-Object { $_.Trim() } | Select-Object -First 1) + Write-Host " [WARN] hipinfo returned a HIP runtime error (exit $LASTEXITCODE)" -ForegroundColor Yellow + Write-Host " $firstLine" -ForegroundColor Yellow + Write-Host " Ensure ROCm drivers are installed: https://rocm.docs.amd.com/en/latest/deploy/windows/index.html" -ForegroundColor Yellow } } catch {} } @@ -1300,6 +1325,17 @@ shell.Run cmd, 0, False # Capture ROCm version for wheel selection (hipconfig, then amd-smi) if ($HasROCm) { $hipConfigExe = Get-Command hipconfig -ErrorAction SilentlyContinue + if (-not $hipConfigExe) { + $hipRoot = if ($env:HIP_PATH) { $env:HIP_PATH } elseif ($env:ROCM_PATH) { $env:ROCM_PATH } else { $null } + if ($hipRoot) { + $hipConfigCandidate = Join-Path $hipRoot "bin\hipconfig.exe" + if (Test-Path $hipConfigCandidate) { + $hipConfigEnvLabel = if ($env:HIP_PATH) { "HIP_PATH" } else { "ROCM_PATH" } + Write-Host " [WARN] hipconfig not on PATH -- located via ${hipConfigEnvLabel}: $hipConfigCandidate" -ForegroundColor Yellow + $hipConfigExe = [PSCustomObject]@{ Source = $hipConfigCandidate } + } + } + } if ($hipConfigExe) { try { $hipVerOut = & $hipConfigExe.Source --version 2>&1 | Out-String diff --git a/studio/setup.ps1 b/studio/setup.ps1 index ada93991c1..b3e977ee75 100644 --- a/studio/setup.ps1 +++ b/studio/setup.ps1 @@ -687,8 +687,26 @@ $HasROCm = $false $ROCmGpuLabel = $null $script:ROCmGfxArch = $null if (-not $HasNvidiaSmi) { - # hipinfo: present + output contains gcnArchName → real HIP GPU + # hipinfo: PATH first, then HIP_PATH/ROCM_PATH bin fallback (mirrors NVIDIA smi path resolution). + # AMD HIP SDK sets HIP_PATH but may not add the bin dir to PATH depending on install type. $hipinfoExe = Get-Command hipinfo -ErrorAction SilentlyContinue + if (-not $hipinfoExe) { + $hipRoot = if ($env:HIP_PATH) { $env:HIP_PATH } elseif ($env:ROCM_PATH) { $env:ROCM_PATH } else { $null } + $hipEnvLabel = if ($env:HIP_PATH) { "HIP_PATH" } else { "ROCM_PATH" } + if ($hipRoot) { + $hipinfoCandidate = Join-Path $hipRoot "bin\hipinfo.exe" + if (Test-Path $hipinfoCandidate) { + substep "[WARN] hipinfo not on PATH -- located via ${hipEnvLabel}: $hipinfoCandidate" "Yellow" + substep " Add '$(Join-Path $hipRoot 'bin')' to your PATH to suppress this warning" "Yellow" + substep " Quick fix: [Environment]::SetEnvironmentVariable('PATH',`$env:PATH+';$(Join-Path $hipRoot 'bin')','User')" "Yellow" + $hipinfoExe = [PSCustomObject]@{ Source = $hipinfoCandidate } + } else { + substep "[WARN] ${hipEnvLabel}=$hipRoot is set but hipinfo.exe not found at $hipinfoCandidate" "Yellow" + substep " HIP SDK install may be incomplete -- re-install from:" "Yellow" + substep " https://rocm.docs.amd.com/en/latest/deploy/windows/index.html" "Yellow" + } + } + } if ($hipinfoExe) { try { $hipOut = & $hipinfoExe.Source 2>&1 | Out-String @@ -700,6 +718,12 @@ if (-not $HasNvidiaSmi) { } else { $ROCmGpuLabel = "AMD ROCm" } + } elseif ($LASTEXITCODE -ne 0) { + # hipinfo ran but returned a HIP runtime error (e.g. "no ROCm-capable device detected") + $firstLine = ($hipOut -split '\r?\n' | Where-Object { $_.Trim() } | Select-Object -First 1) + substep "[WARN] hipinfo returned a HIP runtime error (exit $LASTEXITCODE)" "Yellow" + substep " $firstLine" "Yellow" + substep " Ensure ROCm drivers are installed: https://rocm.docs.amd.com/en/latest/deploy/windows/index.html" "Yellow" } } catch {} } @@ -787,6 +811,17 @@ if (-not $HasNvidiaSmi) { if ($HasROCm) { $script:ROCmVersion = $null $hipConfigExe = Get-Command hipconfig -ErrorAction SilentlyContinue + if (-not $hipConfigExe) { + $hipRoot = if ($env:HIP_PATH) { $env:HIP_PATH } elseif ($env:ROCM_PATH) { $env:ROCM_PATH } else { $null } + if ($hipRoot) { + $hipConfigCandidate = Join-Path $hipRoot "bin\hipconfig.exe" + if (Test-Path $hipConfigCandidate) { + $hipConfigEnvLabel = if ($env:HIP_PATH) { "HIP_PATH" } else { "ROCM_PATH" } + substep "[WARN] hipconfig not on PATH -- located via ${hipConfigEnvLabel}: $hipConfigCandidate" "Yellow" + $hipConfigExe = [PSCustomObject]@{ Source = $hipConfigCandidate } + } + } + } if ($hipConfigExe) { try { $hipVerOut = & $hipConfigExe.Source --version 2>&1 | Out-String diff --git a/tests/studio/install/test_rocm_support.py b/tests/studio/install/test_rocm_support.py index fac8b4bb85..53eb9aa1a4 100644 --- a/tests/studio/install/test_rocm_support.py +++ b/tests/studio/install/test_rocm_support.py @@ -2077,5 +2077,128 @@ class TestStrixHaloGfxArchDetection: ), f"gfx arch regex not found in {path.name}" +# ============================================================================= +# TEST: HIP SDK tool path resolution via HIP_PATH / ROCM_PATH env vars +# ============================================================================= + + +class TestHipSdkEnvPathResolution: + """Verify that both install scripts resolve hipinfo/hipconfig via HIP_PATH + and ROCM_PATH when the tools are not on $PATH, and emit explicit warnings.""" + + # ── hipinfo resolution ──────────────────────────────────────────────────── + + def test_setup_checks_hip_path_for_hipinfo(self): + """setup.ps1 must reference HIP_PATH when resolving hipinfo.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert "HIP_PATH" in source + assert "hipinfo" in source + + def test_install_checks_hip_path_for_hipinfo(self): + """install.ps1 must reference HIP_PATH when resolving hipinfo.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "HIP_PATH" in source + assert "hipinfo" in source + + def test_setup_checks_rocm_path_as_hipinfo_fallback(self): + """setup.ps1 must also check ROCM_PATH as a secondary hipinfo fallback.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert "ROCM_PATH" in source + # Confirm the fallback pattern: HIP_PATH ?? ROCM_PATH (or equivalent elseif) + assert ("ROCM_PATH" in source and "HIP_PATH" in source) + + def test_install_checks_rocm_path_as_hipinfo_fallback(self): + """install.ps1 must also check ROCM_PATH as a secondary hipinfo fallback.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "ROCM_PATH" in source + assert ("ROCM_PATH" in source and "HIP_PATH" in source) + + def test_setup_resolves_hipinfo_via_bin_subdir(self): + """setup.ps1 must join the env var root with 'bin\\hipinfo.exe'.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert r"bin\hipinfo.exe" in source + + def test_install_resolves_hipinfo_via_bin_subdir(self): + """install.ps1 must join the env var root with 'bin\\hipinfo.exe'.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert r"bin\hipinfo.exe" in source + + # ── hipinfo not-on-PATH warning ─────────────────────────────────────────── + + def test_setup_warns_when_hipinfo_not_on_path(self): + """setup.ps1 must warn when hipinfo is found via env var but not on PATH.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert "hipinfo not on PATH" in source + + def test_install_warns_when_hipinfo_not_on_path(self): + """install.ps1 must warn when hipinfo is found via env var but not on PATH.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "hipinfo not on PATH" in source + + # ── warn when HIP_PATH set but exe missing ──────────────────────────────── + + def test_setup_warns_when_hip_path_set_but_exe_missing(self): + """setup.ps1 must warn when HIP_PATH is set but hipinfo.exe is not present.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + # The warning must mention that the SDK install may be incomplete + assert "incomplete" in source or "not found at" in source + + def test_install_warns_when_hip_path_set_but_exe_missing(self): + """install.ps1 must warn when HIP_PATH is set but hipinfo.exe is not present.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "incomplete" in source or "not found at" in source + + # ── hipinfo runtime error warning ───────────────────────────────────────── + + def test_setup_warns_on_hipinfo_nonzero_exit(self): + """setup.ps1 must warn when hipinfo runs but returns a non-zero exit code.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert "HIP runtime error" in source or "runtime error" in source.lower() + + def test_install_warns_on_hipinfo_nonzero_exit(self): + """install.ps1 must warn when hipinfo runs but returns a non-zero exit code.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "HIP runtime error" in source or "runtime error" in source.lower() + + # ── hipconfig resolution ────────────────────────────────────────────────── + + def test_setup_resolves_hipconfig_via_bin_subdir(self): + """setup.ps1 must also fall back to HIP_PATH/bin/hipconfig.exe for version detection.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert r"bin\hipconfig.exe" in source + + def test_install_resolves_hipconfig_via_bin_subdir(self): + """install.ps1 must also fall back to HIP_PATH/bin/hipconfig.exe for version detection.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert r"bin\hipconfig.exe" in source + + def test_setup_warns_when_hipconfig_not_on_path(self): + """setup.ps1 must warn when hipconfig is found via env var but not on PATH.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + assert "hipconfig not on PATH" in source + + def test_install_warns_when_hipconfig_not_on_path(self): + """install.ps1 must warn when hipconfig is found via env var but not on PATH.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "hipconfig not on PATH" in source + + # ── PATH fix hint ───────────────────────────────────────────────────────── + + def test_setup_provides_path_fix_hint(self): + """setup.ps1 must tell the user how to add the HIP bin dir to PATH.""" + source = _SETUP_PS1_PATH.read_text(encoding = "utf-8") + # Should mention adding to PATH or SetEnvironmentVariable + assert "PATH" in source and ( + "SetEnvironmentVariable" in source or "Add" in source + ) + + def test_install_provides_path_fix_hint(self): + """install.ps1 must tell the user how to add the HIP bin dir to PATH.""" + source = _INSTALL_PS1_PATH.read_text(encoding = "utf-8") + assert "PATH" in source and ( + "SetEnvironmentVariable" in source or "Add" in source + ) + + if __name__ == "__main__": pytest.main([__file__, "-v"])