From 01401ef6756c0876b775e0bcdd06064abc68697e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 23 Mar 2026 11:31:41 -0700 Subject: [PATCH] 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. --- CMakeLists.txt | 8 ++++++++ dist/cmake/ghostty-vt-config.cmake.in | 5 +++++ src/build/GhosttyLibVt.zig | 17 +++++++---------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf17d955f..cae5bdba7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ------------------------------------------------------------------ diff --git a/dist/cmake/ghostty-vt-config.cmake.in b/dist/cmake/ghostty-vt-config.cmake.in index 4d97a525c..8e1d75729 100644 --- a/dist/cmake/ghostty-vt-config.cmake.in +++ b/dist/cmake/ghostty-vt-config.cmake.in @@ -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) diff --git a/src/build/GhosttyLibVt.zig b/src/build/GhosttyLibVt.zig index fcc93e4c7..59e7a46e3 100644 --- a/src/build/GhosttyLibVt.zig +++ b/src/build/GhosttyLibVt.zig @@ -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()) {