build: fix Windows static lib linking with MSVC

Three issues when linking the static library with the MSVC linker:

Use the LLVM backend on Windows to produce valid COFF objects.
The self-hosted backend generates compiler_rt objects with invalid
COMDAT sections that the MSVC linker rejects (LNK1143).

Disable bundling ubsan_rt on Windows. Zig's ubsan runtime emits
/exclude-symbols linker directives that MSVC does not understand
(LNK4229).

Add ntdll and kernel32 as transitive link dependencies for the
static library on Windows. The Zig standard library uses NT API
functions (NtClose, NtCreateSection, etc.) that consumers must
link.
This commit is contained in:
Mitchell Hashimoto
2026-03-23 11:31:41 -07:00
parent 2c89bef860
commit 01401ef675
3 changed files with 20 additions and 10 deletions

View File

@@ -160,6 +160,14 @@ set_target_properties(ghostty-vt-static PROPERTIES
IMPORTED_LOCATION "${GHOSTTY_VT_STATIC_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${ZIG_OUT_DIR}/include"
)
if(WIN32)
# On Windows, the Zig standard library uses NT API functions
# (NtClose, NtCreateSection, etc.) and kernel32 functions that
# consumers must link when using the static library.
set_target_properties(ghostty-vt-static PROPERTIES
INTERFACE_LINK_LIBRARIES "ntdll;kernel32"
)
endif()
add_dependencies(ghostty-vt-static zig_build_lib_vt)
# --- Install ------------------------------------------------------------------

View File

@@ -53,6 +53,11 @@ if(NOT TARGET ghostty-vt::ghostty-vt-static)
IMPORTED_LOCATION "${_ghostty_vt_libdir}/@GHOSTTY_VT_STATIC_REALNAME@"
INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@"
)
if(WIN32)
set_target_properties(ghostty-vt::ghostty-vt-static PROPERTIES
INTERFACE_LINK_LIBRARIES "ntdll;kernel32"
)
endif()
endif()
unset(_ghostty_vt_libdir)

View File

@@ -94,20 +94,12 @@ fn initLib(
);
if (kind == .static) {
const is_windows = target.result.os.tag == .windows;
// These must be bundled since we're compiling into a static lib.
// Otherwise, you get undefined symbol errors. This could cause
// problems if you're linking multiple static Zig libraries but
// we'll cross that bridge when we get to it.
//
// On Windows, Zig's compiler_rt produces COFF objects with
// invalid COMDAT sections (LNK1143) and its ubsan_rt emits
// /exclude-symbols directives the MSVC linker rejects
// (LNK4229). Both are skipped since the MSVC CRT provides
// the needed builtins (memcpy, memset, etc.).
lib.bundle_compiler_rt = !is_windows;
lib.bundle_ubsan_rt = !is_windows;
lib.bundle_compiler_rt = true;
lib.bundle_ubsan_rt = true;
// Enable PIC so the static library can be linked into PIE
// executables, which is the default on most Linux distributions.
@@ -118,6 +110,11 @@ fn initLib(
// Zig's ubsan emits /exclude-symbols linker directives that
// are incompatible with the MSVC linker (LNK4229).
lib.bundle_ubsan_rt = false;
// The self-hosted backend produces COFF objects with invalid
// COMDAT sections in compiler_rt that the MSVC linker rejects
// (LNK1143). Use the LLVM backend to produce valid objects.
lib.use_llvm = true;
}
if (lib.rootModuleTarget().abi.isAndroid()) {