From 84254a9d8cb7d8bd28852933484be3f499cfbeee Mon Sep 17 00:00:00 2001 From: Riccardo Mazzarini Date: Sat, 25 Jul 2026 16:35:50 +0200 Subject: [PATCH] build: avoid MSVC C++ runtime in no-libcxx builds AI-assisted: Codex --- pkg/highway/build.zig | 7 +++++++ pkg/simdutf/build.zig | 14 ++++++++++---- src/build/GhosttyLibVt.zig | 11 ++++++++--- src/build/SharedDeps.zig | 5 +++++ src/lib_vt.zig | 11 +++++++++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/pkg/highway/build.zig b/pkg/highway/build.zig index fce823bf3..af3300eb3 100644 --- a/pkg/highway/build.zig +++ b/pkg/highway/build.zig @@ -99,6 +99,13 @@ pub fn build(b: *std.Build) !void { "-fmath-errno", "-fno-exceptions", }); + } else if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + // -fno-autolink also drops UCRT's /alternatename fallback. + "-D_Avx2WmemEnabledWeakValue=_Avx2WmemEnabled", + "-fno-autolink", + "-fno-stack-protector", + }); } lib.root_module.addCSourceFiles(.{ .flags = flags.items, .files = &.{ diff --git a/pkg/simdutf/build.zig b/pkg/simdutf/build.zig index a92fa3a07..3efc08263 100644 --- a/pkg/simdutf/build.zig +++ b/pkg/simdutf/build.zig @@ -50,10 +50,16 @@ pub fn build(b: *std.Build) !void { if (no_libcxx) { try flags.append(b.allocator, "-DSIMDUTF_NO_LIBCXX"); - if (target.result.abi != .msvc) { - // Clang/GCC-only flags; MSVC doesn't accept these. - try flags.append(b.allocator, "-fno-exceptions"); - try flags.append(b.allocator, "-fno-rtti"); + try flags.append(b.allocator, "-fno-exceptions"); + try flags.append(b.allocator, "-fno-rtti"); + if (target.result.abi == .msvc) { + try flags.appendSlice(b.allocator, &.{ + "-D_USE_STD_VECTOR_ALGORITHMS=0", + // -fno-autolink also drops UCRT's /alternatename fallback. + "-D_Avx2WmemEnabledWeakValue=_Avx2WmemEnabled", + "-fno-autolink", + "-fno-stack-protector", + }); } lib.root_module.addCMacro("SIMDUTF_NO_LIBCXX", "1"); diff --git a/src/build/GhosttyLibVt.zig b/src/build/GhosttyLibVt.zig index 389be4ef5..0ef7d6937 100644 --- a/src/build/GhosttyLibVt.zig +++ b/src/build/GhosttyLibVt.zig @@ -249,9 +249,14 @@ fn initLib( lib.bundle_ubsan_rt = false; if (kind == .static) { - // compiler_rt expects ntdll to provide _fltused when libc is - // linked, and the Zig standard library uses other NT and kernel32 - // symbols. + if (target.result.abi == .msvc) { + // Zig's compiler runtime doesn't provide MSVC's security + // cookie symbols when libc is linked. Disable stack-protector + // generation so static consumers don't need BufferOverflowU. + lib.root_module.stack_protector = false; + } + + // The Zig standard library uses NT and kernel32 symbols. lib.root_module.linkSystemLibrary("ntdll", .{}); lib.root_module.linkSystemLibrary("kernel32", .{}); } diff --git a/src/build/SharedDeps.zig b/src/build/SharedDeps.zig index f1ec7c9d5..0c1589842 100644 --- a/src/build/SharedDeps.zig +++ b/src/build/SharedDeps.zig @@ -991,6 +991,11 @@ pub fn addSimd( "-fno-sanitize=undefined", "-fno-sanitize-trap=undefined", }); + if (target.result.abi == .msvc) try flags.appendSlice(b.allocator, &.{ + // -fno-autolink also drops UCRT's /alternatename fallback. + "-D_Avx2WmemEnabledWeakValue=_Avx2WmemEnabled", + "-fno-autolink", + }); m.addCSourceFiles(.{ .files = &.{ diff --git a/src/lib_vt.zig b/src/lib_vt.zig index b4a2722bf..e49427409 100644 --- a/src/lib_vt.zig +++ b/src/lib_vt.zig @@ -12,6 +12,8 @@ const lib = @This(); const std = @import("std"); const builtin = @import("builtin"); +var msvc_fltused: c_int = 1; + // The public API below reproduces a lot of terminal/main.zig but // is separate because (1) we need our root file to be in `src/` // so we can access other directories and (2) we may want to withhold @@ -145,6 +147,15 @@ comptime { // If we're building the C library (vs. the Zig module) then // we want to reference the C API so that it gets exported. if (@import("root") == lib) { + // MSVC requires this marker whenever floating-point code is present. + // Zig's compiler_rt only provides it when libc is not linked. + if (builtin.os.tag == .windows and + builtin.abi == .msvc and + builtin.link_mode == .static) + { + @export(&msvc_fltused, .{ .name = "_fltused" }); + } + // Force-reference our memset override so its export is // emitted. This must stay inside the root guard so that // downstream Zig module consumers don't get the override