build: bundle MSVC runtime DLLs into win32 zips - #6
Open
greatcoat wants to merge 1 commit into
Open
Conversation
The win32 exes link the dynamic MSVC runtime (CMAKE_MSVC_RUNTIME_LIBRARY= MultiThreaded is a no-op while CMP0091 is unset, and OpenMP links vcomp140 dynamically regardless), but every win32 zip shipped a bare exe. On machines without the VC++ 2015-2022 redistributable the loader kills whisper-server with 0xC0000135 (STATUS_DLL_NOT_FOUND) before main(), breaking local transcription in OpenWhispr (CUS-113). Bundle msvcp140/vcruntime140/vcruntime140_1/vcomp140 from the runner's VC redist dir (globbed, not pinned to VC143) into the CPU, CUDA, and Vulkan zips, and fail CI if any zip is missing them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Problem: Every win32 zip ships a bare exe that imports the dynamic MSVC runtime; machines without the VC++ redistributable kill it at load with 0xC0000135, breaking OpenWhispr local transcription.
Fix: Copy msvcp140/vcruntime140/vcruntime140_1/vcomp140 from the runner's VC redist dir (globbed toolset path) into dist for the CPU, CUDA, and Vulkan jobs, include them in every Compress-Archive, and fail CI if any zip lacks them.
Root cause
The build passes
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedintending a static CRT, but that variable is a silent no-op while CMake policy CMP0091 is unset — so the exes link the dynamic CRT — and MSVC OpenMP linksVCOMP140.DLLdynamically regardless. The packaging steps then zip the bare exe (CPU, Vulkan) or exe + CUDA DLLs only (CUDA). Nothing else in OpenWhispr's shipping path provides the runtime: the Windows loader terminates the process with0xC0000135(STATUS_DLL_NOT_FOUND) beforemain(), with empty stderr.PE import tables of the shipped 0.0.8/0.0.9 exes (parsed from the release assets — dumpbin-equivalent): all five win32 exes (
whisper-cpp-cpu/-cuda,whisper-server-cpu/-cuda/-vulkan) importMSVCP140.dll,VCOMP140.DLL,VCRUNTIME140.dll,VCRUNTIME140_1.dll; none of the zips contains any of them (0.0.8 + 0.0.9 asset listings verified). The Vulkan packaging comment claiming "no other runtime DLLs are needed" was factually wrong and is corrected.Fix details
build-windows-x64-cpu— copy the 4 DLLs from$env:VCToolsRedistDir\x64\Microsoft.VC*.CRT/...\Microsoft.VC*.OpenMPintodist, include them in both Compress-Archive calls (thewhisper-cpp-*.zipcli asset had the same defect).build-windows-x64-cuda— same 4 DLLs appended to the existing$bundledDllslist (after the CUDA-DLL count check, so that check keeps its meaning).build-windows-x64-vulkan— same 4 DLLs added to the zip;vulkan-1.dllstays unbundled (GPU driver provides it).Microsoft.VC*.CRT), not hardcoded to VC143 — the toolset version moves with the runner image.Deliberate non-changes: not switching to a real static CRT (CMP0091=NEW +
GGML_OPENMP=OFF) — bundling app-locally is the approved scope; the static alternative is documented in the RCA and needs an explicit go. CUDA DLL bundling logic untouched.Tests
missing: msvcp140.dll, vcomp140.dll, vcruntime140.dll, vcruntime140_1.dll. A simulated dist with the four DLLs passes.workflow_dispatch/tag only); dispatching it publishes a release, so first real run = the 0.0.10 cut after merge.Provenance
wiki/areas/engineering/whisper-server-dll-not-found-rca.md; Linear CUS-113 (evidence chain in RCA comment).1a00fc15dfac3569,debug-2026-08-17T12-23-22-137Z.log(14 spawns, all exit 3221225781 in ~50 ms, empty stderr).WHISPER_CPP_TAGbump targets 0.0.10 (companion PR).🤖 Generated with Claude Code