mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
termio: exec uses new flatpak command, no more host-spawn
This commit is contained in:
18
build.zig
18
build.zig
@ -46,6 +46,7 @@ comptime {
|
|||||||
var tracy: bool = false;
|
var tracy: bool = false;
|
||||||
var enable_coretext: bool = false;
|
var enable_coretext: bool = false;
|
||||||
var enable_fontconfig: bool = false;
|
var enable_fontconfig: bool = false;
|
||||||
|
var flatpak: bool = false;
|
||||||
var app_runtime: apprt.Runtime = .none;
|
var app_runtime: apprt.Runtime = .none;
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) !void {
|
pub fn build(b: *std.build.Builder) !void {
|
||||||
@ -67,6 +68,12 @@ pub fn build(b: *std.build.Builder) !void {
|
|||||||
"Enable Tracy integration (default true in Debug on Linux)",
|
"Enable Tracy integration (default true in Debug on Linux)",
|
||||||
) orelse (optimize == .Debug and target.isLinux());
|
) orelse (optimize == .Debug and target.isLinux());
|
||||||
|
|
||||||
|
flatpak = b.option(
|
||||||
|
bool,
|
||||||
|
"flatpak",
|
||||||
|
"Build for Flatpak (integrates with Flatpak APIs). Only has an effect targeting Linux.",
|
||||||
|
) orelse false;
|
||||||
|
|
||||||
enable_coretext = b.option(
|
enable_coretext = b.option(
|
||||||
bool,
|
bool,
|
||||||
"coretext",
|
"coretext",
|
||||||
@ -123,6 +130,7 @@ 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, "coretext", enable_coretext);
|
exe_options.addOption(bool, "coretext", enable_coretext);
|
||||||
exe_options.addOption(bool, "fontconfig", enable_fontconfig);
|
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);
|
||||||
@ -578,6 +586,13 @@ fn addDeps(
|
|||||||
step.addIncludePath("vendor/glad/include/");
|
step.addIncludePath("vendor/glad/include/");
|
||||||
step.addCSourceFile("vendor/glad/src/gl.c", &.{});
|
step.addCSourceFile("vendor/glad/src/gl.c", &.{});
|
||||||
|
|
||||||
|
// When we're targeting flatpak we ALWAYS link GTK so we
|
||||||
|
// get access to glib for dbus.
|
||||||
|
if (flatpak) {
|
||||||
|
step.linkSystemLibrary("gtk4");
|
||||||
|
step.addLibraryPath("/usr/lib/aarch64-linux-gnu");
|
||||||
|
}
|
||||||
|
|
||||||
switch (app_runtime) {
|
switch (app_runtime) {
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|
||||||
@ -604,9 +619,6 @@ fn addDeps(
|
|||||||
try glfw.link(b, step, glfw_opts);
|
try glfw.link(b, step, glfw_opts);
|
||||||
|
|
||||||
step.linkSystemLibrary("gtk4");
|
step.linkSystemLibrary("gtk4");
|
||||||
|
|
||||||
// This is for Flatpak
|
|
||||||
step.addLibraryPath("/usr/lib/aarch64-linux-gnu");
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,30 +41,10 @@ modules:
|
|||||||
only-arches:
|
only-arches:
|
||||||
- aarch64
|
- aarch64
|
||||||
|
|
||||||
# We use this to get a proper PTY on our host spawn. We should eventually
|
|
||||||
# replace this with using dbus directly.
|
|
||||||
- name: host-spawn
|
|
||||||
buildsystem: simple
|
|
||||||
build-commands:
|
|
||||||
- mkdir -p /app/bin
|
|
||||||
- mv ./host-spawn-* /app/bin/host-spawn
|
|
||||||
- chmod +x /app/bin/host-spawn
|
|
||||||
sources:
|
|
||||||
- type: file
|
|
||||||
url: https://github.com/1player/host-spawn/releases/download/1.4.1/host-spawn-x86_64
|
|
||||||
sha256: d81bb6125ec73a9a2e26266c48787367fbcb665d67c2e7fb42217f0981106cf7
|
|
||||||
only-arches:
|
|
||||||
- x86_64
|
|
||||||
- type: file
|
|
||||||
url: https://github.com/1player/host-spawn/releases/download/1.4.1/host-spawn-aarch64
|
|
||||||
sha256: 29bff846d72e37093b3fdf7859bae16addd64acc98087f8c059548df3c2273c4
|
|
||||||
only-arches:
|
|
||||||
- aarch64
|
|
||||||
|
|
||||||
- name: ghostty
|
- name: ghostty
|
||||||
buildsystem: simple
|
buildsystem: simple
|
||||||
build-commands:
|
build-commands:
|
||||||
- MACH_SDK_PATH="$(pwd)/vendor/mach-sdk" zig build -Dcpu=baseline -Dapp-runtime=gtk --prefix /app
|
- MACH_SDK_PATH="$(pwd)/vendor/mach-sdk" zig build -Dcpu=baseline -Dflatpak=true -Dapp-runtime=gtk --prefix /app
|
||||||
sources:
|
sources:
|
||||||
- type: dir
|
- type: dir
|
||||||
path: .
|
path: .
|
||||||
|
@ -22,6 +22,9 @@ pub const app_runtime = std.meta.stringToEnum(
|
|||||||
/// compiled.
|
/// compiled.
|
||||||
pub const devmode_enabled = artifact == .exe and app_runtime == .glfw;
|
pub const devmode_enabled = artifact == .exe and app_runtime == .glfw;
|
||||||
|
|
||||||
|
/// We want to integrate with Flatpak APIs.
|
||||||
|
pub const flatpak = options.flatpak;
|
||||||
|
|
||||||
pub const Artifact = enum {
|
pub const Artifact = enum {
|
||||||
/// Standalone executable
|
/// Standalone executable
|
||||||
exe,
|
exe,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const build_config = @import("build_config.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
const internal_os = @import("os/main.zig");
|
const internal_os = @import("os/main.zig");
|
||||||
@ -49,8 +50,13 @@ pub fn get(alloc: Allocator) !Entry {
|
|||||||
// If we're in flatpak then our entry is always empty so we grab it
|
// If we're in flatpak then our entry is always empty so we grab it
|
||||||
// by shelling out to the host. note that we do HAVE an entry in the
|
// by shelling out to the host. note that we do HAVE an entry in the
|
||||||
// sandbox but only the username is correct.
|
// sandbox but only the username is correct.
|
||||||
if (internal_os.isFlatpak()) {
|
if (internal_os.isFlatpak()) flatpak: {
|
||||||
log.info("flatpak detected, will use host-spawn to get our entry", .{});
|
if (comptime !build_config.flatpak) {
|
||||||
|
log.warn("flatpak detected, but this build doesn't contain flatpak support", .{});
|
||||||
|
break :flatpak;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("flatpak detected, will use host command to get our entry", .{});
|
||||||
|
|
||||||
// Note: we wrap our getent call in a /bin/sh login shell because
|
// Note: we wrap our getent call in a /bin/sh login shell because
|
||||||
// some operating systems (NixOS tested) don't set the PATH for various
|
// some operating systems (NixOS tested) don't set the PATH for various
|
||||||
@ -104,7 +110,6 @@ pub fn get(alloc: Allocator) !Entry {
|
|||||||
|
|
||||||
break :output try output.toOwnedSlice(alloc);
|
break :output try output.toOwnedSlice(alloc);
|
||||||
};
|
};
|
||||||
log.warn("DONE output={s}", .{output});
|
|
||||||
|
|
||||||
// Shell and home are the last two entries
|
// Shell and home are the last two entries
|
||||||
var it = std.mem.splitBackwards(u8, std.mem.trimRight(u8, output, " \r\n"), ":");
|
var it = std.mem.splitBackwards(u8, std.mem.trimRight(u8, output, " \r\n"), ":");
|
||||||
|
@ -322,6 +322,10 @@ fn ttyWrite(
|
|||||||
|
|
||||||
/// Subprocess manages the lifecycle of the shell subprocess.
|
/// Subprocess manages the lifecycle of the shell subprocess.
|
||||||
const Subprocess = struct {
|
const Subprocess = struct {
|
||||||
|
/// If we build with flatpak support then we have to keep track of
|
||||||
|
/// a potential execution on the host.
|
||||||
|
const FlatpakHostCommand = if (build_config.flatpak) internal_os.FlatpakHostCommand else void;
|
||||||
|
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
cwd: ?[]const u8,
|
cwd: ?[]const u8,
|
||||||
env: EnvMap,
|
env: EnvMap,
|
||||||
@ -331,6 +335,7 @@ const Subprocess = struct {
|
|||||||
screen_size: renderer.ScreenSize,
|
screen_size: renderer.ScreenSize,
|
||||||
pty: ?Pty = null,
|
pty: ?Pty = null,
|
||||||
command: ?Command = null,
|
command: ?Command = null,
|
||||||
|
flatpak_command: ?FlatpakHostCommand = null,
|
||||||
|
|
||||||
/// Initialize the subprocess. This will NOT start it, this only sets
|
/// Initialize the subprocess. This will NOT start it, this only sets
|
||||||
/// up the internal state necessary to start it later.
|
/// up the internal state necessary to start it later.
|
||||||
@ -364,8 +369,18 @@ const Subprocess = struct {
|
|||||||
break :argv0 argv0_buf;
|
break :argv0 argv0_buf;
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
// Set our env vars
|
// Set our env vars. For Flatpak builds running in Flatpak we don't
|
||||||
var env = try std.process.getEnvMap(alloc);
|
// inherit our environment because the login shell on the host side
|
||||||
|
// will get it.
|
||||||
|
var env = env: {
|
||||||
|
if (comptime build_config.flatpak) {
|
||||||
|
if (internal_os.isFlatpak()) {
|
||||||
|
break :env std.process.EnvMap.init(alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break :env try std.process.getEnvMap(alloc);
|
||||||
|
};
|
||||||
errdefer env.deinit();
|
errdefer env.deinit();
|
||||||
try env.put("TERM", "xterm-256color");
|
try env.put("TERM", "xterm-256color");
|
||||||
try env.put("COLORTERM", "truecolor");
|
try env.put("COLORTERM", "truecolor");
|
||||||
@ -394,13 +409,9 @@ const Subprocess = struct {
|
|||||||
var args = try std.ArrayList([]const u8).initCapacity(alloc, 8);
|
var args = try std.ArrayList([]const u8).initCapacity(alloc, 8);
|
||||||
defer args.deinit();
|
defer args.deinit();
|
||||||
|
|
||||||
// We use host-spawn so the PTY is setup properly.
|
// We run our shell wrapped in a /bin/sh login shell because
|
||||||
// future: rewrite host-spawn into pure Zig using dbus and
|
// some systems do not properly initialize the env vars unless
|
||||||
// we can run this directly.
|
// we start this way (NixOS!)
|
||||||
try args.append("/app/bin/host-spawn");
|
|
||||||
try args.append("-pty");
|
|
||||||
try args.append("-env");
|
|
||||||
try args.append("TERM,COLORTERM");
|
|
||||||
try args.append("/bin/sh");
|
try args.append("/bin/sh");
|
||||||
try args.append("-l");
|
try args.append("-l");
|
||||||
try args.append("-c");
|
try args.append("-c");
|
||||||
@ -451,6 +462,37 @@ const Subprocess = struct {
|
|||||||
self.args,
|
self.args,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// In flatpak, we use the HostCommand to execute our shell.
|
||||||
|
if (internal_os.isFlatpak()) flatpak: {
|
||||||
|
if (comptime !build_config.flatpak) {
|
||||||
|
log.warn("flatpak detected, but flatpak support not built-in", .{});
|
||||||
|
break :flatpak;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For flatpak our path and argv[0] must match because that is
|
||||||
|
// used for execution by the dbus API.
|
||||||
|
assert(std.mem.eql(u8, self.path, self.args[0]));
|
||||||
|
|
||||||
|
// Flatpak command must have a stable pointer.
|
||||||
|
self.flatpak_command = .{
|
||||||
|
.argv = self.args,
|
||||||
|
.env = &self.env,
|
||||||
|
.stdin = pty.slave,
|
||||||
|
.stdout = pty.slave,
|
||||||
|
.stderr = pty.slave,
|
||||||
|
};
|
||||||
|
var cmd = &self.flatpak_command.?;
|
||||||
|
const pid = try cmd.spawn(alloc);
|
||||||
|
errdefer killCommandFlatpak(cmd);
|
||||||
|
|
||||||
|
log.info("started subcommand on host via flatpak API path={s} pid={?}", .{
|
||||||
|
self.path,
|
||||||
|
pid,
|
||||||
|
});
|
||||||
|
|
||||||
|
return pty.master;
|
||||||
|
}
|
||||||
|
|
||||||
// Build our subcommand
|
// Build our subcommand
|
||||||
var cmd: Command = .{
|
var cmd: Command = .{
|
||||||
.path = self.path,
|
.path = self.path,
|
||||||
@ -489,6 +531,17 @@ const Subprocess = struct {
|
|||||||
self.command = null;
|
self.command = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kill our Flatpak command
|
||||||
|
if (FlatpakHostCommand != void) {
|
||||||
|
if (self.flatpak_command) |*cmd| {
|
||||||
|
killCommandFlatpak(cmd) catch |err|
|
||||||
|
log.err("error sending SIGHUP to command, may hang: {}", .{err});
|
||||||
|
_ = cmd.wait() catch |err|
|
||||||
|
log.err("error waiting for command to exit: {}", .{err});
|
||||||
|
self.flatpak_command = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Close our PTY. We do this after killing our command because on
|
// Close our PTY. We do this after killing our command because on
|
||||||
// macOS, close will block until all blocking operations read/write
|
// macOS, close will block until all blocking operations read/write
|
||||||
// are done with it and our reader thread is probably still alive.
|
// are done with it and our reader thread is probably still alive.
|
||||||
@ -547,6 +600,11 @@ const Subprocess = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn killCommandFlatpak(command: *FlatpakHostCommand) !void {
|
||||||
|
// TODO
|
||||||
|
_ = command;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The read thread sits in a loop doing the following pseudo code:
|
/// The read thread sits in a loop doing the following pseudo code:
|
||||||
|
Reference in New Issue
Block a user