Skip to content

Commit b92b2d0

Browse files
fix(ci): force MSVC host toolchain on Windows to prevent dlltool errors
The self-hosted Windows runner has a persistent rustup settings file (C:\Windows\system32\config\systemprofile\.rustup\settings.toml) with default_host_triple set to x86_64-pc-windows-gnu. The setup-rust-toolchain action reinstalls rustup which reads this file, causing bare toolchain names like nightly-2026-02-09 to resolve to the GNU variant. The GNU toolchain requires dlltool.exe which is not present on MSVC-only runners. Fix with three layers of defense: - Use fully qualified RUSTUP_TOOLCHAIN on Windows (nightly-2026-02-09-x86_64-pc-windows-msvc) in taskfiles/ci.yml to eliminate host triple ambiguity - Add rustup set default-host x86_64-pc-windows-msvc before toolchain install in both the composite action and the Taskfile - Pass PINNED_RUST explicitly from the composite action to task ci:setup on Windows, bypassing unreliable grep/awk resolution in Task's sh: - Add host verification to the setup-rust-windows status check - Document the constraint in AGENTS.md and docs/builds.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f74c32f commit b92b2d0

4 files changed

Lines changed: 39 additions & 3 deletions

File tree

.github/actions/setup-tauri-build/action.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ runs:
4141
$gitPath = (Get-ItemProperty 'HKLM:\SOFTWARE\GitForWindows' -ErrorAction SilentlyContinue).InstallPath
4242
if ($gitPath) { echo "$gitPath\usr\bin" >> $env:GITHUB_PATH }
4343
44+
- name: Set rustup default host to MSVC (Windows)
45+
if: runner.os == 'Windows'
46+
shell: pwsh
47+
run: |
48+
if (Get-Command rustup -ErrorAction SilentlyContinue) {
49+
rustup set default-host x86_64-pc-windows-msvc
50+
}
51+
4452
- name: Install Task
4553
uses: go-task/setup-task@v1
4654

@@ -129,7 +137,7 @@ runs:
129137
- name: Setup CI environment (Windows)
130138
if: runner.os == 'Windows'
131139
shell: pwsh
132-
run: task ci:setup
140+
run: task ci:setup PINNED_RUST=${{ steps.rust-version-windows.outputs.toolchain }}
133141

134142
- name: Windows Defender exclusions
135143
if: runner.os == 'Windows'

AGENTS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ Three directories are involved — do NOT cross-link them:
8484

8585
`cargo.yml` adds `~/.cargo/bin` to PATH so rustup tools are always findable. The `_setup-cargo-home` task symlinks project-local `CARGO_HOME/bin/` to `~/.cargo/bin/` — never to the mise install dir, which has its own internal symlink structure.
8686

87+
### Windows CI Toolchain Constraint
88+
89+
On Windows CI runners, `RUSTUP_TOOLCHAIN` MUST use the fully qualified name with host triple suffix (e.g. `nightly-2026-02-09-x86_64-pc-windows-msvc`). Bare channel names like `nightly-2026-02-09` resolve using the runner's default host triple, which can be stale GNU — causing `dlltool.exe` not found errors. See [Build Configuration — Windows Toolchain Pinning](docs/builds.md#windows-toolchain-pinning) for details.
90+
91+
When modifying `taskfiles/ci.yml` or `.github/actions/setup-tauri-build/action.yml`:
92+
93+
- Never set `RUSTUP_TOOLCHAIN` to a bare toolchain name on Windows
94+
- Always run `rustup set default-host x86_64-pc-windows-msvc` before toolchain installation
95+
- Pass `PINNED_RUST` explicitly from the composite action rather than relying on shell extraction in Task
96+
8797
## Queue and Shuffle Behavior
8898

8999
The queue store (`app/frontend/js/stores/queue.js`) maintains tracks in **play order** — the `items` array always reflects the order tracks will be played.

docs/builds.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ Runs on `ubuntu-latest`:
522522

523523
Runs on a self-hosted `[self-hosted, Windows, X64]` runner:
524524

525-
1. Sets up the Tauri build environment (Chocolatey installs cmake and rustup; `RUSTUP_TOOLCHAIN=nightly-2026-02-09` is exported to `GITHUB_ENV` and `~/.cargo/bin` is prepended to `GITHUB_PATH` to ensure the nightly toolchain takes precedence)
525+
1. Sets up the Tauri build environment (Chocolatey installs cmake and rustup; `~/.cargo/bin` is prepended to `GITHUB_PATH`; `RUSTUP_TOOLCHAIN` is set to the fully qualified `nightly-2026-02-09-x86_64-pc-windows-msvc` to ensure the MSVC-hosted toolchain is used — see [Windows Toolchain Pinning](#windows-toolchain-pinning) below)
526526
2. Installs Windows SDK for `signtool.exe`
527527
3. Generates a self-signed `CodeSigningCert` and exports to PFX
528528
4. Builds the frontend explicitly (`npm run build` in `app/frontend/`)
@@ -531,6 +531,22 @@ Runs on a self-hosted `[self-hosted, Windows, X64]` runner:
531531
7. Attaches the signed `.exe` to the same draft GitHub Release
532532
8. Cleans up the certificate and config override (runs in `always()` step)
533533

534+
#### Windows Toolchain Pinning
535+
536+
The self-hosted Windows runner can accumulate stale rustup state across runs. In particular, a system-level settings file (`C:\Windows\system32\config\systemprofile\.rustup\settings.toml`) may set `default_host_triple` to `x86_64-pc-windows-gnu`. When `RUSTUP_TOOLCHAIN` is set to a bare channel name like `nightly-2026-02-09`, rustup resolves it using the default host triple — producing the GNU-hosted toolchain, which requires `dlltool.exe` (not present on MSVC-only runners) and fails with:
537+
538+
```text
539+
error: error calling dlltool 'dlltool.exe': program not found
540+
```
541+
542+
To prevent this, the CI configuration uses three layers of defense:
543+
544+
1. **Fully qualified `RUSTUP_TOOLCHAIN`** (`taskfiles/ci.yml`): On Windows, the env var is set to `nightly-2026-02-09-x86_64-pc-windows-msvc` (with the host triple suffix), eliminating any ambiguity in toolchain resolution.
545+
546+
2. **`rustup set default-host x86_64-pc-windows-msvc`** (`.github/actions/setup-tauri-build/action.yml` and `taskfiles/ci.yml`): Run before toolchain installation to override any stale GNU default.
547+
548+
3. **Explicit `PINNED_RUST` passthrough** (`.github/actions/setup-tauri-build/action.yml`): The composite action extracts the Rust version from `.tool-versions` using PowerShell and passes it to `task ci:setup PINNED_RUST=...`, bypassing the Taskfile's `sh: grep | awk` which may fail when Git Bash utilities aren't in PATH.
549+
534550
## Linux System Dependencies
535551

536552
Tauri on Ubuntu/Debian requires these packages:

taskfiles/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ vars:
2121
env:
2222
PATH: "{{.CARGO_BIN}}:{{.MISE_SHIMS}}:{{.PATH}}"
2323
RUSTC_WRAPPER: ""
24-
RUSTUP_TOOLCHAIN: "{{.PINNED_RUST}}"
24+
RUSTUP_TOOLCHAIN: '{{if eq OS "windows"}}{{.PINNED_RUST}}-x86_64-pc-windows-msvc{{else}}{{.PINNED_RUST}}{{end}}'
2525

2626
tasks:
2727
setup:
@@ -50,12 +50,14 @@ tasks:
5050
desc: "Configure rustup nightly toolchain (Windows)"
5151
platforms: [windows]
5252
cmds:
53+
- rustup set default-host x86_64-pc-windows-msvc
5354
- rustup toolchain install {{.PINNED_RUST}} --profile minimal --no-self-update --target x86_64-pc-windows-msvc
5455
- rustup default {{.PINNED_RUST}}
5556
- rustc --version
5657
- cargo --version
5758
status:
5859
- rustup run {{.PINNED_RUST}} rustc --version
60+
- 'rustup run {{.PINNED_RUST}} rustc --version --verbose | findstr "host: x86_64-pc-windows-msvc"'
5961
- rustup target list --installed --toolchain {{.PINNED_RUST}} | findstr x86_64-pc-windows-msvc
6062

6163
setup-cargo-tools:

0 commit comments

Comments
 (0)