fix(natives): pin cmake opus build to static MSVC CRT (/MT)

The win32 addon static-CRT switch enabled the static_link_msvcrt cc
feature, but audiopus_sys's bundled opus is built through the generated
CMake toolchain, which pinned CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL
(/MD) as authoritative under CMP0091 NEW. The opus objects could then
still emit /MD and pull VCRUNTIME140.dll / conflict with the static CRT
the rest of the addon links, leaving the outcome dependent on compile-
flag ordering.

Pin CMAKE_MSVC_RUNTIME_LIBRARY to MultiThreaded (static release /MT) in
the msvc toolchain.cmake so opus deterministically matches rustc's
+crt-static and the static_link_msvcrt feature.

Verified with a fully cold `bazel build //:natives-win32-x64-baseline`
(opus recompiled): the produced .node imports no VCRUNTIME140.dll and no
api-ms-win-crt-* — only core Windows system DLLs.

Fixes #8439
This commit is contained in:
roboomp
2026-08-13 16:21:23 +00:00
parent 246dda7f1c
commit 2e2bf1f3a5
3 changed files with 15 additions and 9 deletions
+2 -1
View File
@@ -102,7 +102,8 @@ exec hosts. Replaces cargo-xwin.
defaults to the Debug config → `/MDd` → `msvcrtd.lib`, which the lean splat
(like cargo-xwin's) does not carry; toolchain.cmake pins
`CMAKE_TRY_COMPILE_CONFIGURATION=Release`, `CMAKE_POLICY_DEFAULT_CMP0091=NEW`
and `CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL` (/MD everywhere).
and `CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded` (static release `/MT`
everywhere, matching the addon's static-CRT policy — issue #8439).
Verified on darwin: scratch `project(C)` + `add_executable` configures with
"Clang 20.1.7 with MSVC-like command-line" and links a valid PE32+ exe
through vs_link_exe with the wrapper rc/mt/linker.
+12 -7
View File
@@ -124,15 +124,20 @@ set(CMAKE_CXX_COMPILER "${CMAKE_CURRENT_LIST_DIR}/bin/clang-cl")
set(CMAKE_LINKER "${CMAKE_CURRENT_LIST_DIR}/bin/lld-link")
set(CMAKE_RC_COMPILER "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-rc")
set(CMAKE_MT "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-mt")
# The xwin splat carries release CRT import libs only (msvcrt.lib, no
# msvcrtd.lib — same as cargo-xwin). try_compile defaults to the Debug
# configuration, whose /MDd would demand the debug CRT; pin try_compile to
# Release and the runtime library to dynamic release /MD for every config
# (CMP0091 NEW makes CMAKE_MSVC_RUNTIME_LIBRARY authoritative even for
# projects with ancient cmake_minimum_required, e.g. bundled opus).
# The xwin splat carries release CRT import + static libs only (msvcrt.lib /
# libcmt.lib, no debug msvcrtd.lib / libcmtd.lib — same as cargo-xwin).
# try_compile defaults to the Debug configuration, whose debug CRT the splat
# lacks; pin try_compile to Release. The shipped win32 addon statically links
# the CRT (rustc +crt-static + the static_link_msvcrt cc feature; see
# bazel/defs.bzl and crates/pi-natives/BUILD.bazel), so pin the runtime library
# to the static release CRT /MT for every config as well — otherwise CMake's
# authoritative CMAKE_MSVC_RUNTIME_LIBRARY (CMP0091 NEW) would emit /MD for the
# bundled opus objects, which then import VCRUNTIME140.dll and conflict with the
# static CRT the rest of the addon links (issue #8439). Keep this in lock-step
# with the static_link_msvcrt feature: both must select the static CRT together.
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
"""
_BUILD = """\
+1 -1
View File
@@ -217,7 +217,7 @@ bazelisk build --nobuild //:natives-win32-x64-baseline
| rstest macro: "Cargo.toml not found" in a vendored test | rstest verifies `Cargo.toml` exists in the manifest dir | `compile_data = ["Cargo.toml"]` on the `rust_test` (see `crates/vendor/uu-tail/BUILD.bazel`) |
| vendored tests fail on bare `test_data/...` paths / symlink into srcs | tests assume cargo's cwd, incompatible with runfiles execution | `tags = ["manual"]`; run via `cargo nextest` when touching the fork; hermetic sibling test covers the contract |
| blake3 msvc: `ml64.exe` not found | cc-rs resolves MASM from build-script PATH on non-windows hosts | `bin/ml64.exe → llvm-ml -m64` shim in `@msvc_cc`, prepended via the `blake3` annotation PATH |
| audiopus_sys msvc: cmake demands VS generator / rc+mt tools; `try_compile` wants `msvcrtd.lib` | cross cmake on linux/mac hosts; Debug config → `/MDd` which the lean xwin splat lacks | `CMAKE_GENERATOR_x86_64_pc_windows_msvc=Ninja` + `@msvc_cc`'s `toolchain.cmake` (`CMAKE_TOOLCHAIN_FILE_x86_64_pc_windows_msvc`) pinning wrappers + Release try-compile + `/MD` |
| audiopus_sys msvc: cmake demands VS generator / rc+mt tools; `try_compile` wants `msvcrtd.lib` | cross cmake on linux/mac hosts; Debug config → `/MDd` which the lean xwin splat lacks | `CMAKE_GENERATOR_x86_64_pc_windows_msvc=Ninja` + `@msvc_cc`'s `toolchain.cmake` (`CMAKE_TOOLCHAIN_FILE_x86_64_pc_windows_msvc`) pinning wrappers + Release try-compile + `/MT` (static CRT, matches the addon policy) |
| win32 link oddities generally | — | read `bazel/toolchains/msvc/NOTES.md` first: wrapper self-location, `lld-link` flavor/driver-link behavior, `LIB`, `/MD` CRT choice, xwin splat caveats |
| `rust_test(crate = ...)` "can't find crate" at macro expansion | rmeta-only pipelined deps break macro_rules re-export harness compiles | rust pipelined_compilation stays OFF (`.bazelrc` note) |
| build script can't find cmake/ninja | `--incompatible_strict_action_env` — no host env leaks | explicit `PATH` in the crate annotation (`MODULE.bazel`), not host env |