can now use -Dfont-backend to choose the font backend to use

This commit is contained in:
Mitchell Hashimoto
2023-03-04 10:50:13 -08:00
parent 4e31f14f7b
commit 06035e2f95
4 changed files with 79 additions and 45 deletions

View File

@ -21,6 +21,7 @@ const utf8proc = @import("pkg/utf8proc/build.zig");
const zlib = @import("pkg/zlib/build.zig"); const zlib = @import("pkg/zlib/build.zig");
const tracylib = @import("pkg/tracy/build.zig"); const tracylib = @import("pkg/tracy/build.zig");
const system_sdk = @import("vendor/mach/libs/glfw/system_sdk.zig"); const system_sdk = @import("vendor/mach/libs/glfw/system_sdk.zig");
const font = @import("src/font/main.zig");
const WasmTarget = @import("src/os/wasm/target.zig").Target; const WasmTarget = @import("src/os/wasm/target.zig").Target;
const LibtoolStep = @import("src/build/LibtoolStep.zig"); const LibtoolStep = @import("src/build/LibtoolStep.zig");
const LipoStep = @import("src/build/LipoStep.zig"); const LipoStep = @import("src/build/LipoStep.zig");
@ -44,10 +45,9 @@ comptime {
// Build options, see the build options help for more info. // Build options, see the build options help for more info.
var tracy: bool = false; var tracy: bool = false;
var enable_coretext: bool = false;
var enable_fontconfig: bool = false;
var flatpak: bool = false; var flatpak: bool = false;
var app_runtime: apprt.Runtime = .none; var app_runtime: apprt.Runtime = .none;
var font_backend: font.Backend = .freetype;
pub fn build(b: *std.build.Builder) !void { pub fn build(b: *std.build.Builder) !void {
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
@ -62,6 +62,8 @@ pub fn build(b: *std.build.Builder) !void {
break :target result; break :target result;
}; };
const wasm_target: WasmTarget = .browser;
tracy = b.option( tracy = b.option(
bool, bool,
"tracy", "tracy",
@ -74,17 +76,11 @@ pub fn build(b: *std.build.Builder) !void {
"Build for Flatpak (integrates with Flatpak APIs). Only has an effect targeting Linux.", "Build for Flatpak (integrates with Flatpak APIs). Only has an effect targeting Linux.",
) orelse false; ) orelse false;
enable_coretext = b.option( font_backend = b.option(
bool, font.Backend,
"coretext", "font-backend",
"Enable coretext for font discovery (default true on macOS)", "The font backend to use for discovery and rasterization.",
) orelse target.isDarwin(); ) orelse font.Backend.default(target, wasm_target);
enable_fontconfig = b.option(
bool,
"fontconfig",
"Enable fontconfig for font discovery (default true on Linux)",
) orelse target.isLinux();
app_runtime = b.option( app_runtime = b.option(
apprt.Runtime, apprt.Runtime,
@ -131,9 +127,8 @@ pub fn build(b: *std.build.Builder) !void {
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, "flatpak", flatpak); exe_options.addOption(bool, "flatpak", flatpak);
exe_options.addOption(bool, "coretext", enable_coretext);
exe_options.addOption(bool, "fontconfig", enable_fontconfig);
exe_options.addOption(apprt.Runtime, "app_runtime", app_runtime); exe_options.addOption(apprt.Runtime, "app_runtime", app_runtime);
exe_options.addOption(font.Backend, "font_backend", font_backend);
// Exe // Exe
{ {
@ -263,7 +258,7 @@ pub fn build(b: *std.build.Builder) !void {
// wasm // wasm
{ {
// Build our Wasm target. // Build our Wasm target.
const wasm_target: std.zig.CrossTarget = .{ const wasm_crosstarget: std.zig.CrossTarget = .{
.cpu_arch = .wasm32, .cpu_arch = .wasm32,
.os_tag = .freestanding, .os_tag = .freestanding,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
@ -286,13 +281,12 @@ pub fn build(b: *std.build.Builder) !void {
// We want to support alternate wasm targets in the future (i.e. // We want to support alternate wasm targets in the future (i.e.
// server side) so we have this now although its hardcoded. // server side) so we have this now although its hardcoded.
const wasm_specific_target: WasmTarget = .browser; exe_options.addOption(WasmTarget, "wasm_target", wasm_target);
exe_options.addOption(WasmTarget, "wasm_target", wasm_specific_target);
const wasm = b.addSharedLibrary(.{ const wasm = b.addSharedLibrary(.{
.name = "ghostty-wasm", .name = "ghostty-wasm",
.root_source_file = .{ .path = "src/main_wasm.zig" }, .root_source_file = .{ .path = "src/main_wasm.zig" },
.target = wasm_target, .target = wasm_crosstarget,
.optimize = optimize, .optimize = optimize,
}); });
wasm.setOutputDir("zig-out"); wasm.setOutputDir("zig-out");
@ -320,7 +314,7 @@ pub fn build(b: *std.build.Builder) !void {
const main_test = b.addTest(.{ const main_test = b.addTest(.{
.name = "wasm-test", .name = "wasm-test",
.root_source_file = .{ .path = "src/main_wasm.zig" }, .root_source_file = .{ .path = "src/main_wasm.zig" },
.target = wasm_target, .target = wasm_crosstarget,
}); });
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);
@ -456,7 +450,7 @@ fn addDeps(
// We always need the Zig packages // We always need the Zig packages
// TODO: This can't be the right way to use the new Zig modules system, // TODO: This can't be the right way to use the new Zig modules system,
// so take a closer look at this again later. // so take a closer look at this again later.
if (enable_fontconfig) step.addModule("fontconfig", fontconfig.module(b)); if (font_backend.hasFontconfig()) step.addModule("fontconfig", fontconfig.module(b));
const mod_freetype = freetype.module(b); const mod_freetype = freetype.module(b);
const mod_macos = macos.module(b); const mod_macos = macos.module(b);
step.addModule("freetype", mod_freetype); step.addModule("freetype", mod_freetype);
@ -512,7 +506,7 @@ fn addDeps(
step.linkSystemLibrary("pixman-1"); step.linkSystemLibrary("pixman-1");
step.linkSystemLibrary("zlib"); step.linkSystemLibrary("zlib");
if (enable_fontconfig) step.linkSystemLibrary("fontconfig"); if (font_backend.hasFontconfig()) step.linkSystemLibrary("fontconfig");
} }
// Other dependencies, we may dynamically link // Other dependencies, we may dynamically link
@ -553,7 +547,7 @@ fn addDeps(
}, },
.coretext = .{ .coretext = .{
.enabled = enable_coretext, .enabled = font_backend.hasCoretext(),
}, },
}); });
system_sdk.include(b, harfbuzz_step, .{}); system_sdk.include(b, harfbuzz_step, .{});
@ -564,7 +558,7 @@ fn addDeps(
try static_libs.append(.{ .generated = &pixman_step.output_path_source }); try static_libs.append(.{ .generated = &pixman_step.output_path_source });
// Only Linux gets fontconfig // Only Linux gets fontconfig
if (enable_fontconfig) { if (font_backend.hasFontconfig()) {
// Libxml2 // Libxml2
const libxml2_lib = try libxml2.create( const libxml2_lib = try libxml2.create(
b, b,

View File

@ -7,6 +7,7 @@ const builtin = @import("builtin");
const options = @import("build_options"); const options = @import("build_options");
const assert = std.debug.assert; const assert = std.debug.assert;
const apprt = @import("apprt.zig"); const apprt = @import("apprt.zig");
const font = @import("font/main.zig");
/// The artifact we're producing. This can be used to determine if we're /// The artifact we're producing. This can be used to determine if we're
/// building a standalone exe, an embedded lib, etc. /// building a standalone exe, an embedded lib, etc.
@ -18,6 +19,12 @@ pub const app_runtime: apprt.Runtime = switch (artifact) {
else => std.meta.stringToEnum(apprt.Runtime, std.meta.tagName(options.app_runtime)).?, else => std.meta.stringToEnum(apprt.Runtime, std.meta.tagName(options.app_runtime)).?,
}; };
/// The font backend desired for the build.
pub const font_backend: font.Backend = std.meta.stringToEnum(
font.Backend,
std.meta.tagName(options.font_backend),
).?;
/// Whether our devmode UI is enabled or not. This requires imgui to be /// Whether our devmode UI is enabled or not. This requires imgui to be
/// compiled. /// compiled.
pub const devmode_enabled = artifact == .exe and app_runtime == .glfw; pub const devmode_enabled = artifact == .exe and app_runtime == .glfw;

View File

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const build_options = @import("build_options"); const build_config = @import("../build_config.zig");
pub const Atlas = @import("Atlas.zig"); pub const Atlas = @import("Atlas.zig");
pub const discovery = @import("discovery.zig"); pub const discovery = @import("discovery.zig");
@ -32,10 +32,12 @@ pub usingnamespace if (builtin.target.isWasm()) struct {
pub const options: struct { pub const options: struct {
backend: Backend, backend: Backend,
} = .{ } = .{
.backend = Backend.default(), .backend = build_config.font_backend,
}; };
pub const Backend = enum { pub const Backend = enum {
const WasmTarget = @import("../os/wasm/target.zig").Target;
/// FreeType for font rendering with no font discovery enabled. /// FreeType for font rendering with no font discovery enabled.
freetype, freetype,
@ -54,32 +56,62 @@ pub const Backend = enum {
web_canvas, web_canvas,
/// Returns the default backend for a build environment. This is /// Returns the default backend for a build environment. This is
/// meant to be called at comptime. /// meant to be called at comptime by the build.zig script. To get the
pub fn default() Backend { /// backend look at build_options.
const wasm_target = @import("../os/wasm/target.zig"); pub fn default(
if (wasm_target.target) |target| return switch (target) { target: std.zig.CrossTarget,
.browser => .web_canvas, wasm_target: WasmTarget,
}; ) Backend {
if (target.getCpuArch() == .wasm32) {
return switch (wasm_target) {
.browser => .web_canvas,
};
}
return if (build_options.coretext) return if (target.isDarwin()) darwin: {
.coretext_freetype // On macOS right now, the coretext renderer is still pretty buggy
else if (build_options.fontconfig) // so we default to coretext for font discovery and freetype for
.fontconfig_freetype // rasterization.
else break :darwin .coretext_freetype;
.freetype; } else .fontconfig_freetype;
} }
/// Helper that just returns true if we should be using freetype. This // All the functions below can be called at comptime or runtime to
/// is used for tests. // determine if we have a certain dependency.
pub fn freetype(self: Backend) bool {
pub fn hasFreetype(self: Backend) bool {
return switch (self) { return switch (self) {
.freetype, .fontconfig_freetype => true, .freetype,
.fontconfig_freetype,
.coretext_freetype,
=> true,
.coretext, .web_canvas => false, .coretext, .web_canvas => false,
}; };
} }
test "default can run at comptime" { pub fn hasCoretext(self: Backend) bool {
_ = comptime default(); return switch (self) {
.coretext,
.coretext_freetype,
=> true,
.freetype,
.fontconfig_freetype,
.web_canvas,
=> false,
};
}
pub fn hasFontconfig(self: Backend) bool {
return switch (self) {
.fontconfig_freetype => true,
.freetype,
.coretext,
.coretext_freetype,
.web_canvas,
=> false,
};
} }
}; };

View File

@ -129,8 +129,9 @@ pub const GlobalState = struct {
pub fn init(self: *GlobalState) void { pub fn init(self: *GlobalState) void {
// Output some debug information right away // Output some debug information right away
std.log.info("runtime={}", .{build_config.app_runtime}); std.log.info("runtime={}", .{build_config.app_runtime});
std.log.info("font_backend={}", .{build_config.font_backend});
std.log.info("dependency harfbuzz={s}", .{harfbuzz.versionString()}); std.log.info("dependency harfbuzz={s}", .{harfbuzz.versionString()});
if (options.fontconfig) { if (comptime build_config.font_backend.hasFontconfig()) {
std.log.info("dependency fontconfig={d}", .{fontconfig.version()}); std.log.info("dependency fontconfig={d}", .{fontconfig.version()});
} }
std.log.info("renderer={}", .{renderer.Renderer}); std.log.info("renderer={}", .{renderer.Renderer});