build: use linkLibC instead of linkLibCpp on MSVC targets

When compiling C++ files, Zig unconditionally passes -nostdinc++ and,
if link_libcpp is set, adds its bundled libc++/libc++abi include paths
as replacements (see Compilation.zig). On MSVC targets this conflicts
with the MSVC C++ runtime headers (vcruntime_typeinfo.h,
vcruntime_exception.h, etc.), causing compilation failures in SIMD
C++ code.

The fix is to use linkLibC instead of linkLibCpp on MSVC. Zig always
passes -nostdinc to strip default search paths, but LibCDirs.detect
re-adds the MSVC SDK include directories, which contain both C and
C++ standard library headers. This gives us proper access to MSVC's
own <optional>, <iterator>, <cstddef>, etc. without the libc++
conflicts.

For the package builds (highway, simdutf, utfcpp) this means
switching from linkLibCpp to linkLibC on MSVC. For SharedDeps and
GhosttyZig, linkLibC is already called separately, so we just skip
linkLibCpp.
This commit is contained in:
Mitchell Hashimoto
2026-03-23 12:05:57 -07:00
parent afa8f059e5
commit 3d581eb92e
5 changed files with 28 additions and 11 deletions

View File

@@ -20,8 +20,12 @@ pub fn build(b: *std.Build) !void {
}),
.linkage = .static,
});
// On MSVC, the C++ standard library is provided by the MSVC runtime
// and linking Zig's bundled libc++ would conflict with it.
lib.linkLibC();
// On MSVC, we must not use linkLibCpp because Zig unconditionally
// passes -nostdinc++ and then adds its bundled libc++/libc++abi
// include paths, which conflict with MSVC's own C++ runtime headers.
// The MSVC SDK include directories (added via linkLibC) contain
// both C and C++ headers, so linkLibCpp is not needed.
if (target.result.abi != .msvc) {
lib.linkLibCpp();
}

View File

@@ -12,8 +12,12 @@ pub fn build(b: *std.Build) !void {
}),
.linkage = .static,
});
// On MSVC, the C++ standard library is provided by the MSVC runtime
// and linking Zig's bundled libc++ would conflict with it.
lib.linkLibC();
// On MSVC, we must not use linkLibCpp because Zig unconditionally
// passes -nostdinc++ and then adds its bundled libc++/libc++abi
// include paths, which conflict with MSVC's own C++ runtime headers.
// The MSVC SDK include directories (added via linkLibC) contain
// both C and C++ headers, so linkLibCpp is not needed.
if (target.result.abi != .msvc) {
lib.linkLibCpp();
}

View File

@@ -12,8 +12,12 @@ pub fn build(b: *std.Build) !void {
}),
.linkage = .static,
});
// On MSVC, the C++ standard library is provided by the MSVC runtime
// and linking Zig's bundled libc++ would conflict with it.
lib.linkLibC();
// On MSVC, we must not use linkLibCpp because Zig unconditionally
// passes -nostdinc++ and then adds its bundled libc++/libc++abi
// include paths, which conflict with MSVC's own C++ runtime headers.
// The MSVC SDK include directories (added via linkLibC) contain
// both C and C++ headers, so linkLibCpp is not needed.
if (target.result.abi != .msvc) {
lib.linkLibCpp();
}