--- name: Build script (Windows tokenizers guard) type: architecture-map-page slice: 03-audio-transcription last_verified: 2026/05/09 --- # Build script (Windows tokenizers guard) > **Where you are:** [Architecture map](../README.md) → [Audio + Transcription](README.md) → Build script **Plain English summary.** `magnotia-transcription/build.rs` reads `Cargo.lock` and refuses to compile on Windows if the `tokenizers` crate ever lands in the workspace dependency graph. Linking `whisper-rs-sys` and `tokenizers` together has been a repeated MSVC C-runtime conflict (Whispering v7.11.0 shipped a broken Windows build over exactly this). On non-Windows the check is a `cargo:warning`, not a fatal error, so the failure surfaces at CI build time rather than waiting for a Windows ship. ## At a glance - Crate: `magnotia-transcription` - Path: `crates/transcription/build.rs` - LOC: 73 - External deps: stdlib only (`std::env`, `std::fs`). - Internal callers: cargo invokes this automatically because `Cargo.toml` declares `build = "build.rs"`. Public surface: none (build scripts have no callable surface). ## What's in here ```rust fn main() { println!("cargo:rerun-if-changed=build.rs"); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into())); // Walk up to workspace root: crates/transcription/ -> crates/ -> root let workspace_root = manifest_dir .ancestors() .find(|p| p.join("Cargo.lock").exists()) .map(PathBuf::from); let Some(root) = workspace_root else { return; }; let lock_path = root.join("Cargo.lock"); println!("cargo:rerun-if-changed={}", lock_path.display()); let lock = match fs::read_to_string(&lock_path) { Ok(s) => s, Err(_) => return, }; let has_tokenizers = lock .lines() .any(|line| matches!(line.trim(), "name = \"tokenizers\"")); if !has_tokenizers { return; } if target_os == "windows" { panic!( "magnotia-transcription: the `tokenizers` crate appears in Cargo.lock and this is a \ Windows build. ..." ); } println!( "cargo:warning=magnotia-transcription: `tokenizers` crate is in the dependency graph. \ This build is non-Windows so the link will succeed, but Windows builds will panic ..." ); } ``` ## Data flow ``` cargo invoke └─ build.rs ├─ rerun-if-changed=build.rs ├─ ancestors().find(Cargo.lock) → workspace root ├─ rerun-if-changed=Cargo.lock ├─ scan for `name = "tokenizers"` └─ if found: target_os == windows? → panic!("brief item #6") else → cargo:warning ``` ## Watch-outs - **`rerun-if-changed=Cargo.lock` is the trigger.** Adding tokenizers without changing this crate's source still re-runs the script the next build because the lockfile changed. - **The string match is brittle on purpose.** Looking for the literal `name = "tokenizers"` line in `Cargo.lock` is what TOML pretty-prints. A future cargo version that emits the lockfile differently could miss this. Mitigation: keep the test simple and review on cargo upgrade. - **The non-Windows path is a warning, not an error.** A CI matrix job on Linux will pass with a yellow message; Windows will fail at build. Fine for a desktop project that ships from Linux first; surprising if anyone ever assumes "Linux green = ready to ship". - **Brief item #6 reference.** The panic message points at `docs/whisper-ecosystem/brief.md` item #6. Do not lose that pointer in any rewrite — the failure mode is non-obvious without the historical context. - **`workspace_root` walk falls back gracefully.** If no `Cargo.lock` is found in any ancestor (first-ever cargo run), the script returns early. Subsequent builds will pick up the lock. - **No way to override.** A maintainer who *wants* to ship `tokenizers` on Windows must delete this `build.rs`, or carry a sidecar process that links tokenizers in its own binary. There is no escape hatch env var. ## See also - [Transcription whisper](transcription-whisper.md) — `whisper-rs-sys` is the link target this guard protects. - [Cargo features](cargo-features.md) — same brief-item #6 family of decisions. - `docs/whisper-ecosystem/brief.md` — the full incident background.