Skip to content

fix: Windows/MSVC build (5 build.rs bugs)#7

Open
zxcloli666 wants to merge 5 commits into
rust-hermes:mainfrom
zxcloli666:windows-cmake-generator-fix
Open

fix: Windows/MSVC build (5 build.rs bugs)#7
zxcloli666 wants to merge 5 commits into
rust-hermes:mainfrom
zxcloli666:windows-cmake-generator-fix

Conversation

@zxcloli666

Copy link
Copy Markdown

Got this building and running on Windows (MSVC 14.44 + Ninja, Windows 10 SDK) while wiring Hermes into a custom desktop runtime. libhermes-sys/build.rs had five separate bugs blocking it, all Windows-only in effect — Linux/macOS paths are either untouched or the change is a strict superset there.

  1. CMake generator conflict. -G Ninja was passed via configure_arg as a raw string instead of Config::generator("Ninja"). cmake-rs only recognizes Ninja through its own generator field — on MSVC targets it still assumes a Visual Studio generator and appends -Thost=x64 -Ax64, which conflicts with the real -G Ninja arg ("Generator Ninja does not support platform specification").

  2. binding.cc compiler flags. cc::Build used .flag("-std=c++17") / .flag("-fexceptions") / .flag("-frtti") — GCC/Clang spellings that cl.exe silently ignores (unrecognized --prefixed args just warn, they don't error). It compiles in whatever pre-C++17 mode MSVC defaults to and fails on structured bindings. Switched to .flag_if_supported() with both spellings (POSIX + /std:c++17 / /EHsc / /GR).

  3. Static archive discovery + system libs. The discovery walk only matched *.a; MSVC produces *.lib, so none of Hermes' own built libraries were ever linked. This was masked by a second bug in the same fallback: it unconditionally linked stdc++/icuuc/icui18n/icudata for anything that isn't macOS, and those names don't exist on Windows, so the linker died on a missing stdc++.lib before it ever got far enough to expose the first bug.

  4. Debug/release CRT mismatch. Once 3 was fixed, link failed on ~20 unresolved external symbol __imp__calloc_dbg (and friends). cmake-rs infers CMAKE_BUILD_TYPE from Cargo's profile ("Debug" for a plain cargo build), which under MSVC pulls in the debug CRT (/MDd) for Hermes' objects — but Rust's own linked output always expects the release CRT (/MD), regardless of --release. Forced .profile("Release") for the vendored build unconditionally; it's not something downstream crates ever edit, so building it unoptimized just to match the outer dev profile bought nothing.

  5. Missing Windows ICU/Winmm linkage. "Using Windows 10 built-in ICU" in the CMake log just means Hermes calls the same unorm2_* / ucol_* / udat_* / u_strTo* entry points ICU4C exposes, backed by the OS's icu.dll — it doesn't get baked into hermesvm_a.lib. Windows' import lib for it is named icu, not icuuc/icui18n/icudata. Also needed winmm for timeBeginPeriod/timeEndPeriod (sampling profiler).

Verified with a minimal crate depending on this branch: cargo build succeeds and the resulting binary evaluates JS correctly (1 + 2 -> 3).

…figure_arg

cmake-rs only recognizes Ninja through its own generator field; on MSVC
targets it otherwise assumes a Visual Studio generator and appends
-Thost=x64 -Ax64, which conflicts with a Ninja generator passed as a raw
configure_arg ("Generator Ninja does not support platform specification").
…r binding.cc

.flag() passes GCC/Clang spellings (-std=c++17, -fexceptions, -frtti)
straight through; cl.exe silently ignores unrecognized "-"-prefixed args
instead of erroring, so binding.cc compiled in a pre-C++17 mode under MSVC
and failed on structured bindings. flag_if_supported() probes the actual
compiler and applies whichever spelling (GCC/Clang or MSVC) it accepts.
…libs on Windows

Two compounding bugs in the same linking step, the first masking the
second: (1) the static-archive discovery walk only matched "*.a" files,
so on MSVC (which produces "*.lib") it silently linked none of Hermes'
own built libraries at all; (2) the system-library fallback branch
unconditionally added "stdc++"/"icuuc"/"icui18n"/"icudata", which
don't exist under those names on Windows and made the linker fail before
ever reaching a symbol-resolution error that would have surfaced bug (1).
…elease

cmake-rs infers CMAKE_BUILD_TYPE from cargo's own profile ("Debug" for a
plain cargo build). Under MSVC that pulls in CMake's default /MDd (debug
CRT) flags for Hermes' object files, while Rust's linked output always
expects the release CRT (/MD) regardless of --release — the mismatch
surfaces as dozens of unresolved __imp__calloc_dbg (and other debug-CRT
symbols) at final link. Force Release unconditionally: a vendored C++ VM
built unoptimized to match our own dev profile buys nothing (we never
edit it) and would just be slower to run.
CMake reporting "Using Windows 10 built-in ICU" only means
PlatformUnicodeICU.cpp calls the same unorm2_*/ucol_*/udat_*/u_str*
symbols ICU4C exposes, backed by the OS's icu.dll instead of a vendored
ICU — it doesn't embed that linkage into hermesvm_a.lib, and Windows'
import library is named "icu", not "icuuc"/"icui18n"/"icudata"
(those are POSIX ICU4C names). SamplingProfilerSampler.cpp's high-res
timer also needs winmm's timeBeginPeriod/timeEndPeriod.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant