Commit Graph

15500 Commits

Author SHA1 Message Date
Alessandro De Blasis
4df71bcad7 build: fix zlib compilation on Windows with MSVC
Gate Z_HAVE_UNISTD_H behind a non-Windows check since unistd.h does
not exist on Windows. Add _CRT_SECURE_NO_DEPRECATE and
_CRT_NONSTDC_NO_DEPRECATE for MSVC to suppress deprecation errors
for standard C functions that zlib uses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 08:02:50 +01:00
Mitchell Hashimoto
d4a38c8661 cmake: add import library to custom command OUTPUT (#11794)
# What 

PR #11756 added IMPORTED_IMPLIB pointing to the .lib import library, but
the
import library is not listed in the OUTPUT directive of the
`add_custom_command`
that runs zig build. The file is produced as a side-effect of the build.

This works with the Visual Studio generator (which is lenient about
undeclared outputs) but fails with Ninja:

ninja: error: 'zig-out/lib/ghostty-vt.lib', needed by 'ghostling',
missing and no known rule to make it

The fix adds "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_IMPLIB}" to the OUTPUT
list. No
behavioral change. The file was already being built, Ninja just needs to
know
about it.

## but_why.gif

I am cleaning up https://github.com/ghostty-org/ghostling/pull/6 and I
realise that in order to get rid of the CMake workarounds we had before
#11756, this change is necessary.

# POC

I set up a branch pointing at my fork with a POC and it builds, this is
the cleaned up CMakeList
https://github.com/deblasis/winghostling/blob/test/cmake-implib-no-workaround/CMakeLists.txt
2026-03-23 21:04:48 -07:00
Alessandro De Blasis
7d31d9b57f cmake: add import library to custom command OUTPUT
Ninja requires all produced files to be listed as explicit outputs of
custom commands. The zig build produces a .lib import library alongside
the DLL, but it was not listed in the OUTPUT directive. This causes
Ninja to fail with "missing and no known rule to make it" when
IMPORTED_IMPLIB references the .lib file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 04:23:24 +01:00
Jeffrey C. Ollie
c584f87b90 build(deps): bump cachix/install-nix-action from 31.10.1 to 31.10.2 (#11790)
Bumps
[cachix/install-nix-action](https://github.com/cachix/install-nix-action)
from 31.10.1 to 31.10.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cachix/install-nix-action/releases">cachix/install-nix-action's
releases</a>.</em></p>
<blockquote>
<h2>v31.10.2</h2>
<h2>What's Changed</h2>
<ul>
<li>nix: 2.34.1 -&gt; 2.34.2 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/cachix/install-nix-action/pull/270">cachix/install-nix-action#270</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cachix/install-nix-action/compare/v31...v31.10.2">https://github.com/cachix/install-nix-action/compare/v31...v31.10.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="51f3067b56"><code>51f3067</code></a>
Revert &quot;ci: use 25.11 for channel tests&quot;</li>
<li><a
href="15118c17f9"><code>15118c1</code></a>
ci: use 25.11 for channel tests</li>
<li><a
href="e1ac057965"><code>e1ac057</code></a>
Merge pull request <a
href="https://redirect.github.com/cachix/install-nix-action/issues/270">#270</a>
from cachix/create-pull-request/patch</li>
<li><a
href="d181b9642f"><code>d181b96</code></a>
nix: 2.34.1 -&gt; 2.34.2</li>
<li>See full diff in <a
href="1ca7d21a94...51f3067b56">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cachix/install-nix-action&package-manager=github_actions&previous-version=31.10.1&new-version=31.10.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2026-03-23 20:44:57 -05:00
ghostty-vouch[bot]
846599b97e Update VOUCHED list (#11791)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11460#discussioncomment-16285158)
from @00-kat.

Vouch: @viruslobster

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-24 01:20:46 +00:00
dependabot[bot]
147596d560 build(deps): bump cachix/install-nix-action from 31.10.1 to 31.10.2
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.10.1 to 31.10.2.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](1ca7d21a94...51f3067b56)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-version: 31.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-24 00:12:58 +00:00
Mitchell Hashimoto
67db6b8960 libghostty: add ghostty_free for cross-runtime memory safety (#11785)
## What

On Windows, calling `free()` on memory allocated by libghostty crashes
because Zig and MSVC use separate heaps.

This adds `ghostty_free()` so consumers can free library-allocated
memory safely on all platforms.

## Why

When Zig builds a DLL on Windows with `link_libc = true`, it does not
link the Windows C runtime (`ucrtbase.dll`). Instead it uses its own
libc built on top of `KERNEL32.dll`. So `builtin.link_libc` is true and
`c_allocator` is selected, but Zig's `malloc` and MSVC's `malloc` are
different implementations with different heaps. 💥

On Linux/macOS this is not a problem because Zig links the system libc
and everyone shares the same heap. On Windows, `free(buf)` from MSVC
tries to free memory from Zig's heap and you get a debug assertion
failure or undefined behavior.

The `format_alloc` docs said "the buffer can be freed with `free()`" but
that is only true when the library and consumer share the same C
runtime, which is not the case on Windows.

## How

- Add `ghostty_free(allocator, ptr, len)` that frees through the same
allocator that did the allocation
- Update `format_alloc` docs to point to `ghostty_free()` instead of
`free()`
- Update all 3 examples to use `ghostty_free(NULL, buf, len)`

The signature takes an allocator because raw buffers (unlike objects
like terminals or formatters) do not store their allocator internally.
The caller already has all three values: the allocator they passed, the
pointer, and the length they got back.

I went back and forth on the naming. Other options I considered:
`ghostty_alloc_free(allocator, ptr, len)` or returning a `GhosttyBuffer`
wrapper with its own `_free`. Happy to change the naming if there is a
preference.

No impact on Linux/macOS. `ghostty_free()` works correctly there too, it
just happens to call the same `free()` the consumer would have called
anyway.

## Verified

- `zig build test-lib-vt` passes on Windows, macOS arm64, Linux x86_64
(exit 0)
- `zig build test` passes on Windows (2575/2619 passed, 1 pre-existing
font sprite failure) and macOS (exit 0)
- cmake shared example builds, links, and runs correctly on Windows with
`ghostty_free()` (no more heap crash)

## What I Learnt

- What I wrote in Why
- Zig allocators require the length to free (no hidden metadata headers
like C's malloc). This is a deliberate design choice for explicit
control.
- The standard pattern for C libraries on Windows is "whoever allocates,
frees" (like `curl_free()`, `SDL_free()`). This avoids cross-runtime
heap issues entirely.
2026-03-23 16:23:10 -07:00
Mitchell Hashimoto
b819ce0e20 vt: add ghostty_alloc for buffer allocation
Add a ghostty_alloc function that pairs with the existing
ghostty_free, giving embedders a symmetric malloc/free-style
API for buffer allocation through the libghostty allocator
interface. Returns NULL on allocation failure.
2026-03-23 16:12:29 -07:00
Mitchell Hashimoto
7039f566bb vt: move free_alloc to dedicated allocator.zig
Extract the inline free_alloc function from main.zig into a new
allocator.zig module in the C API layer. The function is renamed
to alloc_free in main.zig (and free in allocator.zig) for
consistency with the other C API naming conventions. Add tests
for null pointer, allocated memory, and null allocator fallback.
2026-03-23 16:08:32 -07:00
Mitchell Hashimoto
69104fb1f0 libghostty: introduce optional "effects" to handle queries and side effects for terminals (#11787)
Renames `ReadonlyStream` to `TerminalStream` and introduces an
effects-based callback system so that the stream handler can optionally
respond to queries and side effects (bell, title changes, device
attributes, device status, size reports, XTVERSION, ENQ, DECRQM, kitty
keyboard queries).

The default behavior is still read-only, callers have to opt-in to
setting callbacks to function pointers.

This doesn't handle every possible side effect yet, e.g. this doesn't
include clipboards, pwd reporting, and others. But this covers the
important ones.

This PR is Zig only, the C version of this will come later.
2026-03-23 15:30:18 -07:00
Mitchell Hashimoto
701d1d55d2 terminal: fix secondary DA test to match default firmware version
The default firmware_version for Secondary device attributes is 0,
but the test expected a value of 10. Update the test expectation to
match the actual default.
2026-03-23 15:02:13 -07:00
Mitchell Hashimoto
ba3f9bb400 terminal: port device_attributes to stream_terminal Effects
Add a device_attributes effect callback to the stream_terminal
Handler. The callback returns a device_attributes.Attributes
struct which the handler encodes and writes back to the pty.

Add Attributes.encode which dispatches to the correct sub-type
encoder based on the request type (primary, secondary, tertiary).

In readonly mode the callback is null so all DA queries are
silently ignored, matching the previous behavior where
device_attributes was in the ignored actions list.

Tests cover all three DA types with default attributes, custom
attributes, and readonly mode.
2026-03-23 14:55:04 -07:00
Mitchell Hashimoto
b31dcf9a4c terminal: add device_attributes module
Introduce a dedicated device_attributes.zig module that consolidates
all device attribute types and encoding logic. This moves
DeviceAttributeReq out of ansi.zig and adds structured response
types for DA1 (primary), DA2 (secondary), and DA3 (tertiary) with
self-encoding methods.

Primary DA uses a ConformanceLevel enum covering VT100-series
per-model values and VT200+ conformance levels, plus a Feature
enum with all known xterm DA1 attribute codes (132-col, printer,
sixel, color, clipboard, etc.) as a simple slice. Secondary DA
uses a DeviceType enum matching the xterm decTerminalID values.
Tertiary DA encodes the DECRPTUI unit ID as a u32 formatted to
8 hex digits.

This is preparatory work for exposing device attributes through
the stream_terminal Effects callback system.
2026-03-23 14:50:26 -07:00
Mitchell Hashimoto
2e7aa047af terminal: port device_status to stream_terminal Effects
Previously device_status was in the ignored "no terminal-modifying
effect" group in stream_terminal.zig. This ports it to use the
Effects pattern, handling all three DSR request types.

Operating status and cursor position are handled entirely within
stream_terminal since they only need terminal state and write_pty.
Cursor position respects origin mode and scrolling region offsets.

Color scheme adds a new color_scheme effect callback that returns
a ColorScheme enum (light/dark). The handler encodes the response
internally, keeping protocol knowledge in the terminal layer. A
new ColorScheme type is added to device_status.zig so the terminal
layer does not depend on apprt.
2026-03-23 14:31:47 -07:00
Mitchell Hashimoto
165e03669c terminal: port enquiry to Effects
Previously the ENQ (0x05) action was ignored in stream_terminal,
listed in the no-op group alongside other unhandled queries. The
real implementation in termio/stream_handler writes a configurable
response string back to the pty.

Add an enquiry callback to Effects following the same query-style
pattern as xtversion: the callback returns the raw response bytes
and the handler owns writing them to the pty via writePty. When no
callback is set (readonly mode), ENQ is silently ignored. Empty
responses are also ignored. The response is capped at 256 bytes
using a stack buffer with sentinel conversion for writePty.
2026-03-23 14:25:25 -07:00
Mitchell Hashimoto
2fe89c340a windows: fix XDG-related test failures on Windows (#11783)
## What

Two fixes for tests that fail on Windows due to Unix-specific
assumptions.

1. The "cache directory paths" test in xdg.zig hardcodes Unix paths like
`/Users/test/.cache` in expected values. The function under test uses
`std.fs.path.join` which produces native separators, so the expectations
need to match. Fixed by using `std.fs.path.join` for expected values
too, with a platform-appropriate mock home path.

2. Two shell integration tests for `setupXdgDataDirs` hardcode Unix path
separators (`:`) and Unix default paths (`/usr/local/share:/usr/share`).
These are not applicable on Windows where the delimiter is `;` and
`XDG_DATA_DIRS` is not a standard concept. Skipped on Windows with
`SkipZigTest`.


## Why skip instead of fix for the shell integration tests?

`setupXdgDataDirs` is used by fish, elvish, and nushell. On Windows,
`XDG_DATA_DIRS` is not standard. The equivalent would be `%ProgramData%`
(what Go's `adrg/xdg`, Python's `platformdirs`, and others map to).
Fixing this properly means adding a Windows-appropriate default, which
is a separate change. (How do you guys deal with these situations? Do
you create issues on the spot as reminders or do you wait for the
requirement to emerge by itself when the time comes?

Worth noting: the production code on line 664 of `shell_integration.zig`
hardcodes the fallback to `"/usr/local/share:/usr/share"` with `:`
separators, while `prependEnv` correctly uses `std.fs.path.delimiter`
(`;` on Windows). If a shell that uses this runs on Windows, you would
get mixed separators. Tracked separately.

## Verified

- `zig build test-lib-vt` passes on Windows (exit 0)
- No behavior change on Linux/macOS (xdg.zig fix produces same paths,
shell_integration skip only triggers on Windows)

## What I Learnt

- `std.fs.path.join` uses the native path separator, so tests that
hardcode `/` in expected paths will fail on Windows even if the
production code is correct. Better to use `path.join` in test
expectations too.
- The XDG Base Directory spec is Unix-only but cross-platform libraries
have converged on mappings. Ghostty maps to `%LOCALAPPDATA%` which
matches common conventions. The missing piece is `XDG_DATA_DIRS` which
has no Windows default and falls through to Unix paths.
2026-03-23 14:20:02 -07:00
Mitchell Hashimoto
b9669e10c4 fuzz: update stream fuzzer to use TerminalStream
ReadonlyStream was removed from the public API. Update the stream
fuzzer to use TerminalStream, which is the type now returned by
Terminal.vtStream().
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
6083e9f80b terminal: expose size_report via stream_terminal effects
Add a `size` callback to the stream_terminal Effects struct that
returns a size_report.Size geometry snapshot for XTWINOPS size
queries (CSI 14/16/18 t). The handler owns all protocol encoding
using the existing size_report.encode, keeping VT knowledge out
of effect consumers. This follows the same pattern as the xtversion
effect: the callback supplies data, the handler formats the reply
and calls write_pty.

CSI 21 t (title report) is handled internally from terminal state
since the title is already available via terminal.getTitle() and
does not require an external callback.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
26c81b4b0e terminal: add xtversion effect to stream_terminal
Add an xtversion callback to the Effects struct so that
stream_terminal can respond to XTVERSION queries. The callback
returns the version string to embed in the DCS response. If the
callback is unset or returns an empty string, the response defaults
to "libghostty". The response is formatted and written back via the
existing write_pty effect.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
134516310d terminal: implement kitty_keyboard_query in stream_terminal
Previously kitty_keyboard_query was listed as a no-op in the
readonly stream handler. This implements it using the write_pty
effect callback so that the current kitty keyboard flags are
reported back via the pty, matching the behavior in the full
stream handler.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
22c7edf3f8 terminal: rename set_window_title effect to title_changed
The effect callback no longer receives the title string directly.
Instead, the handler stores the title in terminal state via setTitle
before invoking the callback, so consumers query it through
handler.terminal.getTitle(). This removes the redundant parameter
and keeps the effect signature consistent with the new terminal
title field. Tests now verify terminal state directly rather than
tracking the title through the callback.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
08a44d7e69 terminal: store title set by escape sequences
Add a title field to Terminal, mirroring the existing pwd field.
The title is set via setTitle/getTitle and tracks the most recent
value written by OSC 0/2 sequences. The stream handler now persists
the title in terminal state in addition to forwarding it to the
surface. The field is cleared on full reset.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
6366ce9a22 terminal: add set_window_title effect to stream handler
Previously the window_title action was silently ignored in the
readonly stream handler. Add a set_window_title callback to the
Effects struct so callers can be notified when a window title is
set via OSC 2. Follows the same pattern as bell and write_pty
where the callback is optional and defaults to null in readonly
mode.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
e24cc1b53b terminal: add write_pty effect and implement DECRQM
Add a generic write_pty effect callback to the stream terminal
handler, allowing callers to receive pty response data. Use it to
implement request_mode and request_mode_unknown (DECRQM), which
encode the mode state as a DECRPM response and write it back
through the callback. Previously these were silently ignored.

The write_pty data is stack-allocated and only valid for the
duration of the call.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
67d8d86efd terminal: rename ReadonlyStream to TerminalStream
Rename stream_readonly.zig to stream_terminal.zig and its exported
types from ReadonlyStream/ReadonlyHandler to TerminalStream. The
"readonly" name is now wrong since the handler now supports
settable effects callbacks. The new name better reflects that this
is a stream handler for updating terminal state.
2026-03-23 14:17:10 -07:00
Mitchell Hashimoto
07272ae88f stream: add bell effect callback support
Add an Effects struct to the readonly stream Handler that allows
callers to provide optional callbacks for side effects like bell.
Previously, the bell action was silently ignored along with other
query/response actions. Now it is handled separately and dispatched
through the effects callback if one is provided.

Add a test that verifies bell with a null callback (default readonly
behavior) does not crash, and that a provided callback is invoked
the correct number of times.
2026-03-23 14:17:09 -07:00
Jeffrey C. Ollie
fd49716ea2 windows: skip expandHomeUnix test on Windows (#11784)
## What

Skip the `expandHomeUnix` test on Windows with `SkipZigTest`.

`expandHomeUnix` is a Unix-internal function that is never called on
Windows. The public `expandHome` already returns the path unchanged on
Windows (added upstream in cccdb0d2a). But the unit test calls
`expandHomeUnix` directly, which invokes `home()` and expects Unix-style
forward-slash separators, so it fails on Windows.

## How

Two lines:

```zig
if (builtin.os.tag == .windows) return error.SkipZigTest;

```

## Verified

- `zig build test-lib-vt` passes on Windows (exit 0)
- No behavior change on Linux/macOS

## What I Learnt

- When upstream adds a platform dispatch for production code (like
`expandHome` returning unchanged on Windows), the unit tests for
internal platform-specific functions (like `expandHomeUnix`) may still
need a skip guard.
- Zig doesn't have something like Go's `//go:build` but damn... comptime
is insane, like supercharged C# `#if`
2026-03-23 15:20:02 -05:00
Alessandro De Blasis
c1e616c6cd libghostty: add ghostty_free for cross-runtime memory safety
On Windows, Zig's built-in libc and MSVC's CRT maintain separate
heaps, so calling free() on memory allocated by the library causes
undefined behavior. Add ghostty_free() that frees through the same
allocator that performed the allocation, making it safe on all
platforms.

Update format_alloc docs and all examples to use ghostty_free()
instead of free().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:52:02 +01:00
Mitchell Hashimoto
1213dacd5b cmake: fix Windows libghostty build support (#11756)
On Windows, shared libraries (DLLs) require an import library (.lib) for
linking, and the DLL itself is placed in bin/ rather than lib/ by the
Zig build. The CMake wrapper was missing IMPORTED_IMPLIB on the shared
imported target, causing link failures, and assumed the shared library
was always in lib/.

Add GHOSTTY_VT_IMPLIB for the import library name, set IMPORTED_IMPLIB
on the ghostty-vt target, and fix the shared library path to use bin/ on
Windows. Install the DLL and PDB to bin/ and the import library to lib/
following standard Windows conventions. Apply the same fixes to
ghostty-vt-config.cmake.in for the find_package path.
2026-03-23 12:50:42 -07:00
Mitchell Hashimoto
b723f2a437 ci: remove run step from Windows cmake examples
The "Run Example" step in the build-examples-cmake-windows job
hangs, so remove it entirely. The build step is still run so
compilation is verified, but the examples are no longer executed
on Windows.
2026-03-23 12:34:22 -07:00
Mitchell Hashimoto
63260ec722 build: disable ubsan for SIMD C++ files on MSVC
The SIMD C++ files reference __ubsan_handle_* symbols when compiled
in debug mode, but we do not link or bundle the ubsan runtime on
MSVC. This matches what the highway and simdutf packages already do
in their own build files.
2026-03-23 12:32:06 -07:00
Alessandro De Blasis
f2773d42c1 windows: skip expandHomeUnix test on Windows
expandHomeUnix is a Unix-internal function that is never called on
Windows. The public expandHome function returns the path unchanged
on Windows since ~/ is not a standard Windows idiom. The test calls
expandHomeUnix directly, which invokes home() and expects Unix-style
forward-slash separators.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:29:59 +01:00
Mitchell Hashimoto
b4c529a827 build: add -std=c++17 for SIMD C++ files on MSVC
The SIMD C++ files use C++17 features (std::optional, std::size).
With Zig's bundled libc++ these are available implicitly, but MSVC
headers guard C++17 features behind the standard version
(_HAS_CXX17). Without an explicit -std=c++17 flag, clang defaults
to a lower standard and the MSVC <optional> header does not define
std::optional.
2026-03-23 12:23:33 -07:00
Mitchell Hashimoto
3d581eb92e 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.
2026-03-23 12:11:03 -07:00
Alessandro De Blasis
5ef2da8127 windows: fix XDG-related test failures on Windows
Make the "cache directory paths" test cross-platform by using
std.fs.path.join for expected values and a platform-appropriate
mock home path, since the function under test uses native path
separators.

Skip the two shell integration XDG_DATA_DIRS tests on Windows.
These tests use hardcoded Unix path separators (:) and Unix default
paths (/usr/local/share:/usr/share) which are not applicable on
Windows where the path delimiter is ; and XDG_DATA_DIRS is not a
standard concept.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:09:32 +01:00
Mitchell Hashimoto
afa8f059e5 build: skip linkLibCpp on MSVC targets
Zig's bundled libc++/libc++abi conflicts with the MSVC C++ runtime
headers (vcruntime_typeinfo.h, vcruntime_exception.h, etc.) when
targeting native-native-msvc. This caused compilation failures in
the SIMD C++ code due to -nostdinc++ suppressing MSVC headers and
libc++ types clashing with MSVC runtime types.

Skip linkLibCpp() for MSVC targets across all packages (highway,
simdutf, utfcpp) and the main build (SharedDeps, GhosttyZig) since
MSVC provides its own C++ standard library natively. Also add
missing <iterator> and <cstddef> includes that were previously
pulled in transitively through libc++ headers but are not
guaranteed by MSVC's headers.
2026-03-23 11:57:14 -07:00
Mitchell Hashimoto
1eed35dddc build: default to MSVC ABI on Windows
Zig defaults to the GNU ABI on Windows, which produces COFF objects
with invalid COMDAT sections in compiler_rt that the MSVC linker
rejects (LNK1143), and uses GNU conventions like ___chkstk_ms that
are unavailable in the MSVC CRT.

Default to the MSVC ABI when no explicit ABI is requested, following
the same pattern as the existing macOS target override. This ensures
compiler_rt produces valid COFF and the generated code uses
MSVC-compatible symbols. Users can still explicitly request the GNU
ABI via -Dtarget.

Also disable bundling ubsan_rt on Windows (its /exclude-symbols
directives are MSVC-incompatible) and add ntdll and kernel32 as
transitive link dependencies for the static library.
2026-03-23 11:45:43 -07:00
Mitchell Hashimoto
01401ef675 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.
2026-03-23 11:31:41 -07:00
Mitchell Hashimoto
2c89bef860 build: skip bundled compiler_rt and ubsan_rt in Windows static lib
Zig's compiler_rt produces COFF objects with invalid COMDAT
sections that the MSVC linker rejects (LNK1143), and its ubsan_rt
emits /exclude-symbols directives that MSVC does not understand
(LNK4229). Skip bundling both in the static library on Windows
since the MSVC CRT provides the needed builtins (memcpy, memset,
etc.). The shared library continues to bundle compiler_rt as it
needs to be self-contained.
2026-03-23 11:20:20 -07:00
Mitchell Hashimoto
69f82ec751 build: disable bundled ubsan runtime on Windows
Zig's ubsan runtime emits /exclude-symbols linker directives that
are incompatible with the MSVC linker, causing LNK4229 warnings and
LNK1143 errors. Disable bundling ubsan_rt on Windows while keeping
compiler_rt which provides essential symbols like memcpy, memset,
memmove, and ___chkstk_ms.

The previous check used target.result.abi == .msvc which never
matched because Zig defaults to the gnu ABI on Windows.
2026-03-23 11:12:19 -07:00
Mitchell Hashimoto
1ce057f053 build: disable ubsan and bundled runtimes for MSVC targets
Zig's ubsan instrumentation emits ELF-style /exclude-symbols linker
directives into the compiled object files, causing LNK4229 warnings
with the MSVC linker. The bundled compiler_rt also produces COMDAT
sections that are incompatible with MSVC, causing fatal LNK1143.

Disable sanitize_c entirely on the root module for MSVC targets and
skip bundling both compiler_rt and ubsan_rt since MSVC provides its
own runtime.
2026-03-23 11:04:28 -07:00
Mitchell Hashimoto
31285e1ac3 build: disable bundled compiler_rt and ubsan_rt for MSVC targets
Zig's bundled compiler_rt and ubsan_rt produce object files with
ELF-style linker directives (/exclude-symbols) and COMDAT sections
that are incompatible with the MSVC linker, causing LNK1143 and
LNK4229 errors when linking the static library.

MSVC provides its own compiler runtime so bundling Zig's versions
is unnecessary. Skip bundling both runtimes when the target ABI is
MSVC.
2026-03-23 10:42:10 -07:00
Mitchell Hashimoto
2afadfc104 build: fix Windows cmake example failures
The cmake examples were failing at runtime on Windows CI for two
reasons.

The static library was installed as "libghostty-vt.a" on all
platforms, but on Windows the DLL import library is also placed in
zig-out/lib/ as "ghostty-vt.lib". The CMakeLists.txt expected the
platform-native name "ghostty-vt.lib" for the static lib, so it
picked up the tiny DLL import lib instead, silently producing a
dynamically-linked executable. That executable then failed at
runtime because the DLL was not on PATH.

Fix this by installing the static library as "ghostty-vt-static.lib"
on Windows to avoid the name collision, and updating CMakeLists.txt
to match. For the shared (DLL) example, add zig-out/bin to PATH in
the CI run step so the DLL can be found at runtime.
2026-03-23 10:32:22 -07:00
Mitchell Hashimoto
6ccc01a852 revert the build-windows 2026-03-23 10:31:31 -07:00
Mitchell Hashimoto
0fdddd5bc2 Revert "build: fix Windows build failures in helpgen and framegen"
This reverts commit 704511465b.
2026-03-23 10:31:11 -07:00
Mitchell Hashimoto
48cf3f36cd ci: run Windows CMake examples after building
Add a "Run Example" step to the build-examples-cmake-windows job
so that each CMake example is executed after it is built, verifying
the resulting binaries actually work. The executable name is derived
from the matrix directory name by replacing hyphens with underscores,
matching the project convention.
2026-03-23 10:31:11 -07:00
Mitchell Hashimoto
f4998c6abb build: fix Windows build failures in helpgen and framegen
Use writerStreaming() instead of writer() for stdout in helpgen and
main_build_data. The positional writer calls setEndPos/ftruncate in
end(), which fails on Windows when stdout is redirected via
captureStdOut() because ftruncate maps INVALID_PARAMETER to
FileTooBig. Streaming mode skips truncation entirely since stdout
is inherently a sequential stream.

Replace scandir with opendir/readdir plus qsort in framegen since
scandir is a POSIX extension not available on Windows.
2026-03-23 10:31:11 -07:00
Mitchell Hashimoto
5a46e61bee cmake: fix Windows build support
On Windows, shared libraries (DLLs) require an import library (.lib)
for linking, and the DLL itself is placed in bin/ rather than lib/ by
the Zig build. The CMake wrapper was missing IMPORTED_IMPLIB on the
shared imported target, causing link failures, and assumed the shared
library was always in lib/.

Add GHOSTTY_VT_IMPLIB for the import library name, set IMPORTED_IMPLIB
on the ghostty-vt target, and fix the shared library path to use bin/
on Windows. Install the DLL and PDB to bin/ and the import library to
lib/ following standard Windows conventions. Apply the same fixes to
ghostty-vt-config.cmake.in for the find_package path.
2026-03-23 10:31:11 -07:00
Mitchell Hashimoto
fa10237fb0 build: fix windows build to properly run tests and build of libghostty-vt (#11781)
Our Windows build has been broken for a _long_ time. It hasn't actually
worked and our CI was falsely passing when it was actually failing to
build/test. This PR fixes that and fixes the issues it found so
`libghostty-vt` can build and pass tests.

**This is only for libghostty!** I'd still like to expand our _test_
coverage to all of Ghostty for Windows but libghostty is more important
for that platform in the short term and it's an incremental piece of
work.

A couple windows compatibility issues fixed:

- `terminal.Page` uses `VirtualAlloc` on Windows (thanks @deblasis)
- Our rgb.txt loading was not resilient to CRLF endings
2026-03-23 10:29:45 -07:00
Mitchell Hashimoto
e95fdd2f21 terminal: handle CRLF line endings in rgb.txt parsing
The X11 color map parser in x11_color.zig uses @embedFile to load
rgb.txt at comptime, then splits on \n. On Windows, git may check
out rgb.txt with CRLF line endings, leaving a trailing \r on each
line. This caused color names to be stored as e.g. "white\r" instead
of "white", so all X11 color lookups failed at runtime.

Strip trailing \r from each line before parsing. Also mark rgb.txt
as -text in .gitattributes to prevent line ending conversion in
future checkouts.
2026-03-23 10:15:16 -07:00