build: lower build.zig dependencies to improve caching (#8798)
This is stomping towards minimizing our build.zig dependencies so that it can be cached more often. Right now, touching almost any file in the project forces the build.zig to rebuild which is destroying my productivity. The first set of work is to move all our completion and syntax file generation into a data generator exe, e.g. vim, zsh, fish, etc. This might seem like just shuffling bits but it results in a real tangible improvement: when you run `zig build test`, we no longer have to rebuild our `build.zig` when you for example... modify a CLI action. This is just a small improvement. Our build.zig depends on way too much stuff, so this PR will be draft while I continue to use commits to separate out scopes of change.pull/8802/head
commit
944f206b76
|
|
@ -404,91 +404,6 @@ pub fn getData(self: Command, comptime DT: type) ?*DT {
|
|||
return if (self.data) |ptr| @ptrCast(@alignCast(ptr)) else null;
|
||||
}
|
||||
|
||||
/// Search for "cmd" in the PATH and return the absolute path. This will
|
||||
/// always allocate if there is a non-null result. The caller must free the
|
||||
/// resulting value.
|
||||
pub fn expandPath(alloc: Allocator, cmd: []const u8) !?[]u8 {
|
||||
// If the command already contains a slash, then we return it as-is
|
||||
// because it is assumed to be absolute or relative.
|
||||
if (std.mem.indexOfScalar(u8, cmd, '/') != null) {
|
||||
return try alloc.dupe(u8, cmd);
|
||||
}
|
||||
|
||||
const PATH = switch (builtin.os.tag) {
|
||||
.windows => blk: {
|
||||
const win_path = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null;
|
||||
const path = try std.unicode.utf16LeToUtf8Alloc(alloc, win_path);
|
||||
break :blk path;
|
||||
},
|
||||
else => std.posix.getenvZ("PATH") orelse return null,
|
||||
};
|
||||
defer if (builtin.os.tag == .windows) alloc.free(PATH);
|
||||
|
||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||
var it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter);
|
||||
var seen_eacces = false;
|
||||
while (it.next()) |search_path| {
|
||||
// We need enough space in our path buffer to store this
|
||||
const path_len = search_path.len + cmd.len + 1;
|
||||
if (path_buf.len < path_len) return error.PathTooLong;
|
||||
|
||||
// Copy in the full path
|
||||
@memcpy(path_buf[0..search_path.len], search_path);
|
||||
path_buf[search_path.len] = std.fs.path.sep;
|
||||
@memcpy(path_buf[search_path.len + 1 ..][0..cmd.len], cmd);
|
||||
path_buf[path_len] = 0;
|
||||
const full_path = path_buf[0..path_len :0];
|
||||
|
||||
// Stat it
|
||||
const f = std.fs.cwd().openFile(
|
||||
full_path,
|
||||
.{},
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => continue,
|
||||
error.AccessDenied => {
|
||||
// Accumulate this and return it later so we can try other
|
||||
// paths that we have access to.
|
||||
seen_eacces = true;
|
||||
continue;
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
defer f.close();
|
||||
const stat = try f.stat();
|
||||
if (stat.kind != .directory and isExecutable(stat.mode)) {
|
||||
return try alloc.dupe(u8, full_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (seen_eacces) return error.AccessDenied;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
fn isExecutable(mode: std.fs.File.Mode) bool {
|
||||
if (builtin.os.tag == .windows) return true;
|
||||
return mode & 0o0111 != 0;
|
||||
}
|
||||
|
||||
// `uname -n` is the *nix equivalent of `hostname.exe` on Windows
|
||||
test "expandPath: hostname" {
|
||||
const executable = if (builtin.os.tag == .windows) "hostname.exe" else "uname";
|
||||
const path = (try expandPath(testing.allocator, executable)).?;
|
||||
defer testing.allocator.free(path);
|
||||
try testing.expect(path.len > executable.len);
|
||||
}
|
||||
|
||||
test "expandPath: does not exist" {
|
||||
const path = try expandPath(testing.allocator, "thisreallyprobablydoesntexist123");
|
||||
try testing.expect(path == null);
|
||||
}
|
||||
|
||||
test "expandPath: slash" {
|
||||
const path = (try expandPath(testing.allocator, "foo/env")).?;
|
||||
defer testing.allocator.free(path);
|
||||
try testing.expect(path.len == 7);
|
||||
}
|
||||
|
||||
// Copied from Zig. This is a publicly exported function but there is no
|
||||
// way to get it from the std package.
|
||||
fn createNullDelimitedEnvMap(arena: mem.Allocator, env_map: *const EnvMap) ![:null]?[*:0]u8 {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ pub const embedded = @import("apprt/embedded.zig");
|
|||
pub const surface = @import("apprt/surface.zig");
|
||||
|
||||
pub const Action = action.Action;
|
||||
pub const Runtime = @import("apprt/runtime.zig").Runtime;
|
||||
pub const Target = action.Target;
|
||||
|
||||
pub const ContentScale = structs.ContentScale;
|
||||
|
|
@ -51,30 +52,6 @@ pub const runtime = switch (build_config.artifact) {
|
|||
pub const App = runtime.App;
|
||||
pub const Surface = runtime.Surface;
|
||||
|
||||
/// Runtime is the runtime to use for Ghostty. All runtimes do not provide
|
||||
/// equivalent feature sets.
|
||||
pub const Runtime = enum {
|
||||
/// Will not produce an executable at all when `zig build` is called.
|
||||
/// This is only useful if you're only interested in the lib only (macOS).
|
||||
none,
|
||||
|
||||
/// GTK4. Rich windowed application. This uses a full GObject-based
|
||||
/// approach to building the application.
|
||||
gtk,
|
||||
|
||||
pub fn default(target: std.Target) Runtime {
|
||||
return switch (target.os.tag) {
|
||||
// The Linux and FreeBSD default is GTK because it is a full
|
||||
// featured application.
|
||||
.linux, .freebsd => .gtk,
|
||||
// Otherwise, we do NONE so we don't create an exe and we create
|
||||
// libghostty. On macOS, Xcode is used to build the app that links
|
||||
// to libghostty.
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
test {
|
||||
_ = Runtime;
|
||||
_ = runtime;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
const std = @import("std");
|
||||
|
||||
/// Runtime is the runtime to use for Ghostty. All runtimes do not provide
|
||||
/// equivalent feature sets.
|
||||
pub const Runtime = enum {
|
||||
/// Will not produce an executable at all when `zig build` is called.
|
||||
/// This is only useful if you're only interested in the lib only (macOS).
|
||||
none,
|
||||
|
||||
/// GTK4. Rich windowed application. This uses a full GObject-based
|
||||
/// approach to building the application.
|
||||
gtk,
|
||||
|
||||
pub fn default(target: std.Target) Runtime {
|
||||
return switch (target.os.tag) {
|
||||
// The Linux and FreeBSD default is GTK because it is a full
|
||||
// featured application.
|
||||
.linux, .freebsd => .gtk,
|
||||
// Otherwise, we do NONE so we don't create an exe and we create
|
||||
// libghostty. On macOS, Xcode is used to build the app that links
|
||||
// to libghostty.
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
test {
|
||||
_ = Runtime;
|
||||
}
|
||||
|
|
@ -5,12 +5,12 @@ const Config = @This();
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const apprt = @import("../apprt.zig");
|
||||
const font = @import("../font/main.zig");
|
||||
const rendererpkg = @import("../renderer.zig");
|
||||
const Command = @import("../Command.zig");
|
||||
const ApprtRuntime = @import("../apprt/runtime.zig").Runtime;
|
||||
const FontBackend = @import("../font/backend.zig").Backend;
|
||||
const RendererBackend = @import("../renderer/backend.zig").Backend;
|
||||
const XCFramework = @import("GhosttyXCFramework.zig");
|
||||
const WasmTarget = @import("../os/wasm/target.zig").Target;
|
||||
const expandPath = @import("../os/path.zig").expand;
|
||||
|
||||
const gtk = @import("gtk.zig");
|
||||
const GitVersion = @import("GitVersion.zig");
|
||||
|
|
@ -29,9 +29,9 @@ xcframework_target: XCFramework.Target = .universal,
|
|||
wasm_target: WasmTarget,
|
||||
|
||||
/// Comptime interfaces
|
||||
app_runtime: apprt.Runtime = .none,
|
||||
renderer: rendererpkg.Impl = .opengl,
|
||||
font_backend: font.Backend = .freetype,
|
||||
app_runtime: ApprtRuntime = .none,
|
||||
renderer: RendererBackend = .opengl,
|
||||
font_backend: FontBackend = .freetype,
|
||||
|
||||
/// Feature flags
|
||||
x11: bool = false,
|
||||
|
|
@ -126,22 +126,22 @@ pub fn init(b: *std.Build) !Config {
|
|||
//---------------------------------------------------------------
|
||||
// Comptime Interfaces
|
||||
config.font_backend = b.option(
|
||||
font.Backend,
|
||||
FontBackend,
|
||||
"font-backend",
|
||||
"The font backend to use for discovery and rasterization.",
|
||||
) orelse font.Backend.default(target.result, wasm_target);
|
||||
) orelse FontBackend.default(target.result, wasm_target);
|
||||
|
||||
config.app_runtime = b.option(
|
||||
apprt.Runtime,
|
||||
ApprtRuntime,
|
||||
"app-runtime",
|
||||
"The app runtime to use. Not all values supported on all platforms.",
|
||||
) orelse apprt.Runtime.default(target.result);
|
||||
) orelse ApprtRuntime.default(target.result);
|
||||
|
||||
config.renderer = b.option(
|
||||
rendererpkg.Impl,
|
||||
RendererBackend,
|
||||
"renderer",
|
||||
"The app runtime to use. Not all values supported on all platforms.",
|
||||
) orelse rendererpkg.Impl.default(target.result, wasm_target);
|
||||
) orelse RendererBackend.default(target.result, wasm_target);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Feature Flags
|
||||
|
|
@ -332,7 +332,7 @@ pub fn init(b: *std.Build) !Config {
|
|||
if (system_package) break :emit_docs true;
|
||||
|
||||
// We only default to true if we can find pandoc.
|
||||
const path = Command.expandPath(b.allocator, "pandoc") catch
|
||||
const path = expandPath(b.allocator, "pandoc") catch
|
||||
break :emit_docs false;
|
||||
defer if (path) |p| b.allocator.free(p);
|
||||
break :emit_docs path != null;
|
||||
|
|
@ -446,9 +446,9 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void {
|
|||
step.addOption(bool, "wayland", self.wayland);
|
||||
step.addOption(bool, "sentry", self.sentry);
|
||||
step.addOption(bool, "i18n", self.i18n);
|
||||
step.addOption(apprt.Runtime, "app_runtime", self.app_runtime);
|
||||
step.addOption(font.Backend, "font_backend", self.font_backend);
|
||||
step.addOption(rendererpkg.Impl, "renderer", self.renderer);
|
||||
step.addOption(ApprtRuntime, "app_runtime", self.app_runtime);
|
||||
step.addOption(FontBackend, "font_backend", self.font_backend);
|
||||
step.addOption(RendererBackend, "renderer", self.renderer);
|
||||
step.addOption(ExeEntrypoint, "exe_entrypoint", self.exe_entrypoint);
|
||||
step.addOption(WasmTarget, "wasm_target", self.wasm_target);
|
||||
step.addOption(bool, "wasm_shared", self.wasm_shared);
|
||||
|
|
@ -503,9 +503,9 @@ pub fn fromOptions() Config {
|
|||
|
||||
.version = options.app_version,
|
||||
.flatpak = options.flatpak,
|
||||
.app_runtime = std.meta.stringToEnum(apprt.Runtime, @tagName(options.app_runtime)).?,
|
||||
.font_backend = std.meta.stringToEnum(font.Backend, @tagName(options.font_backend)).?,
|
||||
.renderer = std.meta.stringToEnum(rendererpkg.Impl, @tagName(options.renderer)).?,
|
||||
.app_runtime = std.meta.stringToEnum(ApprtRuntime, @tagName(options.app_runtime)).?,
|
||||
.font_backend = std.meta.stringToEnum(FontBackend, @tagName(options.font_backend)).?,
|
||||
.renderer = std.meta.stringToEnum(RendererBackend, @tagName(options.renderer)).?,
|
||||
.exe_entrypoint = std.meta.stringToEnum(ExeEntrypoint, @tagName(options.exe_entrypoint)).?,
|
||||
.wasm_target = std.meta.stringToEnum(WasmTarget, @tagName(options.wasm_target)).?,
|
||||
.wasm_shared = options.wasm_shared,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const std = @import("std");
|
|||
const builtin = @import("builtin");
|
||||
const Config = @import("Config.zig");
|
||||
const gresource = @import("../apprt/gtk/build/gresource.zig");
|
||||
const internal_os = @import("../os/main.zig");
|
||||
const locales = @import("../os/i18n_locales.zig").locales;
|
||||
|
||||
const domain = "com.mitchellh.ghostty";
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyI18n {
|
|||
var steps = std.ArrayList(*std.Build.Step).init(b.allocator);
|
||||
defer steps.deinit();
|
||||
|
||||
inline for (internal_os.i18n.locales) |locale| {
|
||||
inline for (locales) |locale| {
|
||||
// There is no encoding suffix in the LC_MESSAGES path on FreeBSD,
|
||||
// so we need to remove it from `locale` to have a correct destination string.
|
||||
// (/usr/local/share/locale/en_AU/LC_MESSAGES)
|
||||
|
|
@ -155,7 +155,7 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
|
|||
"po/" ++ domain ++ ".pot",
|
||||
);
|
||||
|
||||
inline for (internal_os.i18n.locales) |locale| {
|
||||
inline for (locales) |locale| {
|
||||
const msgmerge = b.addSystemCommand(&.{ "msgmerge", "--quiet", "--no-fuzzy-matching" });
|
||||
msgmerge.addFileArg(b.path("po/" ++ locale ++ ".po"));
|
||||
msgmerge.addFileArg(xgettext.captureStdOut());
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ const builtin = @import("builtin");
|
|||
const assert = std.debug.assert;
|
||||
const buildpkg = @import("main.zig");
|
||||
const Config = @import("Config.zig");
|
||||
const config_vim = @import("../config/vim.zig");
|
||||
const config_sublime_syntax = @import("../config/sublime_syntax.zig");
|
||||
const terminfo = @import("../terminfo/main.zig");
|
||||
const RunStep = std.Build.Step.Run;
|
||||
|
||||
steps: []*std.Build.Step,
|
||||
|
|
@ -16,6 +13,19 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
var steps = std.ArrayList(*std.Build.Step).init(b.allocator);
|
||||
errdefer steps.deinit();
|
||||
|
||||
// This is the exe used to generate some build data.
|
||||
const build_data_exe = b.addExecutable(.{
|
||||
.name = "ghostty-build-data",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/main_build_data.zig"),
|
||||
.target = b.graph.host,
|
||||
.strip = false,
|
||||
.omit_frame_pointer = false,
|
||||
.unwind_tables = .sync,
|
||||
}),
|
||||
});
|
||||
build_data_exe.linkLibC();
|
||||
|
||||
// Terminfo
|
||||
terminfo: {
|
||||
const os_tag = cfg.target.result.os.tag;
|
||||
|
|
@ -25,13 +35,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
"terminfo";
|
||||
|
||||
// Encode our terminfo
|
||||
var str = std.ArrayList(u8).init(b.allocator);
|
||||
defer str.deinit();
|
||||
try terminfo.ghostty.encode(str.writer());
|
||||
|
||||
// Write it
|
||||
var wf = b.addWriteFiles();
|
||||
const source = wf.add("ghostty.terminfo", str.items);
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+terminfo");
|
||||
const wf = b.addWriteFiles();
|
||||
const source = wf.addCopyFile(run.captureStdOut(), "ghostty.terminfo");
|
||||
|
||||
if (cfg.emit_terminfo) {
|
||||
const source_install = b.addInstallFile(
|
||||
|
|
@ -130,8 +137,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
|
||||
// Fish shell completions
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+fish");
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("ghostty.fish", buildpkg.fish_completions);
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "ghostty.fish");
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
|
|
@ -143,8 +152,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
|
||||
// zsh shell completions
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+zsh");
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("_ghostty", buildpkg.zsh_completions);
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "_ghostty");
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
|
|
@ -156,8 +167,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
|
||||
// bash shell completions
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+bash");
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("ghostty.bash", buildpkg.bash_completions);
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "ghostty.bash");
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
|
|
@ -167,39 +180,44 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
try steps.append(&install_step.step);
|
||||
}
|
||||
|
||||
// Vim plugin
|
||||
// Vim and Neovim plugin
|
||||
{
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("syntax/ghostty.vim", config_vim.syntax);
|
||||
_ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect);
|
||||
_ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin);
|
||||
_ = wf.add("compiler/ghostty.vim", config_vim.compiler);
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+vim-syntax");
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "syntax/ghostty.vim");
|
||||
}
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+vim-ftdetect");
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "ftdetect/ghostty.vim");
|
||||
}
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+vim-ftplugin");
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "ftplugin/ghostty.vim");
|
||||
}
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+vim-compiler");
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "compiler/ghostty.vim");
|
||||
}
|
||||
|
||||
const vim_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
.install_dir = .prefix,
|
||||
.install_subdir = "share/vim/vimfiles",
|
||||
});
|
||||
try steps.append(&install_step.step);
|
||||
}
|
||||
try steps.append(&vim_step.step);
|
||||
|
||||
// Neovim plugin
|
||||
// This is just a copy-paste of the Vim plugin, but using a Neovim subdir.
|
||||
// By default, Neovim doesn't look inside share/vim/vimfiles. Some distros
|
||||
// configure it to do that however. Fedora, does not as a counterexample.
|
||||
{
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("syntax/ghostty.vim", config_vim.syntax);
|
||||
_ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect);
|
||||
_ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin);
|
||||
_ = wf.add("compiler/ghostty.vim", config_vim.compiler);
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
const neovim_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
.install_dir = .prefix,
|
||||
.install_subdir = "share/nvim/site",
|
||||
});
|
||||
try steps.append(&install_step.step);
|
||||
try steps.append(&neovim_step.step);
|
||||
}
|
||||
|
||||
// Sublime syntax highlighting for bat cli tool
|
||||
|
|
@ -209,8 +227,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources {
|
|||
// the config file within the '~.config/bat' directory
|
||||
// (ex: --map-syntax "/Users/user/.config/ghostty/config:Ghostty Config").
|
||||
{
|
||||
const run = b.addRunArtifact(build_data_exe);
|
||||
run.addArg("+sublime");
|
||||
const wf = b.addWriteFiles();
|
||||
_ = wf.add("ghostty.sublime-syntax", config_sublime_syntax.syntax);
|
||||
_ = wf.addCopyFile(run.captureStdOut(), "ghostty.sublime-syntax");
|
||||
|
||||
const install_step = b.addInstallDirectory(.{
|
||||
.source_dir = wf.getDirectory(),
|
||||
|
|
|
|||
|
|
@ -28,10 +28,5 @@ pub const LipoStep = @import("LipoStep.zig");
|
|||
pub const MetallibStep = @import("MetallibStep.zig");
|
||||
pub const XCFrameworkStep = @import("XCFrameworkStep.zig");
|
||||
|
||||
// Shell completions
|
||||
pub const fish_completions = @import("fish_completions.zig").completions;
|
||||
pub const zsh_completions = @import("zsh_completions.zig").completions;
|
||||
pub const bash_completions = @import("bash_completions.zig").completions;
|
||||
|
||||
// Helpers
|
||||
pub const requireZig = @import("zig.zig").requireZig;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pub const exe_entrypoint = config.exe_entrypoint;
|
|||
pub const flatpak = options.flatpak;
|
||||
pub const app_runtime: apprt.Runtime = config.app_runtime;
|
||||
pub const font_backend: font.Backend = config.font_backend;
|
||||
pub const renderer: rendererpkg.Impl = config.renderer;
|
||||
pub const renderer: rendererpkg.Backend = config.renderer;
|
||||
pub const i18n: bool = config.i18n;
|
||||
|
||||
/// The bundle ID for the app. This is used in many places and is currently
|
||||
|
|
|
|||
|
|
@ -48,7 +48,4 @@ pub const Wasm = if (!builtin.target.cpu.arch.isWasm()) struct {} else @import("
|
|||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
|
||||
// Vim syntax file, not used at runtime but we want to keep it tested.
|
||||
_ = @import("config/vim.zig");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//! Fish completions.
|
||||
const std = @import("std");
|
||||
|
||||
const Config = @import("../config/Config.zig");
|
||||
|
|
@ -5,23 +6,23 @@ const Action = @import("../cli.zig").ghostty.Action;
|
|||
|
||||
/// A fish completions configuration that contains all the available commands
|
||||
/// and options.
|
||||
pub const completions = comptimeGenerateFishCompletions();
|
||||
pub const completions = comptimeGenerateCompletions();
|
||||
|
||||
fn comptimeGenerateFishCompletions() []const u8 {
|
||||
fn comptimeGenerateCompletions() []const u8 {
|
||||
comptime {
|
||||
@setEvalBranchQuota(50000);
|
||||
var counter = std.io.countingWriter(std.io.null_writer);
|
||||
try writeFishCompletions(&counter.writer());
|
||||
try writeCompletions(&counter.writer());
|
||||
|
||||
var buf: [counter.bytes_written]u8 = undefined;
|
||||
var stream = std.io.fixedBufferStream(&buf);
|
||||
try writeFishCompletions(stream.writer());
|
||||
try writeCompletions(stream.writer());
|
||||
const final = buf;
|
||||
return final[0..stream.getWritten().len];
|
||||
}
|
||||
}
|
||||
|
||||
fn writeFishCompletions(writer: anytype) !void {
|
||||
fn writeCompletions(writer: anytype) !void {
|
||||
{
|
||||
try writer.writeAll("set -l commands \"");
|
||||
var count: usize = 0;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
const std = @import("std");
|
||||
const Config = @import("Config.zig");
|
||||
const Config = @import("../config/Config.zig");
|
||||
|
||||
const Template = struct {
|
||||
const header =
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
const std = @import("std");
|
||||
const Config = @import("Config.zig");
|
||||
const Config = @import("../config/Config.zig");
|
||||
|
||||
/// This is the associated Vim file as named by the variable.
|
||||
pub const syntax = comptimeGenSyntax();
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub const Backend = enum {
|
||||
const WasmTarget = @import("../os/wasm/target.zig").Target;
|
||||
|
||||
/// FreeType for font rendering with no font discovery enabled.
|
||||
freetype,
|
||||
|
||||
/// Fontconfig for font discovery and FreeType for font rendering.
|
||||
fontconfig_freetype,
|
||||
|
||||
/// CoreText for font discovery, rendering, and shaping (macOS).
|
||||
coretext,
|
||||
|
||||
/// CoreText for font discovery, FreeType for rendering, and
|
||||
/// HarfBuzz for shaping (macOS).
|
||||
coretext_freetype,
|
||||
|
||||
/// CoreText for font discovery and rendering, HarfBuzz for shaping
|
||||
coretext_harfbuzz,
|
||||
|
||||
/// CoreText for font discovery and rendering, no shaping.
|
||||
coretext_noshape,
|
||||
|
||||
/// Use the browser font system and the Canvas API (wasm). This limits
|
||||
/// the available fonts to browser fonts (anything Canvas natively
|
||||
/// supports).
|
||||
web_canvas,
|
||||
|
||||
/// Returns the default backend for a build environment. This is
|
||||
/// meant to be called at comptime by the build.zig script. To get the
|
||||
/// backend look at build_options.
|
||||
pub fn default(
|
||||
target: std.Target,
|
||||
wasm_target: WasmTarget,
|
||||
) Backend {
|
||||
if (target.cpu.arch == .wasm32) {
|
||||
return switch (wasm_target) {
|
||||
.browser => .web_canvas,
|
||||
};
|
||||
}
|
||||
|
||||
// macOS also supports "coretext_freetype" but there is no scenario
|
||||
// that is the default. It is only used by people who want to
|
||||
// self-compile Ghostty and prefer the freetype aesthetic.
|
||||
return if (target.os.tag.isDarwin()) .coretext else .fontconfig_freetype;
|
||||
}
|
||||
|
||||
// All the functions below can be called at comptime or runtime to
|
||||
// determine if we have a certain dependency.
|
||||
|
||||
pub fn hasFreetype(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.coretext_freetype,
|
||||
=> true,
|
||||
|
||||
.coretext,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasCoretext(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.coretext,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
=> true,
|
||||
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasFontconfig(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.fontconfig_freetype => true,
|
||||
|
||||
.freetype,
|
||||
.coretext,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasHarfbuzz(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
=> true,
|
||||
|
||||
.coretext,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -5,6 +5,7 @@ const build_config = @import("../build_config.zig");
|
|||
const library = @import("library.zig");
|
||||
|
||||
pub const Atlas = @import("Atlas.zig");
|
||||
pub const Backend = @import("backend.zig").Backend;
|
||||
pub const discovery = @import("discovery.zig");
|
||||
pub const embedded = @import("embedded.zig");
|
||||
pub const face = @import("face.zig");
|
||||
|
|
@ -48,115 +49,6 @@ pub const options: struct {
|
|||
.backend = if (builtin.target.cpu.arch.isWasm()) .web_canvas else build_config.font_backend,
|
||||
};
|
||||
|
||||
pub const Backend = enum {
|
||||
const WasmTarget = @import("../os/wasm/target.zig").Target;
|
||||
|
||||
/// FreeType for font rendering with no font discovery enabled.
|
||||
freetype,
|
||||
|
||||
/// Fontconfig for font discovery and FreeType for font rendering.
|
||||
fontconfig_freetype,
|
||||
|
||||
/// CoreText for font discovery, rendering, and shaping (macOS).
|
||||
coretext,
|
||||
|
||||
/// CoreText for font discovery, FreeType for rendering, and
|
||||
/// HarfBuzz for shaping (macOS).
|
||||
coretext_freetype,
|
||||
|
||||
/// CoreText for font discovery and rendering, HarfBuzz for shaping
|
||||
coretext_harfbuzz,
|
||||
|
||||
/// CoreText for font discovery and rendering, no shaping.
|
||||
coretext_noshape,
|
||||
|
||||
/// Use the browser font system and the Canvas API (wasm). This limits
|
||||
/// the available fonts to browser fonts (anything Canvas natively
|
||||
/// supports).
|
||||
web_canvas,
|
||||
|
||||
/// Returns the default backend for a build environment. This is
|
||||
/// meant to be called at comptime by the build.zig script. To get the
|
||||
/// backend look at build_options.
|
||||
pub fn default(
|
||||
target: std.Target,
|
||||
wasm_target: WasmTarget,
|
||||
) Backend {
|
||||
if (target.cpu.arch == .wasm32) {
|
||||
return switch (wasm_target) {
|
||||
.browser => .web_canvas,
|
||||
};
|
||||
}
|
||||
|
||||
// macOS also supports "coretext_freetype" but there is no scenario
|
||||
// that is the default. It is only used by people who want to
|
||||
// self-compile Ghostty and prefer the freetype aesthetic.
|
||||
return if (target.os.tag.isDarwin()) .coretext else .fontconfig_freetype;
|
||||
}
|
||||
|
||||
// All the functions below can be called at comptime or runtime to
|
||||
// determine if we have a certain dependency.
|
||||
|
||||
pub fn hasFreetype(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.coretext_freetype,
|
||||
=> true,
|
||||
|
||||
.coretext,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasCoretext(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.coretext,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
=> true,
|
||||
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasFontconfig(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.fontconfig_freetype => true,
|
||||
|
||||
.freetype,
|
||||
.coretext,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hasHarfbuzz(self: Backend) bool {
|
||||
return switch (self) {
|
||||
.freetype,
|
||||
.fontconfig_freetype,
|
||||
.coretext_freetype,
|
||||
.coretext_harfbuzz,
|
||||
=> true,
|
||||
|
||||
.coretext,
|
||||
.coretext_noshape,
|
||||
.web_canvas,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// The styles that a family can take.
|
||||
pub const Style = enum(u3) {
|
||||
regular = 0,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
const std = @import("std");
|
||||
const Config = @import("config/Config.zig");
|
||||
const Action = @import("cli.zig").ghostty.Action;
|
||||
const Action = @import("cli/ghostty.zig").Action;
|
||||
const KeybindAction = @import("input/Binding.zig").Action;
|
||||
|
||||
pub fn main() !void {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
//! This CLI is used to generate data that is used by the build process.
|
||||
//!
|
||||
//! We used to do this directly in our `build.zig` but the problem with
|
||||
//! that approach is that any changes to the dependencies of this data would
|
||||
//! force a rebuild of our build binary. If we're just doing something like
|
||||
//! running tests and not emitting any of the info below, then that is a
|
||||
//! complete waste.
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cli = @import("cli.zig");
|
||||
|
||||
pub const Action = enum {
|
||||
// Shell completions
|
||||
bash,
|
||||
fish,
|
||||
zsh,
|
||||
|
||||
// Editor syntax files
|
||||
sublime,
|
||||
@"vim-syntax",
|
||||
@"vim-ftdetect",
|
||||
@"vim-ftplugin",
|
||||
@"vim-compiler",
|
||||
|
||||
// Other
|
||||
terminfo,
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
const alloc = std.heap.c_allocator;
|
||||
const action_ = try cli.action.detectArgs(Action, alloc);
|
||||
const action = action_ orelse return error.NoAction;
|
||||
|
||||
// Our output always goes to stdout.
|
||||
const writer = std.io.getStdOut().writer();
|
||||
switch (action) {
|
||||
.bash => try writer.writeAll(@import("extra/bash.zig").completions),
|
||||
.fish => try writer.writeAll(@import("extra/fish.zig").completions),
|
||||
.zsh => try writer.writeAll(@import("extra/zsh.zig").completions),
|
||||
.sublime => try writer.writeAll(@import("extra/sublime.zig").syntax),
|
||||
.@"vim-syntax" => try writer.writeAll(@import("extra/vim.zig").syntax),
|
||||
.@"vim-ftdetect" => try writer.writeAll(@import("extra/vim.zig").ftdetect),
|
||||
.@"vim-ftplugin" => try writer.writeAll(@import("extra/vim.zig").ftplugin),
|
||||
.@"vim-compiler" => try writer.writeAll(@import("extra/vim.zig").compiler),
|
||||
.terminfo => try @import("terminfo/ghostty.zig").ghostty.encode(writer),
|
||||
}
|
||||
}
|
||||
|
|
@ -191,4 +191,11 @@ test {
|
|||
_ = @import("simd/main.zig");
|
||||
_ = @import("synthetic/main.zig");
|
||||
_ = @import("unicode/main.zig");
|
||||
|
||||
// Extra
|
||||
_ = @import("extra/bash.zig");
|
||||
_ = @import("extra/fish.zig");
|
||||
_ = @import("extra/sublime.zig");
|
||||
_ = @import("extra/vim.zig");
|
||||
_ = @import("extra/zsh.zig");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,59 +1,10 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("../build_config.zig");
|
||||
const locales = @import("i18n_locales.zig");
|
||||
|
||||
const log = std.log.scoped(.i18n);
|
||||
|
||||
/// Supported locales for the application. This must be kept up to date
|
||||
/// with the translations available in the `po/` directory; this is used
|
||||
/// by our build process as well runtime libghostty APIs.
|
||||
///
|
||||
/// The order also matters. For incomplete locale information (i.e. only
|
||||
/// a language code available), the first match is used. For example, if
|
||||
/// we know the user requested `zh` but has no script code, then we'd pick
|
||||
/// the first locale that matches `zh`.
|
||||
///
|
||||
/// For ordering, we prefer:
|
||||
///
|
||||
/// 1. The most common locales first, since there are places in the code
|
||||
/// where we do linear searches for a locale and we want to minimize
|
||||
/// the number of iterations for the common case.
|
||||
///
|
||||
/// 2. Alphabetical for otherwise equally common locales.
|
||||
///
|
||||
/// 3. Most preferred locale for a language without a country code.
|
||||
///
|
||||
/// Note for "most common" locales, this is subjective and based on
|
||||
/// the perceived userbase of Ghostty, which may not be representative
|
||||
/// of general populations or global language distribution. Also note
|
||||
/// that ordering may be weird when we first merge a new locale since
|
||||
/// we don't have a good way to determine this. We can always reorder
|
||||
/// with some data.
|
||||
pub const locales = [_][:0]const u8{
|
||||
"zh_CN.UTF-8",
|
||||
"de_DE.UTF-8",
|
||||
"fr_FR.UTF-8",
|
||||
"ja_JP.UTF-8",
|
||||
"nl_NL.UTF-8",
|
||||
"nb_NO.UTF-8",
|
||||
"ru_RU.UTF-8",
|
||||
"uk_UA.UTF-8",
|
||||
"pl_PL.UTF-8",
|
||||
"ko_KR.UTF-8",
|
||||
"mk_MK.UTF-8",
|
||||
"tr_TR.UTF-8",
|
||||
"id_ID.UTF-8",
|
||||
"es_BO.UTF-8",
|
||||
"es_AR.UTF-8",
|
||||
"pt_BR.UTF-8",
|
||||
"ca_ES.UTF-8",
|
||||
"it_IT.UTF-8",
|
||||
"bg_BG.UTF-8",
|
||||
"ga_IE.UTF-8",
|
||||
"hu_HU.UTF-8",
|
||||
"he_IL.UTF-8",
|
||||
};
|
||||
|
||||
/// Set for faster membership lookup of locales.
|
||||
pub const locales_map = map: {
|
||||
var kvs: [locales.len]struct { []const u8 } = undefined;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// NOTE: This is in a separate file because our build depends on it and
|
||||
// we want to minimize the transitive dependencies of the build binary
|
||||
// itself.
|
||||
|
||||
/// Supported locales for the application. This must be kept up to date
|
||||
/// with the translations available in the `po/` directory; this is used
|
||||
/// by our build process as well runtime libghostty APIs.
|
||||
///
|
||||
/// The order also matters. For incomplete locale information (i.e. only
|
||||
/// a language code available), the first match is used. For example, if
|
||||
/// we know the user requested `zh` but has no script code, then we'd pick
|
||||
/// the first locale that matches `zh`.
|
||||
///
|
||||
/// For ordering, we prefer:
|
||||
///
|
||||
/// 1. The most common locales first, since there are places in the code
|
||||
/// where we do linear searches for a locale and we want to minimize
|
||||
/// the number of iterations for the common case.
|
||||
///
|
||||
/// 2. Alphabetical for otherwise equally common locales.
|
||||
///
|
||||
/// 3. Most preferred locale for a language without a country code.
|
||||
///
|
||||
/// Note for "most common" locales, this is subjective and based on
|
||||
/// the perceived userbase of Ghostty, which may not be representative
|
||||
/// of general populations or global language distribution. Also note
|
||||
/// that ordering may be weird when we first merge a new locale since
|
||||
/// we don't have a good way to determine this. We can always reorder
|
||||
/// with some data.
|
||||
pub const locales = [_][:0]const u8{
|
||||
"zh_CN.UTF-8",
|
||||
"de_DE.UTF-8",
|
||||
"fr_FR.UTF-8",
|
||||
"ja_JP.UTF-8",
|
||||
"nl_NL.UTF-8",
|
||||
"nb_NO.UTF-8",
|
||||
"ru_RU.UTF-8",
|
||||
"uk_UA.UTF-8",
|
||||
"pl_PL.UTF-8",
|
||||
"ko_KR.UTF-8",
|
||||
"mk_MK.UTF-8",
|
||||
"tr_TR.UTF-8",
|
||||
"id_ID.UTF-8",
|
||||
"es_BO.UTF-8",
|
||||
"es_AR.UTF-8",
|
||||
"pt_BR.UTF-8",
|
||||
"ca_ES.UTF-8",
|
||||
"it_IT.UTF-8",
|
||||
"bg_BG.UTF-8",
|
||||
"ga_IE.UTF-8",
|
||||
"hu_HU.UTF-8",
|
||||
"he_IL.UTF-8",
|
||||
};
|
||||
|
|
@ -23,6 +23,7 @@ pub const args = @import("args.zig");
|
|||
pub const cgroup = @import("cgroup.zig");
|
||||
pub const hostname = @import("hostname.zig");
|
||||
pub const i18n = @import("i18n.zig");
|
||||
pub const path = @import("path.zig");
|
||||
pub const passwd = @import("passwd.zig");
|
||||
pub const xdg = @import("xdg.zig");
|
||||
pub const windows = @import("windows.zig");
|
||||
|
|
@ -65,6 +66,7 @@ pub const getKernelInfo = kernel_info.getKernelInfo;
|
|||
|
||||
test {
|
||||
_ = i18n;
|
||||
_ = path;
|
||||
|
||||
if (comptime builtin.os.tag == .linux) {
|
||||
_ = kernel_info;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const testing = std.testing;
|
||||
|
||||
/// Search for "cmd" in the PATH and return the absolute path. This will
|
||||
/// always allocate if there is a non-null result. The caller must free the
|
||||
/// resulting value.
|
||||
pub fn expand(alloc: Allocator, cmd: []const u8) !?[]u8 {
|
||||
// If the command already contains a slash, then we return it as-is
|
||||
// because it is assumed to be absolute or relative.
|
||||
if (std.mem.indexOfScalar(u8, cmd, '/') != null) {
|
||||
return try alloc.dupe(u8, cmd);
|
||||
}
|
||||
|
||||
const PATH = switch (builtin.os.tag) {
|
||||
.windows => blk: {
|
||||
const win_path = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse return null;
|
||||
const path = try std.unicode.utf16LeToUtf8Alloc(alloc, win_path);
|
||||
break :blk path;
|
||||
},
|
||||
else => std.posix.getenvZ("PATH") orelse return null,
|
||||
};
|
||||
defer if (builtin.os.tag == .windows) alloc.free(PATH);
|
||||
|
||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||
var it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter);
|
||||
var seen_eacces = false;
|
||||
while (it.next()) |search_path| {
|
||||
// We need enough space in our path buffer to store this
|
||||
const path_len = search_path.len + cmd.len + 1;
|
||||
if (path_buf.len < path_len) return error.PathTooLong;
|
||||
|
||||
// Copy in the full path
|
||||
@memcpy(path_buf[0..search_path.len], search_path);
|
||||
path_buf[search_path.len] = std.fs.path.sep;
|
||||
@memcpy(path_buf[search_path.len + 1 ..][0..cmd.len], cmd);
|
||||
path_buf[path_len] = 0;
|
||||
const full_path = path_buf[0..path_len :0];
|
||||
|
||||
// Stat it
|
||||
const f = std.fs.cwd().openFile(
|
||||
full_path,
|
||||
.{},
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => continue,
|
||||
error.AccessDenied => {
|
||||
// Accumulate this and return it later so we can try other
|
||||
// paths that we have access to.
|
||||
seen_eacces = true;
|
||||
continue;
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
defer f.close();
|
||||
const stat = try f.stat();
|
||||
if (stat.kind != .directory and isExecutable(stat.mode)) {
|
||||
return try alloc.dupe(u8, full_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (seen_eacces) return error.AccessDenied;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
fn isExecutable(mode: std.fs.File.Mode) bool {
|
||||
if (builtin.os.tag == .windows) return true;
|
||||
return mode & 0o0111 != 0;
|
||||
}
|
||||
|
||||
// `uname -n` is the *nix equivalent of `hostname.exe` on Windows
|
||||
test "expand: hostname" {
|
||||
const executable = if (builtin.os.tag == .windows) "hostname.exe" else "uname";
|
||||
const path = (try expand(testing.allocator, executable)).?;
|
||||
defer testing.allocator.free(path);
|
||||
try testing.expect(path.len > executable.len);
|
||||
}
|
||||
|
||||
test "expand: does not exist" {
|
||||
const path = try expand(testing.allocator, "thisreallyprobablydoesntexist123");
|
||||
try testing.expect(path == null);
|
||||
}
|
||||
|
||||
test "expand: slash" {
|
||||
const path = (try expand(testing.allocator, "foo/env")).?;
|
||||
defer testing.allocator.free(path);
|
||||
try testing.expect(path.len == 7);
|
||||
}
|
||||
|
|
@ -10,12 +10,12 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const build_config = @import("build_config.zig");
|
||||
const WasmTarget = @import("os/wasm/target.zig").Target;
|
||||
|
||||
const cursor = @import("renderer/cursor.zig");
|
||||
const message = @import("renderer/message.zig");
|
||||
const size = @import("renderer/size.zig");
|
||||
pub const shadertoy = @import("renderer/shadertoy.zig");
|
||||
pub const Backend = @import("renderer/backend.zig").Backend;
|
||||
pub const GenericRenderer = @import("renderer/generic.zig").Renderer;
|
||||
pub const Metal = @import("renderer/Metal.zig");
|
||||
pub const OpenGL = @import("renderer/OpenGL.zig");
|
||||
|
|
@ -33,27 +33,6 @@ pub const GridSize = size.GridSize;
|
|||
pub const Padding = size.Padding;
|
||||
pub const cursorStyle = cursor.style;
|
||||
|
||||
/// Possible implementations, used for build options.
|
||||
pub const Impl = enum {
|
||||
opengl,
|
||||
metal,
|
||||
webgl,
|
||||
|
||||
pub fn default(
|
||||
target: std.Target,
|
||||
wasm_target: WasmTarget,
|
||||
) Impl {
|
||||
if (target.cpu.arch == .wasm32) {
|
||||
return switch (wasm_target) {
|
||||
.browser => .webgl,
|
||||
};
|
||||
}
|
||||
|
||||
if (target.os.tag.isDarwin()) return .metal;
|
||||
return .opengl;
|
||||
}
|
||||
};
|
||||
|
||||
/// The implementation to use for the renderer. This is comptime chosen
|
||||
/// so that every build has exactly one renderer implementation.
|
||||
pub const Renderer = switch (build_config.renderer) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
const std = @import("std");
|
||||
const WasmTarget = @import("../os/wasm/target.zig").Target;
|
||||
|
||||
/// Possible implementations, used for build options.
|
||||
pub const Backend = enum {
|
||||
opengl,
|
||||
metal,
|
||||
webgl,
|
||||
|
||||
pub fn default(
|
||||
target: std.Target,
|
||||
wasm_target: WasmTarget,
|
||||
) Backend {
|
||||
if (target.cpu.arch == .wasm32) {
|
||||
return switch (wasm_target) {
|
||||
.browser => .webgl,
|
||||
};
|
||||
}
|
||||
|
||||
if (target.os.tag.isDarwin()) return .metal;
|
||||
return .opengl;
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue