Merge PR #8443: fix(natives): static-link win32 MSVC CRT so addon needs no VC++ redist (@roboomp)
This commit is contained in:
+14
-1
@@ -16,19 +16,32 @@ _ADDON_RUSTC_FLAGS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
def _addon_transition_impl(settings, attr):
|
def _addon_transition_impl(settings, attr):
|
||||||
|
# Statically link the MSVC CRT for the shipped win32 addon: rustc gets
|
||||||
|
# +crt-static via the crate's rustc_flags select, and the C dependencies
|
||||||
|
# (opus/cmake, tree-sitter, blake3, ring) must move to /MT in lock-step so
|
||||||
|
# the final .node imports no VCRUNTIME140.dll from the Visual C++
|
||||||
|
# Redistributable (absent on a clean Windows install -> dlopen error 126).
|
||||||
|
# The static_link_msvcrt cc feature flips the toolchain compile flags that
|
||||||
|
# rules_rust forwards to cc-rs/cmake as CFLAGS/CXXFLAGS; it is inert for the
|
||||||
|
# zig/darwin toolchains, so scoping it to win32 is belt-and-suspenders.
|
||||||
|
features = list(settings["//command_line_option:features"])
|
||||||
|
if "win32" in str(attr.platform):
|
||||||
|
features = features + ["static_link_msvcrt"]
|
||||||
return {
|
return {
|
||||||
"//command_line_option:platforms": str(attr.platform),
|
"//command_line_option:platforms": str(attr.platform),
|
||||||
"//command_line_option:compilation_mode": "opt",
|
"//command_line_option:compilation_mode": "opt",
|
||||||
|
"//command_line_option:features": features,
|
||||||
"@rules_rust//rust/settings:lto": "thin",
|
"@rules_rust//rust/settings:lto": "thin",
|
||||||
"@rules_rust//rust/settings:extra_rustc_flags": _ADDON_RUSTC_FLAGS,
|
"@rules_rust//rust/settings:extra_rustc_flags": _ADDON_RUSTC_FLAGS,
|
||||||
}
|
}
|
||||||
|
|
||||||
_addon_transition = transition(
|
_addon_transition = transition(
|
||||||
implementation = _addon_transition_impl,
|
implementation = _addon_transition_impl,
|
||||||
inputs = [],
|
inputs = ["//command_line_option:features"],
|
||||||
outputs = [
|
outputs = [
|
||||||
"//command_line_option:platforms",
|
"//command_line_option:platforms",
|
||||||
"//command_line_option:compilation_mode",
|
"//command_line_option:compilation_mode",
|
||||||
|
"//command_line_option:features",
|
||||||
"@rules_rust//rust/settings:lto",
|
"@rules_rust//rust/settings:lto",
|
||||||
"@rules_rust//rust/settings:extra_rustc_flags",
|
"@rules_rust//rust/settings:extra_rustc_flags",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -22,9 +22,16 @@ exec hosts. Replaces cargo-xwin.
|
|||||||
work from Bazel actions (cwd = execroot) *and* from build scripts, where
|
work from Bazel actions (cwd = execroot) *and* from build scripts, where
|
||||||
rules_rust `${pwd}`-expands `CC`/`AR` to absolute paths and cc-rs/cmake spawn
|
rules_rust `${pwd}`-expands `CC`/`AR` to absolute paths and cc-rs/cmake spawn
|
||||||
tools from other cwds.
|
tools from other cwds.
|
||||||
- **CRT: dynamic `/MD`** (rules_cc's msvc branch default outside `dbg` without
|
- **CRT: static `/MT` for the shipped addon.** The toolchain *default* is
|
||||||
the `static_link_msvcrt` feature) — matches what napi/cc-rs produced under
|
dynamic `/MD` (rules_cc's msvc branch default outside `dbg` without the
|
||||||
cargo-xwin (rust msvc targets default to dynamic CRT without `+crt-static`).
|
`static_link_msvcrt` feature), matching what napi/cc-rs produced under
|
||||||
|
cargo-xwin. But `//:natives-win32-x64-baseline` overrides to static CRT:
|
||||||
|
`-Ctarget-feature=+crt-static` for rustc (crate BUILD select) plus the
|
||||||
|
`static_link_msvcrt` cc feature (enabled for win32 in the `native_addon`
|
||||||
|
transition, `bazel/defs.bzl`) so the C deps compile `/MT` in lock-step.
|
||||||
|
Without this the `.node` imports `VCRUNTIME140.dll` from the Visual C++
|
||||||
|
Redistributable, which is absent on a clean Windows install and makes the
|
||||||
|
loader's dlopen fail with error 126 (issue #8439).
|
||||||
- **SSE floor in the wrapper, not annotations**: `-msse4.1 -msse4.2` live in the
|
- **SSE floor in the wrapper, not annotations**: `-msse4.1 -msse4.2` live in the
|
||||||
clang-cl wrapper, which only ever targets win32-x64 (baseline = x86-64-v2 ⊇
|
clang-cl wrapper, which only ever targets win32-x64 (baseline = x86-64-v2 ⊇
|
||||||
SSE4.2). This is the old build-native.ts CFLAGS hack, windows-only by
|
SSE4.2). This is the old build-native.ts CFLAGS hack, windows-only by
|
||||||
@@ -95,7 +102,8 @@ exec hosts. Replaces cargo-xwin.
|
|||||||
defaults to the Debug config → `/MDd` → `msvcrtd.lib`, which the lean splat
|
defaults to the Debug config → `/MDd` → `msvcrtd.lib`, which the lean splat
|
||||||
(like cargo-xwin's) does not carry; toolchain.cmake pins
|
(like cargo-xwin's) does not carry; toolchain.cmake pins
|
||||||
`CMAKE_TRY_COMPILE_CONFIGURATION=Release`, `CMAKE_POLICY_DEFAULT_CMP0091=NEW`
|
`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
|
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
|
"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.
|
through vs_link_exe with the wrapper rc/mt/linker.
|
||||||
@@ -103,8 +111,9 @@ exec hosts. Replaces cargo-xwin.
|
|||||||
## What to verify on can.internal (linux-x64)
|
## What to verify on can.internal (linux-x64)
|
||||||
|
|
||||||
1. `bazel build //:natives-win32-x64-baseline` end-to-end link; check the
|
1. `bazel build //:natives-win32-x64-baseline` end-to-end link; check the
|
||||||
produced `pi_natives.win32-x64-baseline.node` imports (dumpbin/llvm-readobj:
|
produced `pi_natives.win32-x64-baseline.node` imports (dumpbin/llvm-readobj):
|
||||||
expect VCRUNTIME140/api-ms-win-crt-* → `/MD`, no static CRT).
|
expect **no** `VCRUNTIME140.dll` and **no** `api-ms-win-crt-*` (static CRT);
|
||||||
|
only core Windows system DLLs (kernel32, ntdll, advapi32, …) should remain.
|
||||||
2. LLVM 20.1.7 Linux-X64 binaries are built on a newish Ubuntu: confirm the
|
2. LLVM 20.1.7 Linux-X64 binaries are built on a newish Ubuntu: confirm the
|
||||||
kata runner image's glibc is ≥ 2.35-ish and has `libtinfo6`/`libstdc++6`
|
kata runner image's glibc is ≥ 2.35-ish and has `libtinfo6`/`libstdc++6`
|
||||||
(usual LLVM release-binary runtime deps).
|
(usual LLVM release-binary runtime deps).
|
||||||
|
|||||||
@@ -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_LINKER "${CMAKE_CURRENT_LIST_DIR}/bin/lld-link")
|
||||||
set(CMAKE_RC_COMPILER "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-rc")
|
set(CMAKE_RC_COMPILER "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-rc")
|
||||||
set(CMAKE_MT "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-mt")
|
set(CMAKE_MT "${CMAKE_CURRENT_LIST_DIR}/bin/llvm-mt")
|
||||||
# The xwin splat carries release CRT import libs only (msvcrt.lib, no
|
# The xwin splat carries release CRT import + static libs only (msvcrt.lib /
|
||||||
# msvcrtd.lib — same as cargo-xwin). try_compile defaults to the Debug
|
# libcmt.lib, no debug msvcrtd.lib / libcmtd.lib — same as cargo-xwin).
|
||||||
# configuration, whose /MDd would demand the debug CRT; pin try_compile to
|
# try_compile defaults to the Debug configuration, whose debug CRT the splat
|
||||||
# Release and the runtime library to dynamic release /MD for every config
|
# lacks; pin try_compile to Release. The shipped win32 addon statically links
|
||||||
# (CMP0091 NEW makes CMAKE_MSVC_RUNTIME_LIBRARY authoritative even for
|
# the CRT (rustc +crt-static + the static_link_msvcrt cc feature; see
|
||||||
# projects with ancient cmake_minimum_required, e.g. bundled opus).
|
# 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_TRY_COMPILE_CONFIGURATION Release)
|
||||||
set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)
|
set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
|
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_BUILD = """\
|
_BUILD = """\
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ rust_shared_library(
|
|||||||
# cdylib at all; napi musl addons have always linked the dynamic CRT.
|
# cdylib at all; napi musl addons have always linked the dynamic CRT.
|
||||||
"//bazel/triples:x86_64-unknown-linux-musl": ["-Ctarget-feature=-crt-static"],
|
"//bazel/triples:x86_64-unknown-linux-musl": ["-Ctarget-feature=-crt-static"],
|
||||||
"//bazel/triples:aarch64-unknown-linux-musl": ["-Ctarget-feature=-crt-static"],
|
"//bazel/triples:aarch64-unknown-linux-musl": ["-Ctarget-feature=-crt-static"],
|
||||||
|
# Statically link the MSVC CRT so the shipped .node does not import
|
||||||
|
# VCRUNTIME140.dll from the Visual C++ Redistributable, which is absent
|
||||||
|
# on a clean Windows install and makes the loader's dlopen fail with
|
||||||
|
# "The specified module could not be found" (error 126). The C deps are
|
||||||
|
# switched to /MT in lock-step via the static_link_msvcrt cc feature in
|
||||||
|
# the native_addon transition (bazel/defs.bzl).
|
||||||
|
"//bazel/triples:x86_64-pc-windows-msvc": ["-Ctarget-feature=+crt-static"],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
version = "17.1.5",
|
version = "17.1.5",
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Notes:
|
|||||||
|
|
||||||
This mirrors the old cargo `ci` profile. Because the profile lives **in the transition**, a bare `bazel build //:natives-<t>` is always release-grade regardless of `-c`, and every addon shares one cache entry per (platform, source) pair. The rule then symlinks the produced shared library to the loader's canonical `pi_natives.<platform>-<arch>[-<variant>].node` name, scoped under the rule name (`bazel-bin/natives-<t>/…`) so gnu/musl outputs with identical basenames cannot collide at the package level.
|
This mirrors the old cargo `ci` profile. Because the profile lives **in the transition**, a bare `bazel build //:natives-<t>` is always release-grade regardless of `-c`, and every addon shares one cache entry per (platform, source) pair. The rule then symlinks the produced shared library to the loader's canonical `pi_natives.<platform>-<arch>[-<variant>].node` name, scoped under the rule name (`bazel-bin/natives-<t>/…`) so gnu/musl outputs with identical basenames cannot collide at the package level.
|
||||||
|
|
||||||
Per-target codegen that is not part of the transition lives in `crates/pi-natives/BUILD.bazel` `rustc_flags` selects: `-Ctarget-cpu=x86-64-v2` (baseline) / `x86-64-v3` (modern) via `//bazel/variants`, the napi link args (`-Wl,-undefined,dynamic_lookup` on macOS, `-Wl,-z,nodelete` on linux — `build.rs`/`napi_build::setup()` is deliberately not wired in), and `-Ctarget-feature=-crt-static` for musl.
|
Per-target codegen that is not part of the transition lives in `crates/pi-natives/BUILD.bazel` `rustc_flags` selects: `-Ctarget-cpu=x86-64-v2` (baseline) / `x86-64-v3` (modern) via `//bazel/variants`, the napi link args (`-Wl,-undefined,dynamic_lookup` on macOS, `-Wl,-z,nodelete` on linux — `build.rs`/`napi_build::setup()` is deliberately not wired in), `-Ctarget-feature=-crt-static` for musl, and `-Ctarget-feature=+crt-static` for win32-x64 msvc (paired with the `static_link_msvcrt` cc feature enabled in the `native_addon` transition so the C deps compile `/MT` in lock-step — the shipped `.node` then imports no `VCRUNTIME140.dll` from the VC++ Redistributable).
|
||||||
|
|
||||||
### 3) Platforms and toolchains
|
### 3) Platforms and toolchains
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ Per-target codegen that is not part of the transition lives in `crates/pi-native
|
|||||||
| linux gnu (x64/arm64) | `@zig_sdk//libc_aware/toolchain:linux_*_gnu.2.17` (hermetic zig cc) | glibc **2.17** portability floor — same floor the previous cross builds used |
|
| linux gnu (x64/arm64) | `@zig_sdk//libc_aware/toolchain:linux_*_gnu.2.17` (hermetic zig cc) | glibc **2.17** portability floor — same floor the previous cross builds used |
|
||||||
| linux musl (x64/arm64) | `@zig_sdk//libc_aware/toolchain:linux_*_musl` | dynamic CRT (`-Ctarget-feature=-crt-static` in the crate BUILD) |
|
| linux musl (x64/arm64) | `@zig_sdk//libc_aware/toolchain:linux_*_musl` | dynamic CRT (`-Ctarget-feature=-crt-static` in the crate BUILD) |
|
||||||
| darwin (x64/arm64) | host Xcode toolchain | Apple frameworks aren't redistributable; darwin addons build on mac hosts only |
|
| darwin (x64/arm64) | host Xcode toolchain | Apple frameworks aren't redistributable; darwin addons build on mac hosts only |
|
||||||
| win32-x64 msvc | `//bazel/toolchains/msvc` (`@msvc_cc`): clang-cl + lld-link + xwin CRT/SDK | hermetic cross-link from linux-x64 CI pods and darwin dev hosts; see `bazel/toolchains/msvc/NOTES.md` |
|
| win32-x64 msvc | `//bazel/toolchains/msvc` (`@msvc_cc`): clang-cl + lld-link + xwin CRT/SDK | hermetic cross-link from linux-x64 CI pods and darwin dev hosts; **static CRT** (`+crt-static` + `static_link_msvcrt`) so the addon needs no VC++ Redistributable; see `bazel/toolchains/msvc/NOTES.md` |
|
||||||
|
|
||||||
Rust toolchains are nightly (pinned in `MODULE.bazel`), with repo-local musl re-registrations in `//bazel/toolchains` carrying an explicit `@zig_sdk//libc:musl` constraint (rules_rust's generated gnu and musl toolchains otherwise share (os, cpu) constraints).
|
Rust toolchains are nightly (pinned in `MODULE.bazel`), with repo-local musl re-registrations in `//bazel/toolchains` carrying an explicit `@zig_sdk//libc:musl` constraint (rules_rust's generated gnu and musl toolchains otherwise share (os, cpu) constraints).
|
||||||
|
|
||||||
@@ -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`) |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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) |
|
| `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 |
|
| 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 |
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `omp` failing to start on a clean Windows install with `Failed to load pi_natives native addon for win32-x64 ... The specified module could not be found` (LoadLibrary error 126). The shipped win32-x64 addon linked the dynamic MSVC CRT (`/MD`) and imported `VCRUNTIME140.dll` from the Visual C++ Redistributable, which is absent on a fresh Windows install. The addon now statically links the CRT (`+crt-static` for rustc plus the `static_link_msvcrt` cc feature for its C dependencies), so the `.node` imports only core Windows system DLLs ([#8439](https://github.com/can1357/oh-my-pi/issues/8439)).
|
||||||
|
|
||||||
## [17.3.0] - 2026-08-13
|
## [17.3.0] - 2026-08-13
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
Reference in New Issue
Block a user