Skip to content

fix(wsl): install ROCDXG from the CLI instead of naming a repo script - #224

Open
rominf wants to merge 1 commit into
mainfrom
fix/wsl-install-rocdxg
Open

fix(wsl): install ROCDXG from the CLI instead of naming a repo script#224
rominf wants to merge 1 commit into
mainfrom
fix/wsl-install-rocdxg

Conversation

@rominf

@rominf rominf commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

On WSL2, rocm install driver refused to do anything and pointed the user at a
script that is not shipped:

  supported: false
  mutating: false
  reason: WSL uses the Windows host driver plus ROCDXG; run `scripts/wsl_setup_rocdxg.sh` inside WSL instead of installing Linux DKMS.
  execution_commands: <none>
  action: no driver commands will be executed

scripts/ is not in the release bundle — xtask package stages bin/rocm,
bin/rocmd, README.md, LICENSE.TXT and the platform installer — so for
anyone who installed rocm-cli normally that names a file they do not have.

It matters because ROCDXG (librocdxg) is what lets the ROCm runtime reach the
GPU under WSL2. Without it examine reports wsl_rocdxg_missing and serve
refuses with "no usable AMD GPU detected", while still detecting a gfx target —
that target is read from the Windows-side driver, so its presence says nothing
about whether ROCm can use the device. The one platform where a ROCm-provided
library decides whether the GPU works was the one platform where the CLI would
not install it.

Fixes #223.

What changes

The WSL branch of build_driver_install_plan returns a real plan instead of a
refusal — the same steps scripts/wsl_setup_rocdxg.sh runs, expressed through
the machinery every other platform already uses. That is deliberate: it inherits
plan-then-approve, --dry-run, the recorded install state and the post-install
reconciliation without any new download or verification code.

$ rocm install driver
driver install plan
  policy: wsl_rocdxg
  supported: true
  mutating: true
  approval: required
  repo_version: ${ROCM_CLI_ROCDXG_VERSION:-1.2.0}
  reason: WSL2 uses the Windows host driver plus ROCDXG, not Linux DKMS; this installs ROCDXG.
  preflight_checks:
    /dev/dxg (WSL GPU device)
    /usr/lib/wsl/lib/libdxcore.so (WSL dxcore runtime)
  execution_commands:
    Prepare: test -e /dev/dxg || { ... }
    Prepare: test -e /usr/lib/wsl/lib/libdxcore.so || { ... }
    Prepare: sudo apt-get update
    Prepare: sudo apt-get install -y ca-certificates curl
    Execute: curl -L --fail --show-error --output /tmp/rocdxg-roct_...deb https://github.com/ROCm/librocdxg/releases/download/v.../...
    Execute: if [ -n "${ROCM_CLI_ROCDXG_SHA256:-}" ]; then ... sha256sum -c -; else echo '... skipping checksum verification'; fi
    Execute: sudo apt-get install -y /tmp/rocdxg-roct_...deb
    Execute: sudo ldconfig
  post_install_check_commands:
    test -e /opt/rocm/lib/librocdxg.so
    ldconfig -p | grep -q 'librocdxg\.so'
  action: rerun with --yes after reviewing this plan, or approve from the TUI

Guards before anything mutates. /dev/dxg and dxcore come from the Windows
side; if they are absent the fix is on the host and installing the bridge
library accomplishes nothing, so the plan stops rather than reporting a
successful install of something inert.

Verification asserts what examine keys on. wsl_rocdxg_ready requires the
library and its ldconfig entry, so both are checked — a partial install cannot
report success.

Version and checksum follow the conventions already in this file.
ROCM_CLI_ROCDXG_VERSION mirrors the existing ROCM_CLI_AMDGPU_VERSION
treatment: a shell-expanded expression, so the printed plan shows both the
variable and the default. One expression drives the archive name, the tag and
the path, so an override cannot leave a URL pointing at the default. No digest
is embedded, because the release is not reproducible from here — an unset
ROCM_CLI_ROCDXG_SHA256 says so explicitly rather than letting an unverified
download read as verified.

reboot_required is now a property of the plan

Previously the post-execution output asserted reboot_required: true
unconditionally. That is right for the DKMS paths — an amdgpu module is not live
until the machine restarts — and wrong here: ROCDXG is userspace and ldconfig
publishes it in the current boot. Plans now carry the flag, the DKMS paths keep
true, and the verification steps are labelled post_install rather than
post_reboot so the rendered plan does not contradict the state it records.

The script is deleted, not kept alongside

scripts/wsl_setup_rocdxg.sh is removed. Keeping it would leave two
implementations of one privileged install, and specifically two of everything
that can drift: a ROCDXG_VERSION=1.2.0 pin beside
${ROCM_CLI_ROCDXG_VERSION:-1.2.0}, and a ROCDXG_SHA256 variable beside
ROCM_CLI_ROCDXG_SHA256. Nothing in CI ever ran it — the
ROCDXG_CHECKSUM_SELF_TEST hook existed only as a manual step in
docs/testing.md — so it was an unshipped, untested installer.

Its one behaviour the plan lacked, an explicit "sudo is required" message
instead of a bare sudo: command not found, is folded in as a third guard.
scripts/wsl_preflight.py is untouched: it still has a Windows-to-distro check
with no CLI equivalent.

Docs now lead with rocm install driver.

Not addressed here: rocm diagnose still declares the bare-metal catalog out of
scope on WSL with no entry for wsl_rocdxg_missing, so that finding has no
runnable command — the class of problem #209 fixed elsewhere. It wants a catalog
entry pointing at this command, which is a separate change.

Test plan

Six unit tests, covering the install steps and URL, the ordering guarantee that
the plumbing and sudo guards precede the first mutating command, the verification pair,
checksum opt-in/enforcement, override reach, and that WSL asks for no reboot
while bare metal still does.

Verified on a real WSL2 host: the reproduction from the report now prints the
plan above instead of the refusal. The plumbing guard and the three checksum
branches (unset / matching / mismatched) were exercised directly and behave as
intended — exit 1 with the stated message, skip-with-notice, OK, and FAILED
respectively.

Verification gap. This box is WSL2 without GPU passthrough
(driver_status: wsl_gpu_plumbing_missing, no /dev/dxg), so the install
itself cannot be run through end to end here — the plan correctly refuses at the
first guard. Someone with /dev/dxg and dxcore present should confirm a real
--yes run reaches wsl_rocdxg_ready. The self-hosted WSL2 CI runner is a
candidate once #141 lands.

cargo clippy --locked --workspace --all-targets -- -D warnings,
cargo clippy --locked -p e2e-cucumber --test e2e -- -D warnings,
cargo fmt --all --check and prek run --all-files are clean. cargo test -p rocm --bin rocm: 433 pass; the two failures are the known local flakes
(providers::tests::local_provider_default_chat_requires_builtin_qwen_assistant,
therock::tests::extracting_the_sdk_archive_removes_it), both of which
reproduce on an unmodified main checkout in this environment.

Risk: medium. A command that previously did nothing on WSL now runs privileged
package operations — but only behind the same explicit --yes approval as every
other platform, and only after the plumbing guards pass.

On WSL2 `rocm install driver` refused to do anything and told the user to
run `scripts/wsl_setup_rocdxg.sh`. That script shipped only in a git
checkout -- the release bundle is `bin/`, README, LICENSE and the
installer -- so for anyone who installed rocm-cli normally the guidance
named a file they do not have.

It matters because ROCDXG is what lets the runtime reach the GPU under
WSL2. Without it `examine` reports `wsl_rocdxg_missing` and `serve`
refuses with "no usable AMD GPU detected" while still detecting a gfx
target, which is read from the Windows-side driver. So the one platform
where a ROCm library decides whether the GPU works was the one platform
where the CLI would not install it.

The WSL branch now returns a real plan -- the same steps the script ran,
through the machinery every other platform already uses, so it inherits
plan-then-approve, `--dry-run` and the recorded install state. It guards
on /dev/dxg, dxcore and sudo before touching anything, since those come
from the platform and no package substitutes for them, then verifies the
two things `examine` keys `wsl_rocdxg_ready` on.

The script is deleted rather than left beside it: two implementations of
one privileged install means two version pins and two digest variables to
drift apart, and nothing in CI ever ran it.

Version and checksum follow the conventions already in this file:
`ROCM_CLI_ROCDXG_VERSION` mirrors `ROCM_CLI_AMDGPU_VERSION`, and no digest
is embedded because the release is not reproducible from here -- an unset
`ROCM_CLI_ROCDXG_SHA256` says so rather than reporting an unverified
download as verified.

Plans now carry `reboot_required`. It stays true for the DKMS paths, which
are not live until the machine restarts, and is false here: ROCDXG is
userspace and `ldconfig` publishes it immediately. Previously the
post-execution output asserted a reboot unconditionally, which would have
been wrong advice on this path, and the verification steps are labelled
post_install rather than post_reboot to match.

Signed-off-by: Roman Inflianskas <Roman.Inflianskas@amd.com>
@rominf
rominf force-pushed the fix/wsl-install-rocdxg branch from c4d8367 to 02144d4 Compare August 12, 2026 13:34
@rominf
rominf marked this pull request as ready for review August 12, 2026 16:18
@rominf
rominf requested a review from a team as a code owner August 12, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WSL] rocm install driver points at an unshipped repo script instead of installing ROCDXG

1 participant