Skip to content

Commit 36ed219

Browse files
authored
fix(windows): align CRT to dynamic to resolve ONNX __imp_ link errors (#7)
The x86_64-pc-windows-msvc release link failed with 75 LNK2019/LNK2001 errors on __imp_* C-runtime symbols. Root cause is a CRT linkage conflict (pykeio/ort #329): ONNX Runtime's prebuilt lib (ort download-binaries) links the CRT dynamically (/MD) and references __imp_* import stubs, but two C build-deps hardcode .static_crt(true), dragging libcmt/libucrt into the link and leaving ONNX's __imp_* unresolved: - esaxx-rs via tokenizers' default `esaxx_fast` feature (training-only) - libsqlite3-sys (bundled) via burn's default `dataset` feature Both are pulled by features WhisperForge never uses (no .encode(), no tokenizer training, no burn datasets). Fixes: - tokenizers: default-features=false + ["onig"] — drops esaxx_fast, so esaxx-rs no longer compiles its static-CRT C++. `onig` keeps the same regex backend as the default, so load/decode behavior is unchanged. - .cargo/config.toml: /NODEFAULTLIB:libcmt+libucrt and force msvcrt+ucrt, neutralizing libsqlite3-sys's static CRT and returning the link to ONNX's standard all-dynamic configuration. The prior legacy_stdio_definitions.lib flag targeted the wrong symbols. Also add a `windows-link-check` CI job that links the MSVC target with the dist feature set on every PR — the v0.5.3 failure surfaced only at tag time because PR runs only do `dist plan`, not a real build.
1 parent c28288c commit 36ed219

4 files changed

Lines changed: 53 additions & 11 deletions

File tree

.cargo/config.toml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,19 @@
88
# Release builds (dist) deliberately use the stock toolchain on ubuntu-22.04 for
99
# broad glibc compatibility.
1010

11-
# ORT pre-built static library (ort 2.0.0-rc.10, download-binaries) references
12-
# old-MSVCRT symbols (__dstbias, __timezone, __tzname) that live only in
13-
# legacy_stdio_definitions.lib — Microsoft's backward-compat shim for pre-VS2015
14-
# CRT references, absent from ucrt.lib/msvcrt.lib/vcruntime.lib.
11+
# ONNX Runtime (ort 2.0.0-rc.10, download-binaries) links the CRT *dynamically*
12+
# (/MD) and references __imp_* import stubs. `libsqlite3-sys` (bundled sqlite, via
13+
# burn's default dataset feature) compiles its C with the *static* CRT (/MT), which
14+
# drags libcmt/libucrt into the link and leaves ONNX's __imp_* unresolved (pykeio/ort
15+
# #329). Force the whole link onto the dynamic CRT so ucrt.lib/msvcrt.lib supply the
16+
# __imp_* stubs. The static-CRT C code (sqlite datasets) is never called at runtime,
17+
# so CRT-mixing has no runtime effect — only the link must be consistent.
18+
# NOTE: do not set the RUSTFLAGS env var on the Windows build (it overrides these
19+
# target rustflags); see ci.yml windows-link-check.
1520
[target.x86_64-pc-windows-msvc]
16-
rustflags = ["-C", "link-arg=legacy_stdio_definitions.lib"]
21+
rustflags = [
22+
"-C", "link-arg=/NODEFAULTLIB:libcmt.lib",
23+
"-C", "link-arg=/NODEFAULTLIB:libucrt.lib",
24+
"-C", "link-arg=/DEFAULTLIB:msvcrt.lib",
25+
"-C", "link-arg=/DEFAULTLIB:ucrt.lib",
26+
]

.github/workflows/ci.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,34 @@ jobs:
5353

5454
- name: Test
5555
run: cargo test --release --locked -p whisperforge-core -p whisperforge
56+
57+
windows-link-check:
58+
name: Windows MSVC link check
59+
runs-on: windows-2022
60+
61+
steps:
62+
- name: Checkout
63+
uses: actions/checkout@v4
64+
65+
- name: Install Rust toolchain
66+
uses: dtolnay/rust-toolchain@stable
67+
with:
68+
targets: x86_64-pc-windows-msvc
69+
70+
- name: Cache Cargo registry and build
71+
uses: actions/cache@v4
72+
with:
73+
path: |
74+
~/.cargo/registry/index/
75+
~/.cargo/registry/cache/
76+
~/.cargo/git/db/
77+
target/
78+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml', 'Cargo.lock') }}
79+
restore-keys: |
80+
${{ runner.os }}-cargo-
81+
82+
# NOTE: deliberately do NOT set RUSTFLAGS here — it would override the
83+
# .cargo/config.toml [target.x86_64-pc-windows-msvc] rustflags this job exists
84+
# to validate. (The `check` job sets RUSTFLAGS=mold, which is why this is separate.)
85+
- name: Build wforge (dist profile, gpu) — link only
86+
run: cargo build --profile dist --features gpu -p whisperforge --target x86_64-pc-windows-msvc --locked

Cargo.lock

Lines changed: 0 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,13 @@ rustfft = "6.2"
5858
cpal = "0.15"
5959
ringbuf = "0.4"
6060

61-
# Text processing
62-
tokenizers = "0.23"
61+
# Text processing.
62+
# default-features disabled to drop the `esaxx_fast` feature, which pulls esaxx-rs —
63+
# a C++ build-dep that hardcodes `.static_crt(true)`, forcing the static CRT (/MT) and
64+
# breaking the Windows MSVC link against ONNX Runtime's dynamic-CRT (/MD) prebuilt lib
65+
# (see .cargo/config.toml and pykeio/ort #329). esaxx_fast is training-only; we only
66+
# load + decode. `onig` keeps the same regex backend as the default → zero behavior change.
67+
tokenizers = { version = "0.23", default-features = false, features = ["onig"] }
6368

6469
# Serialization and CLI
6570
serde = { version = "1.0", features = ["derive"] }

0 commit comments

Comments
 (0)