new build system

This commit is contained in:
Mitchell Hashimoto
2023-02-14 20:58:33 -08:00
parent ec19c178a1
commit be75109a1d
20 changed files with 228 additions and 179 deletions

130
build.zig
View File

@ -44,7 +44,7 @@ var enable_coretext: bool = false;
var enable_fontconfig: bool = false; var enable_fontconfig: bool = false;
pub fn build(b: *std.build.Builder) !void { pub fn build(b: *std.build.Builder) !void {
const mode = b.standardReleaseOptions(); const optimize = b.standardOptimizeOption(.{});
const target = target: { const target = target: {
var result = b.standardTargetOptions(.{}); var result = b.standardTargetOptions(.{});
@ -60,7 +60,7 @@ pub fn build(b: *std.build.Builder) !void {
bool, bool,
"tracy", "tracy",
"Enable Tracy integration (default true in Debug on Linux)", "Enable Tracy integration (default true in Debug on Linux)",
) orelse (mode == .Debug and target.isLinux()); ) orelse (optimize == .Debug and target.isLinux());
enable_coretext = b.option( enable_coretext = b.option(
bool, bool,
@ -96,9 +96,14 @@ pub fn build(b: *std.build.Builder) !void {
b.enable_wasmtime = true; b.enable_wasmtime = true;
// Add our benchmarks // Add our benchmarks
try benchSteps(b, target, mode); try benchSteps(b, target, optimize);
const exe = b.addExecutable("ghostty", "src/main.zig"); const exe = b.addExecutable(.{
.name = "ghostty",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const exe_options = b.addOptions(); const exe_options = b.addOptions();
exe_options.addOption(bool, "tracy_enabled", tracy); exe_options.addOption(bool, "tracy_enabled", tracy);
exe_options.addOption(bool, "coretext", enable_coretext); exe_options.addOption(bool, "coretext", enable_coretext);
@ -111,8 +116,6 @@ pub fn build(b: *std.build.Builder) !void {
exe.addCSourceFile("src/renderer/metal_workaround.c", &.{}); exe.addCSourceFile("src/renderer/metal_workaround.c", &.{});
} }
exe.setTarget(target);
exe.setBuildMode(mode);
exe.addOptions("build_options", exe_options); exe.addOptions("build_options", exe_options);
exe.install(); exe.install();
@ -157,13 +160,12 @@ pub fn build(b: *std.build.Builder) !void {
const wasm_specific_target: WasmTarget = .browser; const wasm_specific_target: WasmTarget = .browser;
exe_options.addOption(WasmTarget, "wasm_target", wasm_specific_target); exe_options.addOption(WasmTarget, "wasm_target", wasm_specific_target);
const wasm = b.addSharedLibrary( const wasm = b.addSharedLibrary(.{
"ghostty-wasm", .name = "ghostty-wasm",
"src/main_wasm.zig", .root_source_file = .{ .path = "src/main_wasm.zig" },
.{ .unversioned = {} }, .target = wasm_target,
); .optimize = optimize,
wasm.setTarget(wasm_target); });
wasm.setBuildMode(mode);
wasm.setOutputDir("zig-out"); wasm.setOutputDir("zig-out");
wasm.addOptions("build_options", exe_options); wasm.addOptions("build_options", exe_options);
@ -186,8 +188,11 @@ pub fn build(b: *std.build.Builder) !void {
// isn't an exact match to our freestanding target above but // isn't an exact match to our freestanding target above but
// it lets us test some basic functionality. // it lets us test some basic functionality.
const test_step = b.step("test-wasm", "Run all tests for wasm"); const test_step = b.step("test-wasm", "Run all tests for wasm");
const main_test = b.addTest("src/main_wasm.zig"); const main_test = b.addTest(.{
main_test.setTarget(wasm_target); .name = "wasm-test",
.root_source_file = .{ .path = "src/main_wasm.zig" },
.target = wasm_target,
});
main_test.addOptions("build_options", exe_options); main_test.addOptions("build_options", exe_options);
try addDeps(b, main_test, true); try addDeps(b, main_test, true);
test_step.dependOn(&main_test.step); test_step.dependOn(&main_test.step);
@ -198,7 +203,7 @@ pub fn build(b: *std.build.Builder) !void {
// Build our run step, which runs the main app by default, but will // Build our run step, which runs the main app by default, but will
// run a conformance app if `-Dconformance` is set. // run a conformance app if `-Dconformance` is set.
const run_exe = if (conformance) |name| blk: { const run_exe = if (conformance) |name| blk: {
var conformance_exes = try conformanceSteps(b, target, mode); var conformance_exes = try conformanceSteps(b, target, optimize);
defer conformance_exes.deinit(); defer conformance_exes.deinit();
break :blk conformance_exes.get(name) orelse return error.InvalidConformance; break :blk conformance_exes.get(name) orelse return error.InvalidConformance;
} else exe; } else exe;
@ -217,12 +222,16 @@ pub fn build(b: *std.build.Builder) !void {
const test_step = b.step("test", "Run all tests"); const test_step = b.step("test", "Run all tests");
var test_filter = b.option([]const u8, "test-filter", "Filter for test"); var test_filter = b.option([]const u8, "test-filter", "Filter for test");
const main_test = b.addTestExe("ghostty-test", "src/main.zig"); const main_test = b.addTest(.{
.name = "ghostty-test",
.kind = .test_exe,
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
});
{ {
if (emit_test_exe) main_test.install(); if (emit_test_exe) main_test.install();
const main_test_run = main_test.run(); const main_test_run = main_test.run();
main_test.setFilter(test_filter); main_test.setFilter(test_filter);
main_test.setTarget(target);
try addDeps(b, main_test, true); try addDeps(b, main_test, true);
main_test.addOptions("build_options", exe_options); main_test.addOptions("build_options", exe_options);
@ -236,26 +245,29 @@ pub fn build(b: *std.build.Builder) !void {
// Named package dependencies don't have their tests run by reference, // Named package dependencies don't have their tests run by reference,
// so we iterate through them here. We're only interested in dependencies // so we iterate through them here. We're only interested in dependencies
// we wrote (are in the "pkg/" directory). // we wrote (are in the "pkg/" directory).
for (main_test.packages.items) |pkg_| { var it = main_test.modules.iterator();
const pkg: std.build.Pkg = pkg_; while (it.next()) |entry| {
if (std.mem.eql(u8, pkg.name, "build_options")) continue; const name = entry.key_ptr.*;
if (std.mem.eql(u8, pkg.name, "glfw")) continue; const module = entry.value_ptr.*;
if (std.mem.eql(u8, name, "build_options")) continue;
if (std.mem.eql(u8, name, "glfw")) continue;
var buf: [256]u8 = undefined; var buf: [256]u8 = undefined;
var test_ = b.addTestExeSource( var test_ = b.addTest(.{
try std.fmt.bufPrint(&buf, "{s}-test", .{pkg.name}), .name = try std.fmt.bufPrint(&buf, "{s}-test", .{name}),
pkg.source, .kind = .test_exe,
); .root_source_file = module.source_file,
.target = target,
});
const test_run = test_.run(); const test_run = test_.run();
test_.setTarget(target);
try addDeps(b, test_, true); try addDeps(b, test_, true);
if (pkg.dependencies) |children| { // if (pkg.dependencies) |children| {
test_.packages = std.ArrayList(std.build.Pkg).init(b.allocator); // test_.packages = std.ArrayList(std.build.Pkg).init(b.allocator);
try test_.packages.appendSlice(children); // try test_.packages.appendSlice(children);
} // }
var before = b.addLog("\x1b[" ++ color_map.get("cyan").? ++ "\x1b[" ++ color_map.get("b").? ++ "[{s} tests]" ++ "\x1b[" ++ color_map.get("d").? ++ " ----" ++ "\x1b[0m", .{pkg.name}); var before = b.addLog("\x1b[" ++ color_map.get("cyan").? ++ "\x1b[" ++ color_map.get("b").? ++ "[{s} tests]" ++ "\x1b[" ++ color_map.get("d").? ++ " ----" ++ "\x1b[0m", .{name});
var after = b.addLog("\x1b[" ++ color_map.get("d").? ++ "---\n\n" ++ "\x1b[0m", .{}); var after = b.addLog("\x1b[" ++ color_map.get("d").? ++ "---\n\n" ++ "\x1b[0m", .{});
test_step.dependOn(&before.step); test_step.dependOn(&before.step);
test_step.dependOn(&test_run.step); test_step.dependOn(&test_run.step);
@ -276,9 +288,9 @@ fn addDeps(
if (step.target.getCpuArch() == .wasm32) { if (step.target.getCpuArch() == .wasm32) {
// We link this package but its a no-op since Tracy // We link this package but its a no-op since Tracy
// never actualy WORKS with wasm. // never actualy WORKS with wasm.
step.addPackage(tracylib.pkg); step.addModule("tracy", tracylib.module(b));
step.addPackage(utf8proc.pkg); step.addModule("utf8proc", utf8proc.module(b));
step.addPackage(js.pkg); // TODO: step.addPackage(js.pkg);
// utf8proc // utf8proc
_ = try utf8proc.link(b, step); _ = try utf8proc.link(b, step);
@ -287,20 +299,20 @@ fn addDeps(
} }
// We always need the Zig packages // We always need the Zig packages
if (enable_fontconfig) step.addPackage(fontconfig.pkg); if (enable_fontconfig) step.addModule("fontconfig", fontconfig.module(b));
step.addPackage(freetype.pkg); step.addModule("freetype", freetype.module(b));
step.addPackage(harfbuzz.pkg); step.addModule("harfbuzz", harfbuzz.module(b));
step.addPackage(imgui.pkg); step.addModule("imgui", imgui.module(b));
step.addPackage(glfw.pkg); step.addModule("glfw", glfw.module(b));
step.addPackage(libxev.pkg); step.addModule("xev", libxev.module(b));
step.addPackage(pixman.pkg); step.addModule("pixman", pixman.module(b));
step.addPackage(stb_image_resize.pkg); step.addModule("stb_image_resize", stb_image_resize.module(b));
step.addPackage(utf8proc.pkg); step.addModule("utf8proc", utf8proc.module(b));
// Mac Stuff // Mac Stuff
if (step.target.isDarwin()) { if (step.target.isDarwin()) {
step.addPackage(objc.pkg); step.addModule("objc", objc.module(b));
step.addPackage(macos.pkg); step.addModule("macos", macos.module(b));
_ = try macos.link(b, step, .{}); _ = try macos.link(b, step, .{});
} }
@ -309,7 +321,7 @@ fn addDeps(
step.addCSourceFile("vendor/glad/src/gl.c", &.{}); step.addCSourceFile("vendor/glad/src/gl.c", &.{});
// Tracy // Tracy
step.addPackage(tracylib.pkg); step.addModule("tracy", tracylib.module(b));
if (tracy) { if (tracy) {
var tracy_step = try tracylib.link(b, step); var tracy_step = try tracylib.link(b, step);
system_sdk.include(b, tracy_step, .{}); system_sdk.include(b, tracy_step, .{});
@ -400,7 +412,7 @@ fn addDeps(
const libxml2_lib = try libxml2.create( const libxml2_lib = try libxml2.create(
b, b,
step.target, step.target,
step.build_mode, step.optimize,
.{ .lzma = false, .zlib = false }, .{ .lzma = false, .zlib = false },
); );
libxml2_lib.link(step); libxml2_lib.link(step);
@ -431,7 +443,7 @@ fn addDeps(
fn benchSteps( fn benchSteps(
b: *std.build.Builder, b: *std.build.Builder,
target: std.zig.CrossTarget, target: std.zig.CrossTarget,
mode: std.builtin.Mode, optimize: std.builtin.Mode,
) !void { ) !void {
// Open the directory ./src/bench // Open the directory ./src/bench
const c_dir_path = (comptime root()) ++ "/src/bench"; const c_dir_path = (comptime root()) ++ "/src/bench";
@ -457,9 +469,12 @@ fn benchSteps(
// Executable builder. // Executable builder.
const bin_name = try std.fmt.allocPrint(b.allocator, "bench-{s}", .{name}); const bin_name = try std.fmt.allocPrint(b.allocator, "bench-{s}", .{name});
const c_exe = b.addExecutable(bin_name, path); const c_exe = b.addExecutable(.{
c_exe.setTarget(target); .name = bin_name,
c_exe.setBuildMode(mode); .root_source_file = .{ .path = path },
.target = target,
.optimize = optimize,
});
c_exe.setMainPkgPath("./src"); c_exe.setMainPkgPath("./src");
c_exe.install(); c_exe.install();
try addDeps(b, c_exe, true); try addDeps(b, c_exe, true);
@ -469,7 +484,7 @@ fn benchSteps(
fn conformanceSteps( fn conformanceSteps(
b: *std.build.Builder, b: *std.build.Builder,
target: std.zig.CrossTarget, target: std.zig.CrossTarget,
mode: std.builtin.Mode, optimize: std.builtin.Mode,
) !std.StringHashMap(*LibExeObjStep) { ) !std.StringHashMap(*LibExeObjStep) {
var map = std.StringHashMap(*LibExeObjStep).init(b.allocator); var map = std.StringHashMap(*LibExeObjStep).init(b.allocator);
@ -493,9 +508,12 @@ fn conformanceSteps(
}); });
// Executable builder. // Executable builder.
const c_exe = b.addExecutable(name, path); const c_exe = b.addExecutable(.{
c_exe.setTarget(target); .name = name,
c_exe.setBuildMode(mode); .root_source_file = .{ .path = path },
.target = target,
.optimize = optimize,
});
c_exe.setOutputDir("zig-out/bin/conformance"); c_exe.setOutputDir("zig-out/bin/conformance");
c_exe.install(); c_exe.install();

View File

@ -8,10 +8,11 @@ const include_path_self = thisDir();
pub const include_paths = .{ include_path, include_path_self }; pub const include_paths = .{ include_path, include_path_self };
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "fontconfig", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -36,7 +37,7 @@ pub const Options = struct {
}; };
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -48,14 +49,16 @@ pub fn link(
} }
pub fn buildFontconfig( pub fn buildFontconfig(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("fontconfig", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "fontconfig",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -7,10 +7,11 @@ pub const include_path_self = thisDir();
pub const include_paths = .{ include_path, include_path_self }; pub const include_paths = .{ include_path, include_path_self };
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "freetype", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -34,7 +35,7 @@ pub const Options = struct {
}; };
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -46,14 +47,16 @@ pub fn link(
} }
pub fn buildFreetype( pub fn buildFreetype(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("freetype", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "freetype",
lib.setBuildMode(step.build_mode); .target = target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -8,11 +8,15 @@ const include_path = root ++ "src/";
pub const include_paths = .{include_path}; pub const include_paths = .{include_path};
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "harfbuzz", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
.dependencies = &.{ freetypepkg.pkg, macospkg.pkg }, .dependencies = &.{
}; .{ .name = "freetype", .module = freetypepkg.module(b) },
.{ .name = "macos", .module = macospkg.module(b) },
},
});
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -34,7 +38,7 @@ pub const Options = struct {
}; };
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -45,13 +49,15 @@ pub fn link(
} }
pub fn buildHarfbuzz( pub fn buildHarfbuzz(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const lib = b.addStaticLibrary("harfbuzz", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "harfbuzz",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -8,10 +8,11 @@ pub const include_paths = [_][]const u8{
root ++ "imgui/backends", root ++ "imgui/backends",
}; };
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "imgui", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -30,7 +31,7 @@ pub const Options = struct {
}; };
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -41,14 +42,16 @@ pub fn link(
} }
pub fn buildImgui( pub fn buildImgui(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("imgui", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "imgui",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
inline for (include_paths) |path| lib.addIncludePath(path); inline for (include_paths) |path| lib.addIncludePath(path);

View File

@ -26,7 +26,7 @@ pub const Options = struct {
}; };
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -37,14 +37,16 @@ pub fn link(
} }
pub fn buildLib( pub fn buildLib(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("png", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "png",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -1,10 +1,11 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "macos", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -13,7 +14,7 @@ fn thisDir() []const u8 {
pub const Options = struct {}; pub const Options = struct {};
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -21,7 +22,11 @@ pub fn link(
var flags = std.ArrayList([]const u8).init(b.allocator); var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit(); defer flags.deinit();
const lib = b.addStaticLibrary("macos", null); const lib = b.addStaticLibrary(.{
.name = "macos",
.target = step.target,
.optimize = step.optimize,
});
step.addCSourceFile(comptime thisDir() ++ "/os/log.c", flags.items); step.addCSourceFile(comptime thisDir() ++ "/os/log.c", flags.items);
step.addCSourceFile(comptime thisDir() ++ "/text/ext.c", flags.items); step.addCSourceFile(comptime thisDir() ++ "/text/ext.c", flags.items);
step.linkFramework("CoreFoundation"); step.linkFramework("CoreFoundation");

View File

@ -8,10 +8,11 @@ const include_path_self = thisDir();
pub const include_paths = .{ include_path, include_path_self }; pub const include_paths = .{ include_path, include_path_self };
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "pixman", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -19,7 +20,7 @@ fn thisDir() []const u8 {
pub const Options = struct {}; pub const Options = struct {};
pub fn build(b: *std.build.Builder) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
@ -35,7 +36,7 @@ pub fn build(b: *std.build.Builder) !void {
} }
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -47,16 +48,18 @@ pub fn link(
} }
pub fn buildPixman( pub fn buildPixman(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
_ = opt; _ = opt;
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("pixman", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "pixman",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -6,10 +6,11 @@ pub const include_paths = [_][]const u8{
root, root,
}; };
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "stb_image_resize", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
@ -18,7 +19,7 @@ fn thisDir() []const u8 {
pub const Options = struct {}; pub const Options = struct {};
pub fn link( pub fn link(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
@ -29,15 +30,17 @@ pub fn link(
} }
pub fn buildStbImageResize( pub fn buildStbImageResize(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
opt: Options, opt: Options,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
_ = opt; _ = opt;
const lib = b.addStaticLibrary("stb_image_resize", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "stb_image_resize",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
inline for (include_paths) |path| lib.addIncludePath(path); inline for (include_paths) |path| lib.addIncludePath(path);

View File

@ -3,16 +3,17 @@ const std = @import("std");
/// Directories with our includes. /// Directories with our includes.
const root = thisDir() ++ "../../../vendor/tracy/"; const root = thisDir() ++ "../../../vendor/tracy/";
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "tracy", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/tracy.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/tracy.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
} }
pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep) !*std.build.LibExeObjStep { pub fn link(b: *std.Build, step: *std.build.LibExeObjStep) !*std.build.LibExeObjStep {
const tracy = try buildTracy(b, step); const tracy = try buildTracy(b, step);
step.linkLibrary(tracy); step.linkLibrary(tracy);
step.addIncludePath(root); step.addIncludePath(root);
@ -20,13 +21,15 @@ pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep) !*std.build.L
} }
pub fn buildTracy( pub fn buildTracy(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const target = step.target; const target = step.target;
const lib = b.addStaticLibrary("tracy", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "tracy",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
var flags = std.ArrayList([]const u8).init(b.allocator); var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit(); defer flags.deinit();

View File

@ -6,16 +6,17 @@ const include_path = root;
pub const include_paths = .{include_path}; pub const include_paths = .{include_path};
pub const pkg = std.build.Pkg{ pub fn module(b: *std.Build) *std.build.Module {
.name = "utf8proc", return b.createModule(.{
.source = .{ .path = thisDir() ++ "/main.zig" }, .source_file = .{ .path = (comptime thisDir()) ++ "/main.zig" },
}; });
}
fn thisDir() []const u8 { fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
} }
pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep) !*std.build.LibExeObjStep { pub fn link(b: *std.Build, step: *std.build.LibExeObjStep) !*std.build.LibExeObjStep {
const lib = try buildLib(b, step); const lib = try buildLib(b, step);
step.linkLibrary(lib); step.linkLibrary(lib);
step.addIncludePath(include_path); step.addIncludePath(include_path);
@ -23,12 +24,14 @@ pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep) !*std.build.L
} }
pub fn buildLib( pub fn buildLib(
b: *std.build.Builder, b: *std.Build,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const lib = b.addStaticLibrary("utf8proc", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "utf8proc",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -26,9 +26,11 @@ pub fn buildLib(
b: *std.build.Builder, b: *std.build.Builder,
step: *std.build.LibExeObjStep, step: *std.build.LibExeObjStep,
) !*std.build.LibExeObjStep { ) !*std.build.LibExeObjStep {
const lib = b.addStaticLibrary("z", null); const lib = b.addStaticLibrary(.{
lib.setTarget(step.target); .name = "z",
lib.setBuildMode(step.build_mode); .target = step.target,
.optimize = step.optimize,
});
// Include // Include
lib.addIncludePath(include_path); lib.addIncludePath(include_path);

View File

@ -27,7 +27,7 @@ const log = std.log.scoped(.glfw);
pub const App = struct { pub const App = struct {
pub fn init() !App { pub fn init() !App {
try glfw.init(.{}); if (!glfw.init(.{})) return error.GlfwInitFailed;
return .{}; return .{};
} }
@ -39,13 +39,13 @@ pub const App = struct {
/// Wakeup the event loop. This should be able to be called from any thread. /// Wakeup the event loop. This should be able to be called from any thread.
pub fn wakeup(self: App) !void { pub fn wakeup(self: App) !void {
_ = self; _ = self;
try glfw.postEmptyEvent(); glfw.postEmptyEvent();
} }
/// Wait for events in the event loop to process. /// Wait for events in the event loop to process.
pub fn wait(self: App) !void { pub fn wait(self: App) !void {
_ = self; _ = self;
try glfw.waitEvents(); glfw.waitEvents();
} }
}; };
@ -58,14 +58,14 @@ pub const Window = struct {
pub fn init(app: *const CoreApp, core_win: *CoreWindow) !Window { pub fn init(app: *const CoreApp, core_win: *CoreWindow) !Window {
// Create our window // Create our window
const win = try glfw.Window.create( const win = glfw.Window.create(
640, 640,
480, 480,
"ghostty", "ghostty",
null, null,
null, null,
Renderer.glfwWindowHints(), Renderer.glfwWindowHints(),
); ) orelse return glfw.mustGetErrorCode();
errdefer win.destroy(); errdefer win.destroy();
if (builtin.mode == .Debug) { if (builtin.mode == .Debug) {
@ -76,7 +76,7 @@ pub const Window = struct {
break :monitor glfw.Monitor.getPrimary().?; break :monitor glfw.Monitor.getPrimary().?;
}; };
const physical_size = monitor.getPhysicalSize(); const physical_size = monitor.getPhysicalSize();
const video_mode = try monitor.getVideoMode(); const video_mode = monitor.getVideoMode() orelse return glfw.mustGetErrorCode();
const physical_x_dpi = @intToFloat(f32, video_mode.getWidth()) / (@intToFloat(f32, physical_size.width_mm) / 25.4); const physical_x_dpi = @intToFloat(f32, video_mode.getWidth()) / (@intToFloat(f32, physical_size.width_mm) / 25.4);
const physical_y_dpi = @intToFloat(f32, video_mode.getHeight()) / (@intToFloat(f32, physical_size.height_mm) / 25.4); const physical_y_dpi = @intToFloat(f32, video_mode.getHeight()) / (@intToFloat(f32, physical_size.height_mm) / 25.4);
log.debug("physical dpi x={} y={}", .{ log.debug("physical dpi x={} y={}", .{
@ -99,13 +99,13 @@ pub const Window = struct {
} }
// Create the cursor // Create the cursor
const cursor = try glfw.Cursor.createStandard(.ibeam); const cursor = glfw.Cursor.createStandard(.ibeam) orelse return glfw.mustGetErrorCode();
errdefer cursor.destroy(); errdefer cursor.destroy();
if ((comptime !builtin.target.isDarwin()) or internal_os.macosVersionAtLeast(13, 0, 0)) { if ((comptime !builtin.target.isDarwin()) or internal_os.macosVersionAtLeast(13, 0, 0)) {
// We only set our cursor if we're NOT on Mac, or if we are then the // We only set our cursor if we're NOT on Mac, or if we are then the
// macOS version is >= 13 (Ventura). On prior versions, glfw crashes // macOS version is >= 13 (Ventura). On prior versions, glfw crashes
// since we use a tab group. // since we use a tab group.
try win.setCursor(cursor); win.setCursor(cursor);
} }
// Set our callbacks // Set our callbacks
@ -178,7 +178,7 @@ pub const Window = struct {
/// to use this more. i.e. you can't set max width but no max height, /// to use this more. i.e. you can't set max width but no max height,
/// or no mins. /// or no mins.
pub fn setSizeLimits(self: *Window, min: apprt.WindowSize, max_: ?apprt.WindowSize) !void { pub fn setSizeLimits(self: *Window, min: apprt.WindowSize, max_: ?apprt.WindowSize) !void {
try self.window.setSizeLimits(.{ self.window.setSizeLimits(.{
.width = min.width, .width = min.width,
.height = min.height, .height = min.height,
}, if (max_) |max| .{ }, if (max_) |max| .{
@ -192,7 +192,7 @@ pub const Window = struct {
/// Returns the content scale for the created window. /// Returns the content scale for the created window.
pub fn getContentScale(self: *const Window) !apprt.ContentScale { pub fn getContentScale(self: *const Window) !apprt.ContentScale {
const scale = try self.window.getContentScale(); const scale = self.window.getContentScale();
return apprt.ContentScale{ .x = scale.x_scale, .y = scale.y_scale }; return apprt.ContentScale{ .x = scale.x_scale, .y = scale.y_scale };
} }
@ -200,18 +200,14 @@ pub const Window = struct {
/// not match screen coordinate size but we should be able to convert /// not match screen coordinate size but we should be able to convert
/// back and forth using getContentScale. /// back and forth using getContentScale.
pub fn getSize(self: *const Window) !apprt.WindowSize { pub fn getSize(self: *const Window) !apprt.WindowSize {
const size = self.window.getFramebufferSize() catch |err| err: { const size = self.window.getFramebufferSize();
log.err("error querying window size in pixels, will use screen size err={}", .{err});
break :err try self.window.getSize();
};
return apprt.WindowSize{ .width = size.width, .height = size.height }; return apprt.WindowSize{ .width = size.width, .height = size.height };
} }
/// Returns the cursor position in scaled pixels relative to the /// Returns the cursor position in scaled pixels relative to the
/// upper-left of the window. /// upper-left of the window.
pub fn getCursorPos(self: *const Window) !apprt.CursorPos { pub fn getCursorPos(self: *const Window) !apprt.CursorPos {
const unscaled_pos = try self.window.getCursorPos(); const unscaled_pos = self.window.getCursorPos();
const pos = try self.cursorPosToPixels(unscaled_pos); const pos = try self.cursorPosToPixels(unscaled_pos);
return apprt.CursorPos{ return apprt.CursorPos{
.x = @floatCast(f32, pos.xpos), .x = @floatCast(f32, pos.xpos),
@ -232,7 +228,7 @@ pub const Window = struct {
/// Set the title of the window. /// Set the title of the window.
pub fn setTitle(self: *Window, slice: [:0]const u8) !void { pub fn setTitle(self: *Window, slice: [:0]const u8) !void {
try self.window.setTitle(slice.ptr); self.window.setTitle(slice.ptr);
} }
/// Read the clipboard. The windowing system is responsible for allocating /// Read the clipboard. The windowing system is responsible for allocating
@ -240,13 +236,13 @@ pub const Window = struct {
/// time getClipboardString is called. /// time getClipboardString is called.
pub fn getClipboardString(self: *const Window) ![:0]const u8 { pub fn getClipboardString(self: *const Window) ![:0]const u8 {
_ = self; _ = self;
return try glfw.getClipboardString(); return glfw.getClipboardString() orelse return glfw.mustGetErrorCode();
} }
/// Set the clipboard. /// Set the clipboard.
pub fn setClipboardString(self: *const Window, val: [:0]const u8) !void { pub fn setClipboardString(self: *const Window, val: [:0]const u8) !void {
_ = self; _ = self;
try glfw.setClipboardString(val); glfw.setClipboardString(val);
} }
/// The cursor position from glfw directly is in screen coordinates but /// The cursor position from glfw directly is in screen coordinates but
@ -255,8 +251,8 @@ pub const Window = struct {
// The cursor position is in screen coordinates but we // The cursor position is in screen coordinates but we
// want it in pixels. we need to get both the size of the // want it in pixels. we need to get both the size of the
// window in both to get the ratio to make the conversion. // window in both to get the ratio to make the conversion.
const size = try self.window.getSize(); const size = self.window.getSize();
const fb_size = try self.window.getFramebufferSize(); const fb_size = self.window.getFramebufferSize();
// If our framebuffer and screen are the same, then there is no scaling // If our framebuffer and screen are the same, then there is no scaling
// happening and we can short-circuit by returning the pos as-is. // happening and we can short-circuit by returning the pos as-is.

View File

@ -192,17 +192,17 @@ pub const std_options = struct {
} }
}; };
fn glfwErrorCallback(code: glfw.Error, desc: [:0]const u8) void { fn glfwErrorCallback(code: glfw.ErrorCode, desc: [:0]const u8) void {
std.log.warn("glfw error={} message={s}", .{ code, desc }); std.log.warn("glfw error={} message={s}", .{ code, desc });
// Workaround for: https://github.com/ocornut/imgui/issues/5908 // Workaround for: https://github.com/ocornut/imgui/issues/5908
// If we get an invalid value with "scancode" in the message we assume // If we get an invalid value with "scancode" in the message we assume
// it is from the glfw key callback that imgui sets and we clear the // it is from the glfw key callback that imgui sets and we clear the
// error so that our future code doesn't crash. // error so that our future code doesn't crash.
if (code == glfw.Error.InvalidValue and if (code == glfw.ErrorCode.InvalidValue and
std.mem.indexOf(u8, desc, "scancode") != null) std.mem.indexOf(u8, desc, "scancode") != null)
{ {
glfw.errors.getError() catch {}; _ = glfw.getError();
} }
} }

View File

@ -423,10 +423,9 @@ pub fn threadEnter(self: *const OpenGL, win: apprt.runtime.Window) !void {
// ensures that the context switches over to our thread. Important: // ensures that the context switches over to our thread. Important:
// the prior thread MUST have detached the context prior to calling // the prior thread MUST have detached the context prior to calling
// this entrypoint. // this entrypoint.
try glfw.makeContextCurrent(win.window); glfw.makeContextCurrent(win.window);
errdefer glfw.makeContextCurrent(null) catch |err| errdefer glfw.makeContextCurrent(null);
log.warn("failed to cleanup OpenGL context err={}", .{err}); glfw.swapInterval(1);
try glfw.swapInterval(1);
// Load OpenGL bindings. This API is context-aware so this sets // Load OpenGL bindings. This API is context-aware so this sets
// a threadlocal context for these pointers. // a threadlocal context for these pointers.
@ -443,7 +442,7 @@ pub fn threadExit(self: *const OpenGL) void {
_ = self; _ = self;
gl.glad.unload(); gl.glad.unload();
glfw.makeContextCurrent(null) catch {}; glfw.makeContextCurrent(null);
} }
/// Callback when the focus changes for the terminal this is rendering. /// Callback when the focus changes for the terminal this is rendering.
@ -641,7 +640,7 @@ pub fn render(
} }
// Swap our window buffers // Swap our window buffers
try win.window.swapBuffers(); win.window.swapBuffers();
} }
/// rebuildCells rebuilds all the GPU cells from our CPU state. This is a /// rebuildCells rebuilds all the GPU cells from our CPU state. This is a

2
vendor/libxev vendored

@ -1 +1 @@
Subproject commit f578d81ebe60d3afe6593771f10cf650e4d891cb Subproject commit 62f25af92c666a0b0771b9d35719b88a342a2ced

2
vendor/mach vendored

@ -1 +1 @@
Subproject commit c9793a4666d21608b1b28d0b67aaa7f7fd8b8031 Subproject commit 6ebeb5ea854ebfb023653656094d124aaf1c18b1

2
vendor/zig-js vendored

@ -1 +1 @@
Subproject commit c89c1965cc6bf6ede97c1b891b624ce5282853d1 Subproject commit ff405f62ce9990f88a8eabea4156fc1cafa0352a

2
vendor/zig-libxml2 vendored

@ -1 +1 @@
Subproject commit 2fad039cd983084b615347333790680983c2f4d4 Subproject commit eabfcf3a0b3ca319693d3e5991098a77dace5e9b

2
vendor/zig-objc vendored

@ -1 +1 @@
Subproject commit 4f5eda096c327a6943c834762cead4d1c9db2366 Subproject commit 1ebffc81ef7265ed6c6823370b2e2aaaee6bd860