Related to #7879
This commit updates `zig build test` to run Xcode tests, too. These run
in parallel to the Zig tests, so they don't add any time to the test.
The Xcode tests will _not_ run when: (1) the target is not macOS, or (2)
the `-Dtest-filter` option is non-empty. This makes it so that this
change doesn't affect non-macOS and doesn't affect the general dev cycle
because you usually will run `-Dtest-filter` when developing a core
feature.
I didn't add a step to only run Xcode tests because I find that when I'm
working in Xcode I'm probably going to run the tests from there anyways.
The integration with `zig build test` is just a convenience, especially
around CI.
Speaking of CI, this change also makes it so this will run in CI.
This PR modernizes our benchmarks. This PR focuses on the benchmark
_framework_ and not the benchmarks themselves. That will come in later
PRs.
We now produce two binaries with `-Demit-bench`: `ghostty-bench` and
`ghostty-gen`. The former is our benchmark tool. The latter is our
synthetic data generation tool. The benchmarking CLI usually takes in
data from the synthetic generator but we want to do that offline because
synthetic data generation can be slow and CPU intensive and mess up our
benchmarks.
Our previous benchmark-specific binaries (like
`ghostty-bench-codepoint-width`) are all gone. This is all executed as
subcommands in the format similar to Ghostty users: `ghostty-bench
+codepoint-width --other --args`.
Previously, synthetic data generation was a mess and all unified with
`ghostty-bench-stream` which is just nasty. A dedicated CLI now gets us
args like `ghostty-gen +osc --p-valid=0.5`. Neat!
## Signposts and Xcode/Instruments on macOS
The benchmark framework now automatically emits
[signposts](https://developer.apple.com/documentation/os/recording-performance-data)
around the code that is under test. This is surfaced in Instruments as a
region that you can visualize and zoom in on so you can omit any of the
other overhead.
Additionally, I've integrated benchmarks with libghostty and our Xcode
project so you can just right click a benchmark to open it in
Instruments.
These are macOS-specific niceties but the core benchmarking tool is
platform-agnostic.
## Generalized CLI Actions
The `src/cli/action.zig` file was generalized so that it can be shared
amongst our three action-ized binaries. The Ghostty-specific actions are
now in `src/cli/ghostty.zig`. As an added bonus, our action parsing is
now fully unit tested.
I don't like mixing refactors in with other tasks in PRs but in this
case this one was done to enable not one but two other consumers in the
same PR, so I think it fits.
## TODO
Some things I want to do before merge.
- [ ] Add flags to `ghostty-bench` to configure once mode vs duration
mode
This was in pursuit of trying to get line numbers in `zig build run` on
macOS to work, but I wasn't able to figure that out and this wasn't the
right path because static libs can't have dsyms. But, it may still be
useful to make the xcframework step dsym aware for future use so I'm
PRing this.
CI is currently configured to fail if there are any fuzzy matches in
translation files. This change prevents `msgmerge` from creating any
fuzzy matches when translations are updated.
- The order of the arguments to xgettext influences the output. Since
directorty walking does not guarantee that files will be listed in
a deterministic order (especially when run on different systems) the
translation files would see a lot of churn depending on who updated
them last.
In this update the files are sorted so that the arguments to xgettext
are always in the same order. This should reduce churn in the future.
- Mark all of the files as inputs so that the Zig build system caching
will work properly.
This makes it so `zig build run` can take arguments such as
`--config-default-files=false` or any other configuration. Previously,
it only accepted commands such as `+version`.
Incidentally, this also makes it so that the app in general can now take
configuration arguments via the CLI if it is launched as a new instance
via `open`. For example:
open -n Ghostty.app --args --config-default-files=false
This previously didn't work. This is kind of cool.
To make this work, the libghostty C API was modified so that
initialization requires the CLI args, and there is a new C API to try to
execute an action if it was set.
This is a big'un.
- **Glyph constraint logic is now done fully on the CPU** at the
rasterization stage, so it only needs to be done once per glyph instead
of every frame. This also lets us eliminate padding between glyphs on
the atlas because we're doing nearest-neighbor sampling instead of
interpolating-- which ever so slightly increases our packing efficiency.
- **Special constraints for nerd font glyphs** are applied based roughly
on the constraints they use in their patcher. It's a simplification of
what they do, the largest difference being that they scale groups of
glyphs based on a shared bounding box so that they maintain relative
size to one another, but that would require loading all glyphs on the
group and I'd want to do that on font load TBH and at that point I'd
basically be re-implementing the nerd fonts patcher in Zig to patch
fonts at load time which is way beyond the scope I want to have. (Fixes
#7069)
- These constraints allow for **perfectly sized and centered emojis**,
this is very nice.
- **Changed the default embedded fonts** from 4 copies (regular, italic,
bold, bold italic) of a patched (and outdated) JetBrains Mono to a
single JetBrains Mono variable font and a single Nerd Fonts Symbols Only
font. This cuts the weight of those down from 9MB to 3MB!
- **FreeType's `renderGlyph` is significantly reworked**, and the new
code is, IMO, much cleaner- although there are probably some edge case
behavior differences I've introduced.
> [!NOTE]
> One breaking change I definitely introduced is changing the
`monochrome` freetype load flag config from its previous completely
backwards meaning to instead the correct one (I also changed the
default, so this won't affect any user who hasn't touched it, but users
who set the `monochrome` flag will find their fonts quite crispy after
this change because they will have no anti-aliasing anymore)
### Future work
Following this change I want to get to work on automatic font size
matching (a la CSS
[`font-size-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust)).
I set the stage for that quite some time ago so it shouldn't be too much
work and it will be a big benefit for users who regularly use multiple
writing systems and so have multiple fonts for them that aren't
necessarily size-compatible.
This deletes the GLFW apprt from the Ghostty codebase.
The GLFW apprt was the original apprt used by Ghostty (well, before
Ghostty even had the concept of an "apprt" -- it was all just a single
application then). It let me iterate on the core terminal features,
rendering, etc. without bothering about the UI. It was a good way to get
started. But it has long since outlived its usefulness.
We've had a stable GTK apprt for Linux (and Windows via WSL) and a
native macOS app via libghostty for awhile now. The GLFW apprt only
remained within the tree for a few reasons:
1. Primarily, it provided a faster feedback loop on macOS because
building the macOS app historically required us to hop out of the
zig build system and into Xcode, which is slow and cumbersome.
2. It was a convenient way to narrow whether a bug was in the
core Ghostty codebase or in the apprt itself. If a bug was in both
the glfw and macOS app then it was likely in the core.
3. It provided us a way on macOS to test OpenGL.
All of these reasons are no longer valid. Respectively:
1. Our Zig build scripts now execute the `xcodebuild` CLI directly and
can open the resulting app, stream logs, etc. This is the same
experience we have on Linux. (Xcode has always been a dependency of
building on macOS in general, so this is not cumbersome.)
2. We have a healthy group of maintainers, many of which have access
to both macOS and Linux, so we can quickly narrow down bugs
regardless of the apprt.
3. Our OpenGL renderer hasn't been compatible with macOS for some time
now, so this is no longer a useful feature.
At this point, the GLFW apprt is just a burden. It adds complexity
across the board, and some people try to run Ghostty with it in the real
world and get confused when it doesn't work (it's always been lacking in
features and buggy compared to the other apprts).
So, it's time to say goodbye. Its bittersweet because it is a big part
of Ghostty's history, but we've grown up now and it's time to move on.
Thank you, goodbye.
(NOTE: If you are a user of the GLFW apprt, then please fork the project
prior to this commit or start a new project based on it. We've warned
against using it for a very, very long time now.)
`zig build run` on macOS now builds the app bundle via the `xcodebuild`
CLI and runs it. The experience for running the app is now very similar
to Linux or the prior GLFW build, where the app runs, blocks the zig
command, and logs to the terminal.
`xcodebuild` has its own build cache system that we can't really hook
into so it runs on every `zig build run` command, but it does cache and
I find its actually relatively fast so I think this is a good
replacement for the glfw-based system.
Rather than using binaries statically in our source tree; this makes
them easier to update. This also makes it so that they are separated
from each other rather than using a patched JB mono as our fallback.
We need to use this version of z2d so that we can get reproducible PNG
exports in CI for testing, since previously the PNG export was affected
by the CPU arch / features because it depended on vector width.
We default system-integration to true as this is a shared library that
must be installed on a library path and it is recommended to use the
system package.
If the system does not package gtk4-layer-shell then doing `zig build
-fno-sys` will now correctly build and install the shared library under
a lib/ subdirectory of the output prefix.
The output prefix should be a default library path (`/lib`, `/usr/lib`,
or a lib64 variant) otherwise a custom library path can be configured
using ldconfig (see `man ld.so 8`)
Replaces #7676
When building as a flatpak, don't install the systemd user services
since flatpaks can't use them. Remove references to the systemd service
from the DBus service.
Also, customize the app metadata depending on the debug mode.
Co-authored-by: Leorize <leorize+oss@disroot.org>
This replaces #7433. The improvements are:
1) Install the systemd user service in the proper directory depending
on if it's a 'user' install or a 'system' install. This is controlled
either by using the `--system` build flag (as most packages will) or by
the `-Dsystem-package` flag.
2) Add the absolute path to the `ghostty` binary in the application
file, the DBus service, and the systemd user service. This is done so
that they do not depend on `ghostty` being in the `PATH` of whatever
is launching Ghostty. That `PATH` is not necessarily the same as the
`PATH` in a user shell (especially for DBus activation and systemd user
services).
3) Adjust the DBus bus name that is expected by the system depending on
the optimization level that Ghostty is compiled with.
Reverts two commits:
977cd530c7bb9551de93900170bdaec4601b1b5b
820b7e432b57cd08c49d2e76cce4cb78016f0418
These break build from source on Linux for two reasons:
1.) The systemd user service needs to be installed in the `share`
prefix, not the `lib` prefix. This lets it get picked up in `~/.local`
but is also correct for just standard FHS paths.
2.) The `ghostty` path in the systemd user service needs to be absolute.
We should interpolate in the build install prefix to form an absolute
path.
In this format it will be a lot easier to iterate on this since adding
and removing pipelines only has to be done in a single place.
This commit also separates out the main background color from individual
cell background color drawing, because sometimes kitty images need to be
between the main background and individual cell backgrounds (kitty image
z-index seems to be entirely broken at the moment, I intend to fix it in
future commits).
This wasn't working before but it just requires a restart of the machine
for the changes to take effect. The namespace runners have this prebuilt
so this should work now.
The other workaround was flaky for unknown reasons so I'd prefer to go
back to this.
Updates all copyright notices to include "Ghostty contributors" to
reflect the fact that Mitchell is not the sole copyright owner.
Also adds "Ghostty contributors" to the author section in the manpages,
linking https://github.com/ghostty-org/ghostty/graphs/contributors for
proper credit.
This updates our build script and CI to support Xcode 26 and macOS
Tahoe. **This doesn't update the Ghostty app to resolve any Tahoe
issues.**
For CI, we've added a new build job that runs on macOS Tahoe with Xcode
26. I've stopped short of updating our tip release job, since I think I
want to wait until I verify a bit more about Tahoe before we flip that
bit. Also, ideally, we'd run Xcode 26 on Sequoia (macOS 15) for
stability reasons and Namespace doesn't have Xcode 26 on 15 yet.
For builds, this updates our build script to find Metal binaries using
`xcodebuild -find-executable` instead of `xcrun`. The latter doesn't
work with Xcode 26, but the former does and also still works with older
Xcodes. I'm not sure if this is a bug but I did report it: FB17874042.
I'm not sure if this should be enabled by default like the tab
animation, but on KDE at least this is unintrusive enough for me to
always enable by default. Alacritty appears to agree with me as well.