apprt/embedded: compile for Linux

This commit is contained in:
Mitchell Hashimoto
2024-01-18 08:44:56 -08:00
parent cb463edb84
commit df09c21103
4 changed files with 112 additions and 31 deletions

View File

@ -405,7 +405,7 @@ pub fn build(b: *std.Build) !void {
}
// App (Linux)
if (target.result.os.tag == .linux) {
if (target.result.os.tag == .linux and config.app_runtime != .none) {
// https://developer.gnome.org/documentation/guidelines/maintainer/integrating.html
// Desktop file so that we have an icon and other metadata
@ -428,6 +428,24 @@ pub fn build(b: *std.Build) !void {
b.installFile("images/icons/icon_256x256@2x@2x.png", "share/icons/hicolor/256x256@2/apps/com.mitchellh.ghostty.png");
}
// libghostty (non-Darwin)
if (!builtin.target.isDarwin() and config.app_runtime == .none) {
const lib = b.addSharedLibrary(.{
.name = "ghostty",
.root_source_file = .{ .path = "src/main_c.zig" },
.optimize = optimize,
.target = target,
});
lib.root_module.addOptions("build_options", exe_options);
_ = try addDeps(b, lib, config);
const lib_install = b.addInstallLibFile(
lib.getEmittedBin(),
"libghostty.so",
);
b.getInstallStep().dependOn(&lib_install.step);
}
// On Mac we can build the embedding library. This only handles the macOS lib.
if (builtin.target.isDarwin() and target.result.os.tag == .macos) {
// Create the universal macOS lib.

View File

@ -30,6 +30,10 @@ typedef void *ghostty_surface_t;
typedef void *ghostty_inspector_t;
// Enums are up top so we can reference them later.
typedef enum {
GHOSTTY_PLATFORM_MACOS,
} ghostty_platform_e;
typedef enum {
GHOSTTY_CLIPBOARD_STANDARD,
GHOSTTY_CLIPBOARD_SELECTION,

View File

@ -231,9 +231,49 @@ pub const App = struct {
}
};
/// Platform-specific configuration for libghostty.
pub const Platform = union(PlatformTag) {
macos: MacOS,
// If our build target for libghostty is not darwin then we do
// not include macos support at all.
pub const MacOS = if (builtin.target.isDarwin()) struct {
/// The view to render the surface on.
nsview: objc.Object,
} else void;
// The C ABI compatible version of this union. The tag is expected
// to be stored elsewhere.
pub const C = extern union {
macos: extern struct {
nsview: ?*anyopaque,
},
};
/// Initialize a Platform a tag and configuration from the C ABI.
pub fn init(tag_int: c_int, c_platform: C) !Platform {
const tag = try std.meta.intToEnum(PlatformTag, tag_int);
return switch (tag) {
.macos => if (MacOS != void) macos: {
const config = c_platform.macos;
const nsview = objc.Object.fromId(config.nsview orelse
break :macos error.NSViewMustBeSet);
break :macos .{ .macos = .{ .nsview = nsview } };
} else error.UnsupportedPlatform,
};
}
};
pub const PlatformTag = enum(c_int) {
// "0" is reserved for invalid so we can detect unset values
// from the C API.
macos = 1,
};
pub const Surface = struct {
app: *App,
nsview: objc.Object,
platform: Platform,
core_surface: CoreSurface,
content_scale: apprt.ContentScale,
size: apprt.SurfaceSize,
@ -246,8 +286,10 @@ pub const Surface = struct {
/// Userdata passed to some of the callbacks.
userdata: ?*anyopaque = null,
/// The pointer to the backing NSView for the surface.
nsview: ?*anyopaque = null,
/// The platform that this surface is being initialized for and
/// the associated platform-specific configuration.
platform_tag: c_int = 0,
platform: Platform.C = undefined,
/// The scale factor of the screen.
scale_factor: f64 = 1,
@ -279,13 +321,10 @@ pub const Surface = struct {
};
pub fn init(self: *Surface, app: *App, opts: Options) !void {
const nsview = objc.Object.fromId(opts.nsview orelse
return error.NSViewMustBeSet);
self.* = .{
.app = app,
.platform = try Platform.init(opts.platform_tag, opts.platform),
.core_surface = undefined,
.nsview = nsview,
.content_scale = .{
.x = @floatCast(opts.scale_factor),
.y = @floatCast(opts.scale_factor),
@ -1584,30 +1623,33 @@ pub const CAPI = struct {
ptr.freeInspector();
}
export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool {
return ptr.initMetal(objc.Object.fromId(device));
}
export fn ghostty_inspector_metal_render(
ptr: *Inspector,
command_buffer: objc.c.id,
descriptor: objc.c.id,
) void {
return ptr.renderMetal(
objc.Object.fromId(command_buffer),
objc.Object.fromId(descriptor),
) catch |err| {
log.err("error rendering inspector err={}", .{err});
return;
};
}
export fn ghostty_inspector_metal_shutdown(ptr: *Inspector) void {
if (ptr.backend) |v| {
v.deinit();
ptr.backend = null;
// Inspector Metal APIs are only available on Apple systems
usingnamespace if (builtin.target.isDarwin()) struct {
export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool {
return ptr.initMetal(objc.Object.fromId(device));
}
}
export fn ghostty_inspector_metal_render(
ptr: *Inspector,
command_buffer: objc.c.id,
descriptor: objc.c.id,
) void {
return ptr.renderMetal(
objc.Object.fromId(command_buffer),
objc.Object.fromId(descriptor),
) catch |err| {
log.err("error rendering inspector err={}", .{err});
return;
};
}
export fn ghostty_inspector_metal_shutdown(ptr: *Inspector) void {
if (ptr.backend) |v| {
v.deinit();
ptr.backend = null;
}
}
} else struct {};
export fn ghostty_inspector_set_size(ptr: *Inspector, w: u32, h: u32) void {
ptr.updateSize(w, h);

View File

@ -422,6 +422,12 @@ pub fn surfaceInit(surface: *apprt.Surface) !void {
},
apprt.glfw => try self.threadEnter(surface),
apprt.embedded => {
// TODO(mitchellh): this does nothing today to allow libghostty
// to compile for OpenGL targets but libghostty is strictly
// broken for rendering on this platforms.
},
}
// These are very noisy so this is commented, but easy to uncomment
@ -529,6 +535,12 @@ pub fn threadEnter(self: *const OpenGL, surface: *apprt.Surface) !void {
gl.glad.versionMinor(@intCast(version)),
});
},
apprt.embedded => {
// TODO(mitchellh): this does nothing today to allow libghostty
// to compile for OpenGL targets but libghostty is strictly
// broken for rendering on this platforms.
},
}
}
@ -548,6 +560,10 @@ pub fn threadExit(self: *const OpenGL) void {
gl.glad.unload();
glfw.makeContextCurrent(null);
},
apprt.embedded => {
// TODO: see threadEnter
},
}
}
@ -1815,6 +1831,7 @@ pub fn drawFrame(self: *OpenGL, surface: *apprt.Surface) !void {
switch (apprt.runtime) {
apprt.glfw => surface.window.swapBuffers(),
apprt.gtk => {},
apprt.embedded => {},
else => @compileError("unsupported runtime"),
}
}