mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-04-12 10:48:39 +03:00
build: make glfw opt-in on all platforms, default to GTK on Linux
The GLFW build has grown farther and farther in feature parity with GTK on Linux. And on macOS, the GLFW build has been unstable (crashes) for months. I still find the GLFW build useful for testing some core terminal work, but it is increasingly user-hostile in case someone just downloads the project and does a `zig build`. I keep GLFW as up to date as I can, but the features that are missing are due to fundamental limitations: - GLFW has no tabs, splits, etc. because it has no UI elements. I am not interested in painting UI widgets from scratch. - GLFW cannot support keyboard layouts robustly because it has no hooks to detect keyboard layouts or functions to get keymaps. - GLFW cannot support the Kitty keyboard protocol because the key/char API is too high level and it provides no low-level alternatives. - GLFW crashes on macOS under certain scenarios (this is my problem). I'm not interested in fixing it because the AppKit-based build is highly recommended. To build or run the GLFW build you must now explicitly pass in `-Dapp-runtime=glfw` to `zig build`.
This commit is contained in:
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
||||
# Cross-compile the binary. We always use static building for this
|
||||
# because its the only way to access the headers.
|
||||
- name: Test Build
|
||||
run: nix develop -c zig build -Dstatic=true -Dtarget=${{ matrix.target }}
|
||||
run: nix develop -c zig build -Dstatic=true -Dapp-runtime=glfw -Dtarget=${{ matrix.target }}
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-12
|
||||
@ -89,6 +89,12 @@ jobs:
|
||||
- name: test
|
||||
run: nix develop -c zig build test
|
||||
|
||||
- name: Test GTK Build
|
||||
run: nix develop -c zig build -Dapp-runtime=gtk
|
||||
|
||||
- name: Test GLFW Build
|
||||
run: nix develop -c zig build -Dapp-runtime=glfw
|
||||
|
||||
- name: Test Dynamic Build
|
||||
run: nix develop -c zig build -Dstatic=false
|
||||
|
||||
|
62
build.zig
62
build.zig
@ -190,12 +190,14 @@ pub fn build(b: *std.Build) !void {
|
||||
// Add our benchmarks
|
||||
try benchSteps(b, target, optimize, emit_bench);
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
// We only build an exe if we have a runtime set.
|
||||
const exe_: ?*std.Build.Step.Compile = if (app_runtime != .none) b.addExecutable(.{
|
||||
.name = "ghostty",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
}) else null;
|
||||
|
||||
const exe_options = b.addOptions();
|
||||
exe_options.addOption(std.SemanticVersion, "app_version", version);
|
||||
exe_options.addOption([]const u8, "app_version_string", b.fmt("{}", .{version}));
|
||||
@ -205,7 +207,7 @@ pub fn build(b: *std.Build) !void {
|
||||
exe_options.addOption(font.Backend, "font_backend", font_backend);
|
||||
|
||||
// Exe
|
||||
{
|
||||
if (exe_) |exe| {
|
||||
exe.addOptions("build_options", exe_options);
|
||||
|
||||
// Add the shared dependencies
|
||||
@ -262,6 +264,17 @@ pub fn build(b: *std.Build) !void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// App (Mac)
|
||||
if (target.isDarwin()) {
|
||||
const bin_install = b.addInstallFile(
|
||||
exe.getEmittedBin(),
|
||||
"Ghostty.app/Contents/MacOS/ghostty",
|
||||
);
|
||||
b.getInstallStep().dependOn(&bin_install.step);
|
||||
b.installFile("dist/macos/Info.plist", "Ghostty.app/Contents/Info.plist");
|
||||
b.installFile("dist/macos/Ghostty.icns", "Ghostty.app/Contents/Resources/Ghostty.icns");
|
||||
}
|
||||
}
|
||||
|
||||
// Shell-integration
|
||||
@ -274,7 +287,7 @@ pub fn build(b: *std.Build) !void {
|
||||
});
|
||||
b.getInstallStep().dependOn(&install.step);
|
||||
|
||||
if (target.isDarwin()) {
|
||||
if (target.isDarwin() and exe_ != null) {
|
||||
const mac_install = b.addInstallDirectory(options: {
|
||||
var copy = install.options;
|
||||
copy.install_dir = .{
|
||||
@ -298,7 +311,7 @@ pub fn build(b: *std.Build) !void {
|
||||
const src_source = wf.add("share/terminfo/ghostty.terminfo", str.items);
|
||||
const src_install = b.addInstallFile(src_source, "share/terminfo/ghostty.terminfo");
|
||||
b.getInstallStep().dependOn(&src_install.step);
|
||||
if (target.isDarwin()) {
|
||||
if (target.isDarwin() and exe_ != null) {
|
||||
const mac_src_install = b.addInstallFile(
|
||||
src_source,
|
||||
"Ghostty.app/Contents/Resources/terminfo/ghostty.terminfo",
|
||||
@ -319,7 +332,7 @@ pub fn build(b: *std.Build) !void {
|
||||
const cap_install = b.addInstallFile(out_source, "share/terminfo/ghostty.termcap");
|
||||
b.getInstallStep().dependOn(&cap_install.step);
|
||||
|
||||
if (target.isDarwin()) {
|
||||
if (target.isDarwin() and exe_ != null) {
|
||||
const mac_cap_install = b.addInstallFile(
|
||||
out_source,
|
||||
"Ghostty.app/Contents/Resources/terminfo/ghostty.termcap",
|
||||
@ -348,7 +361,7 @@ pub fn build(b: *std.Build) !void {
|
||||
b.getInstallStep().dependOn(©_step.step);
|
||||
}
|
||||
|
||||
if (target.isDarwin()) {
|
||||
if (target.isDarwin() and exe_ != null) {
|
||||
const copy_step = RunStep.create(b, "copy terminfo db");
|
||||
copy_step.addArgs(&.{ "cp", "-R" });
|
||||
copy_step.addFileSourceArg(path);
|
||||
@ -384,17 +397,6 @@ pub fn build(b: *std.Build) !void {
|
||||
b.installFile("images/icons/icon_256x256@2x@2x.png", "share/icons/hicolor/256x256@2/apps/com.mitchellh.ghostty.png");
|
||||
}
|
||||
|
||||
// App (Mac)
|
||||
if (target.isDarwin()) {
|
||||
const bin_install = b.addInstallFile(
|
||||
exe.getEmittedBin(),
|
||||
"Ghostty.app/Contents/MacOS/ghostty",
|
||||
);
|
||||
b.getInstallStep().dependOn(&bin_install.step);
|
||||
b.installFile("dist/macos/Info.plist", "Ghostty.app/Contents/Info.plist");
|
||||
b.installFile("dist/macos/Ghostty.icns", "Ghostty.app/Contents/Resources/Ghostty.icns");
|
||||
}
|
||||
|
||||
// On Mac we can build the embedding library.
|
||||
if (builtin.target.isDarwin() and target.isDarwin()) {
|
||||
const static_lib_aarch64 = lib: {
|
||||
@ -464,6 +466,20 @@ pub fn build(b: *std.Build) !void {
|
||||
static_lib_universal.step.dependOn(static_lib_aarch64.step);
|
||||
static_lib_universal.step.dependOn(static_lib_x86_64.step);
|
||||
|
||||
// Add our library to zig-out
|
||||
const lib_install = b.addInstallLibFile(
|
||||
static_lib_universal.output,
|
||||
"libghostty.a",
|
||||
);
|
||||
b.getInstallStep().dependOn(&lib_install.step);
|
||||
|
||||
// Copy our ghostty.h to include
|
||||
const header_install = b.addInstallHeaderFile(
|
||||
"include/ghostty.h",
|
||||
"ghostty.h",
|
||||
);
|
||||
b.getInstallStep().dependOn(&header_install.step);
|
||||
|
||||
// The xcframework wraps our ghostty library so that we can link
|
||||
// it to the final app built with Swift.
|
||||
const xcframework = XCFrameworkStep.create(b, .{
|
||||
@ -546,14 +562,14 @@ pub fn build(b: *std.Build) !void {
|
||||
}
|
||||
|
||||
// Run
|
||||
{
|
||||
run: {
|
||||
// Build our run step, which runs the main app by default, but will
|
||||
// run a conformance app if `-Dconformance` is set.
|
||||
const run_exe = if (conformance) |name| blk: {
|
||||
var conformance_exes = try conformanceSteps(b, target, optimize);
|
||||
defer conformance_exes.deinit();
|
||||
break :blk conformance_exes.get(name) orelse return error.InvalidConformance;
|
||||
} else exe;
|
||||
} else exe_ orelse break :run;
|
||||
|
||||
const run_cmd = b.addRunArtifact(run_exe);
|
||||
if (b.args) |args| {
|
||||
@ -844,6 +860,12 @@ fn addDeps(
|
||||
try glfw.link(b, step, glfw_opts);
|
||||
|
||||
step.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
||||
|
||||
// Must also link to imgui but only for tests.
|
||||
if (step.kind == .@"test") {
|
||||
const imgui_step = try imgui.link(b, step, imgui_opts);
|
||||
try glfw.link(b, imgui_step, glfw_opts);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,13 @@ pub const Runtime = enum {
|
||||
gtk,
|
||||
|
||||
pub fn default(target: std.zig.CrossTarget) Runtime {
|
||||
_ = target;
|
||||
return .glfw;
|
||||
// The Linux default is GTK because it is full featured.
|
||||
if (target.isLinux()) return .gtk;
|
||||
|
||||
// Otherwise, we do NONE so we don't create an exe. The GLFW
|
||||
// build is opt-in because it is missing so many features compared
|
||||
// to the other builds that are impossible due to the GLFW interface.
|
||||
return .none;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user