build: replace lib-vt step with -Demit-lib-vt option

Remove the dedicated `zig build lib-vt` step and replace it with a
`-Demit-lib-vt` build option. This fixes two problems:

1. We can default XCFramework, app, etc. steps to false if emit-lib-vt
   is true, so that the lib-vt build doesn't pull in unrelated
   artifacts. **Most importantly, lib-vt alone can be build without
   full Xcode installations.**

2. We can build lib-vt as part of a bundle with other artifacts if we
   really want.
This commit is contained in:
Mitchell Hashimoto
2026-03-20 20:59:27 -07:00
parent e8fb7eabad
commit 3fc04fd4ae
9 changed files with 43 additions and 40 deletions

View File

@@ -408,11 +408,11 @@ jobs:
- name: Build
run: |
nix develop -c zig build lib-vt \
nix develop -c zig build -Demit-lib-vt \
-Dtarget=${{ matrix.target }} \
-Dsimd=false
# lib-vt requires macOS runner for macOS/iOS builds becauase it requires the `apple_sdk` path
# lib-vt requires macOS runner for macOS/iOS builds because it requires the `apple_sdk` path
build-libghostty-vt-macos:
strategy:
matrix:
@@ -448,7 +448,7 @@ jobs:
- name: Build
run: |
nix develop -c zig build lib-vt \
nix develop -c zig build -Demit-lib-vt \
-Dtarget=${{ matrix.target }}
# lib-vt requires the Android NDK for Android builds
@@ -494,7 +494,7 @@ jobs:
- name: Build
run: |
nix develop -c zig build lib-vt \
nix develop -c zig build -Demit-lib-vt \
-Dtarget=${{ matrix.target }}
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}

View File

@@ -1,6 +1,6 @@
# CMake wrapper for libghostty-vt
#
# This file delegates to `zig build lib-vt` to produce the shared library,
# This file delegates to `zig build -Demit-lib-vt` to produce the shared library,
# headers, and pkg-config file. It exists so that CMake-based projects can
# consume libghostty-vt without interacting with the Zig build system
# directly. However, downstream users do still require `zig` on the PATH.
@@ -91,10 +91,10 @@ set(GHOSTTY_VT_LIBRARY "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_REALNAME}")
# INTERFACE_INCLUDE_DIRECTORIES before the zig build has run.
file(MAKE_DIRECTORY "${ZIG_OUT_DIR}/include")
# Custom command: run zig build lib-vt
# Custom command: run zig build -Demit-lib-vt
add_custom_command(
OUTPUT "${GHOSTTY_VT_LIBRARY}"
COMMAND "${ZIG_EXECUTABLE}" build lib-vt ${GHOSTTY_ZIG_BUILD_FLAGS}
COMMAND "${ZIG_EXECUTABLE}" build -Demit-lib-vt ${GHOSTTY_ZIG_BUILD_FLAGS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Building libghostty-vt via zig build..."
USES_TERMINAL

View File

@@ -35,7 +35,6 @@ pub fn build(b: *std.Build) !void {
// All our steps which we'll hook up later. The steps are shown
// up here just so that they are more self-documenting.
const libvt_step = b.step("lib-vt", "Build libghostty-vt");
const run_step = b.step("run", "Run the app");
const run_valgrind_step = b.step(
"run-valgrind",
@@ -91,16 +90,6 @@ pub fn build(b: *std.Build) !void {
check_step.dependOn(dist.install_step);
}
// libghostty (internal, big)
const libghostty_shared = try buildpkg.GhosttyLib.initShared(
b,
&deps,
);
const libghostty_static = try buildpkg.GhosttyLib.initStatic(
b,
&deps,
);
// libghostty-vt
const libghostty_vt_shared = shared: {
if (config.target.result.cpu.arch.isWasm()) {
@@ -115,7 +104,6 @@ pub fn build(b: *std.Build) !void {
&mod,
);
};
libghostty_vt_shared.install(libvt_step);
libghostty_vt_shared.install(b.getInstallStep());
// Helpgen
@@ -128,26 +116,29 @@ pub fn build(b: *std.Build) !void {
resources.install();
if (i18n) |v| v.install();
}
} else {
// Libghostty
} else if (!config.emit_lib_vt) {
// The macOS Ghostty Library
//
// Note: libghostty is not stable for general purpose use. It is used
// heavily by Ghostty on macOS but it isn't built to be reusable yet.
// As such, these build steps are lacking. For example, the Darwin
// build only produces an xcframework.
// This is NOT libghostty (even though its named that for historical
// reasons). It is just the glue between Ghostty GUI on macOS and
// the full Ghostty GUI core.
const lib_shared = try buildpkg.GhosttyLib.initShared(b, &deps);
const lib_static = try buildpkg.GhosttyLib.initStatic(b, &deps);
// We shouldn't have this guard but we don't currently
// build on macOS this way ironically so we need to fix that.
if (!config.target.result.os.tag.isDarwin()) {
libghostty_shared.installHeader(); // Only need one header
libghostty_shared.install("libghostty.so");
libghostty_static.install("libghostty.a");
lib_shared.installHeader(); // Only need one header
lib_shared.install("libghostty.so");
lib_static.install("libghostty.a");
}
}
// macOS only artifacts. These will error if they're initialized for
// other targets.
if (config.target.result.os.tag.isDarwin()) {
if (config.target.result.os.tag.isDarwin() and
(config.emit_xcframework or config.emit_macos_app))
{
// Ghostty xcframework
const xcframework = try buildpkg.GhosttyXCFramework.init(
b,
@@ -202,7 +193,9 @@ pub fn build(b: *std.Build) !void {
// On macOS we can run the macOS app. For "run" we always force
// a native-only build so that we can run as quickly as possible.
if (config.target.result.os.tag.isDarwin()) {
if (config.target.result.os.tag.isDarwin() and
(config.emit_xcframework or config.emit_macos_app))
{
const xcframework_native = try buildpkg.GhosttyXCFramework.init(
b,
&deps,

View File

@@ -2,7 +2,7 @@
The top-level `CMakeLists.txt` wraps the Zig build system so that CMake
projects can consume libghostty-vt without invoking `zig build` manually.
Running `cmake --build` triggers `zig build lib-vt` automatically.
Running `cmake --build` triggers `zig build -Demit-lib-vt` automatically.
This means downstream projects do require a working Zig compiler on
`PATH` to build, but don't need to know any Zig-specific details.

View File

@@ -8,7 +8,7 @@ to encode key events into terminal escape sequences.
First, build the WebAssembly module:
```bash
zig build lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
zig build -Demit-lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
```
This will create `zig-out/bin/ghostty-vt.wasm`.

View File

@@ -9,7 +9,7 @@ styling attributes.
First, build the WebAssembly module:
```bash
zig build lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
zig build -Demit-lib-vt -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmall
```
This will create `zig-out/bin/ghostty-vt.wasm`.

View File

@@ -51,6 +51,7 @@ emit_bench: bool = false,
emit_docs: bool = false,
emit_exe: bool = false,
emit_helpgen: bool = false,
emit_lib_vt: bool = false,
emit_macos_app: bool = false,
emit_terminfo: bool = false,
emit_termcap: bool = false,
@@ -314,11 +315,17 @@ pub fn init(b: *std.Build, appVersion: []const u8) !Config {
//---------------------------------------------------------------
// Artifacts to Emit
config.emit_lib_vt = b.option(
bool,
"emit-lib-vt",
"Set defaults for a libghostty-vt-only build (disables xcframework, macOS app, and docs).",
) orelse false;
config.emit_exe = b.option(
bool,
"emit-exe",
"Build and install main executables with 'build'",
) orelse true;
) orelse !config.emit_lib_vt;
config.emit_test_exe = b.option(
bool,
@@ -352,7 +359,8 @@ pub fn init(b: *std.Build, appVersion: []const u8) !Config {
// If we are emitting any other artifacts then we default to false.
if (config.emit_bench or
config.emit_test_exe or
config.emit_helpgen) break :emit_docs false;
config.emit_helpgen or
config.emit_lib_vt) break :emit_docs false;
// We always emit docs in system package mode.
if (system_package) break :emit_docs true;
@@ -401,7 +409,8 @@ pub fn init(b: *std.Build, appVersion: []const u8) !Config {
bool,
"emit-xcframework",
"Build and install the xcframework for the macOS library.",
) orelse builtin.target.os.tag.isDarwin() and
) orelse !config.emit_lib_vt and
builtin.target.os.tag.isDarwin() and
target.result.os.tag == .macos and
config.app_runtime == .none and
(!config.emit_bench and
@@ -412,7 +421,7 @@ pub fn init(b: *std.Build, appVersion: []const u8) !Config {
bool,
"emit-macos-app",
"Build and install the macOS app bundle.",
) orelse config.emit_xcframework;
) orelse !config.emit_lib_vt and config.emit_xcframework;
//---------------------------------------------------------------
// System Packages

View File

@@ -29,8 +29,9 @@ pub fn init(b: *std.Build, cfg: *const Config, deps: *const SharedDeps) !Ghostty
// Set PIE if requested
if (cfg.pie) exe.pie = true;
// Add the shared dependencies
_ = try deps.add(exe);
// Add the shared dependencies. When building only lib-vt we skip
// heavy deps so cross-compilation doesn't pull in GTK, etc.
if (!cfg.emit_lib_vt) _ = try deps.add(exe);
// Check for possible issues
try checkNixShell(exe, cfg);

View File

@@ -121,7 +121,7 @@ pub fn add(
// We don't support cross-compiling to Darwin but due to the way
// lazy dependencies work with Zig, we call this function. So we just
// bail. The build will fail but the build would've failed anyways.
// And this lets other non-platform-specific targets like `lib-vt`
// And this lets other non-platform-specific targets like `-Demit-lib-vt`
// cross-compile properly.
if (!builtin.target.os.tag.isDarwin() and
self.config.target.result.os.tag.isDarwin())