ci(windows): drop rustc's stale libwinpthread so C++ proc-macros load - #590
Merged
Conversation
Coverage Summary
|
There was a problem hiding this comment.
Pull request overview
Adjusts the Windows CI toolchain bootstrap to avoid a deterministic proc-macro load failure in Slang tests caused by rustc’s sysroot bin/ shadowing MSYS2’s newer MinGW runtime DLLs.
Changes:
- Adds a Windows-only step in the shared
build-toolchaincomposite action to remove rustc’s stalelibwinpthread-1.dllfrom the sysrootbin/, allowing DLL resolution to fall through to MSYS2 viaPATH. - Documents the rationale and why the step is expected to become a no-op once Rust ships a mingw-w64 v14+ bundled runtime.
hedgar2017
approved these changes
Jul 22, 2026
hedgar2017
approved these changes
Jul 22, 2026
hedgar2017
enabled auto-merge
July 22, 2026 14:36
rustc loads proc-macros via LoadLibraryExW with the default search order, where the application directory - rustc's sysroot bin/ - beats PATH. The windows-gnu dist ships a stale libwinpthread-1.dll there that nothing in bin/ imports (verified: rustc.exe, rustdoc.exe, rustc_driver-*.dll, std-*.dll depend only on KERNEL32/msvcrt/ntdll/ libgcc; rust-lld.exe has its own copies under rustlib/, untouched here). Since the shared-libstdc++ workaround for #550, a freshly compiled melior-macro (proc-macro linking LLVM C++ via tblgen) depends on GCC 16's libstdc++-6.dll at load time, which imports clock_gettime64, nanosleep64 and pthread_cond_timedwait64 from mingw-w64 v14 winpthreads. The stale copy predates those exports, the dependency chain fails to load, and rustc reports the generic E0463 "can't find crate for melior_macro" - Slang Tests / Windows has been red on main since the melior rev bump in #557 forced the first fresh melior build (runs 29910202004, 29912409528). Deleting the dead DLL lets the dependency fall through to MSYS2's copy via PATH. Same-class prior art: rust-lang/rust#99534 (stale bundled libgcc_s_dw2-1.dll vs MSYS2 gcc >= 11.3, fixed by a bundled-mingw bump), ddnet/ddnet#10203, and a ruby-core report with the identical delete-the-stale-DLL fix.
nebasuke
force-pushed
the
win-procmacro-winpthread
branch
from
July 22, 2026 14:40
9f2f747 to
72d4e32
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workaround for #589 (the load-time sequel to #550).
Problem
Slang Tests → Windows is deterministically red on
mainsince #557 merged (runs 29910202004, 29912409528):The melior rev bump in #557 is the trigger, not the cause — it invalidated the cargo cache entry and forced the first fresh
meliorcompile (= first proc-macro load) since the #550 shared-libstdc++ workaround landed.melior-macro's source is byte-identical across the two revs, and no goodmeliorartifact can ever be cached while the load fails, so the leg stays red without this fix.Root cause (confirmed by PE import/export analysis — full trail in #589)
melior-macrois a proc-macro that links LLVM C++ (viatblgen). Since the #550 workaround switched test builds to shared libstdc++, the builtmelior_macro.dllneeds GCC 16'slibstdc++-6.dllat load time.rustc loads proc-macros via
libloading→LoadLibraryExW(path, 0)→ the default Windows DLL search order, in which the application directory — rustc's sysrootbin/— beats PATH. The windows-gnu dist ships a stalelibwinpthread-1.dllthere, and GCC 16'slibstdc++-6.dllimports three mingw-w64 v14 64-bit-time symbols the stale copy doesn't export:libstdc++-6.dllimports from winpthreadlibwinpthread-1.dllclock_gettime64nanosleep64pthread_cond_timedwait64The dependency chain fails to load and rustc surfaces it as the generic
E0463: can't find crate. PATH-based fixes cannot work — the app dir always wins.Fix
Delete the stale DLL from the sysroot
bin/inbuild-toolchain(next to the existing #550 workaround, same guards), so the dependency falls through to MSYS2's mingw-w64 v14 copy via PATH:rm -fv "$(rustc --print sysroot)/bin/libwinpthread-1.dll"Verified safe: nothing in the sysroot
bin/imports winpthread —rustc.exe,rustdoc.exe,rustc_driver-*.dll, andstd-*.dllall checked (they depend only on KERNEL32/msvcrt/ntdll/libgcc).rust-lld.exedoes need it, but has its own copies underrustlib/<triple>/bin/(rust-lang/rust#128876), untouched here. The libgcc half of the chain needs no intervention: all 14 symbols GCC 16's libstdc++ imports fromlibgcc_s_seh-1.dllare exported by rust's bundled copy.-fmakes the step self-nooping (and deletable) once rust ships mingw-w64 ≥ v14.Prior art — same class, same fix shape
libgcc_s_dw2-1.dllbroke MSYS2 gcc ≥ 11.3; reporter's workaround was deleting the DLL; fixed upstream by a bundled-mingw bump (Upgrade mingw-w64 on CI rust-lang/rust#100178).libwinpthread-1.dllddnet/ddnet#10203 and a ruby-core report: identical stale-winpthread failures outside Rust, both resolved by removing/replacing the stale DLL.An upstream report against rust-lang/rust is being filed in parallel (the
bin/copy is imported by nothing there and shadows newer runtimes during in-process loads); this workaround stays until a fixed toolchain reaches our pinnedrust-toolchain.toml. The structural fix that makes it deletable on our side — getting tblgen out of macro-expansion time in the melior fork — is tracked in #589.Verification
Verified in run 29923864614: the Windows leg passes — the cached GCC-16-linked
melior_macro.dll(the exact artifact that failed onmain) loads,meliorcompiles, and the slang suite runs green, with this one-file change as the only difference from the failing configuration. The run's overall red comes fromsolx-mlir :: conditional.solfailing on Linux ARM64 + macOS x86 — a pre-existingmainbreakage from #563, unrelated to this Windows-gated change; tracked in #591.