mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
starting libuv bindings
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
||||
[submodule "vendor/cglm"]
|
||||
path = vendor/cglm
|
||||
url = https://github.com/recp/cglm.git
|
||||
[submodule "vendor/libuv"]
|
||||
path = vendor/libuv
|
||||
url = https://github.com/libuv/libuv.git
|
||||
|
@ -3,6 +3,7 @@ const Builder = std.build.Builder;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const glfw = @import("vendor/mach/glfw/build.zig");
|
||||
const ft = @import("src/freetype/build.zig");
|
||||
const uv = @import("src/libuv/build.zig");
|
||||
|
||||
pub fn build(b: *std.build.Builder) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
@ -23,11 +24,8 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
|
||||
const ftlib = try ft.create(b, target, mode, .{});
|
||||
ftlib.link(exe);
|
||||
// to link to system:
|
||||
// exe.linkSystemLibrary("freetype2");
|
||||
// exe.linkSystemLibrary("libpng");
|
||||
// exe.linkSystemLibrary("bzip2");
|
||||
// ftlib.addIncludeDirs(exe);
|
||||
|
||||
const libuv = try uv.create(b, target, mode);
|
||||
|
||||
// stb if we need it
|
||||
// exe.addIncludeDir("vendor/stb");
|
||||
@ -46,6 +44,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
const test_step = b.step("test", "Run all tests");
|
||||
const lib_tests = b.addTest("src/main.zig");
|
||||
ftlib.link(lib_tests);
|
||||
libuv.link(lib_tests);
|
||||
lib_tests.addIncludeDir("vendor/glad/include/");
|
||||
lib_tests.addCSourceFile("vendor/glad/src/gl.c", &.{});
|
||||
test_step.dependOn(&lib_tests.step);
|
||||
|
53
src/libuv/Loop.zig
Normal file
53
src/libuv/Loop.zig
Normal file
@ -0,0 +1,53 @@
|
||||
const Loop = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const testing = std.testing;
|
||||
const c = @import("c.zig");
|
||||
const errors = @import("error.zig");
|
||||
|
||||
loop: *c.uv_loop_t,
|
||||
|
||||
/// Initialize a new uv_loop.
|
||||
pub fn init(alloc: Allocator) !Loop {
|
||||
// The uv_loop_t type MUST be heap allocated and must not be copied.
|
||||
// I can't find a definitive source on this, but the test suite starts
|
||||
// hanging in weird places and doing bad things when it is copied.
|
||||
const loop = try alloc.create(c.uv_loop_t);
|
||||
try errors.convertError(c.uv_loop_init(loop));
|
||||
return Loop{ .loop = loop };
|
||||
}
|
||||
|
||||
/// Releases all internal loop resources. Call this function only when the
|
||||
/// loop has finished executing and all open handles and requests have been
|
||||
/// closed, or this will silently fail (in debug mode it will panic).
|
||||
pub fn deinit(self: *Loop, alloc: Allocator) void {
|
||||
// deinit functions idiomatically cannot fail in Zig, so we do the
|
||||
// next best thing here and assert so that in debug mode you'll get
|
||||
// a crash.
|
||||
std.debug.assert(c.uv_loop_close(self.loop) >= 0);
|
||||
alloc.destroy(self.loop);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
/// This function runs the event loop. See RunMode for mode documentation.
|
||||
///
|
||||
/// This is not reentrant. It must not be called from a callback.
|
||||
pub fn run(self: *Loop, mode: RunMode) !u32 {
|
||||
const res = c.uv_run(self.loop, @enumToInt(mode));
|
||||
try errors.convertError(res);
|
||||
return @intCast(u32, res);
|
||||
}
|
||||
|
||||
/// Mode used to run the loop with uv_run().
|
||||
pub const RunMode = enum(c.uv_run_mode) {
|
||||
default = c.UV_RUN_DEFAULT,
|
||||
once = c.UV_RUN_ONCE,
|
||||
nowait = c.UV_RUN_NOWAIT,
|
||||
};
|
||||
|
||||
test {
|
||||
var loop = try init(testing.allocator);
|
||||
defer loop.deinit(testing.allocator);
|
||||
try testing.expectEqual(@as(u32, 0), try loop.run(.nowait));
|
||||
}
|
132
src/libuv/build.zig
Normal file
132
src/libuv/build.zig
Normal file
@ -0,0 +1,132 @@
|
||||
const std = @import("std");
|
||||
|
||||
/// This is the type returned by create.
|
||||
pub const Library = struct {
|
||||
step: *std.build.LibExeObjStep,
|
||||
|
||||
/// statically link this library into the given step
|
||||
pub fn link(self: Library, other: *std.build.LibExeObjStep) void {
|
||||
self.addIncludeDirs(other);
|
||||
other.linkLibrary(self.step);
|
||||
}
|
||||
|
||||
/// only add the include dirs to the given step. This is useful if building
|
||||
/// a static library that you don't want to fully link in the code of this
|
||||
/// library.
|
||||
pub fn addIncludeDirs(self: Library, other: *std.build.LibExeObjStep) void {
|
||||
_ = self;
|
||||
other.addIncludeDir(include_dir);
|
||||
}
|
||||
};
|
||||
|
||||
/// Create this library. This is the primary API users of build.zig should
|
||||
/// use to link this library to their application. On the resulting Library,
|
||||
/// call the link function and given your own application step.
|
||||
pub fn create(
|
||||
b: *std.build.Builder,
|
||||
target: std.zig.CrossTarget,
|
||||
mode: std.builtin.Mode,
|
||||
) !Library {
|
||||
const ret = b.addStaticLibrary("uv", null);
|
||||
ret.setTarget(target);
|
||||
ret.setBuildMode(mode);
|
||||
|
||||
var flags = std.ArrayList([]const u8).init(b.allocator);
|
||||
defer flags.deinit();
|
||||
|
||||
// try flags.appendSlice(&.{});
|
||||
|
||||
if (!target.isWindows()) {
|
||||
try flags.appendSlice(&.{
|
||||
"-D_FILE_OFFSET_BITS=64",
|
||||
"-D_LARGEFILE_SOURCE",
|
||||
});
|
||||
}
|
||||
|
||||
if (target.isLinux()) {
|
||||
try flags.appendSlice(&.{
|
||||
"-D_GNU_SOURCE",
|
||||
"-D_POSIX_C_SOURCE=200112",
|
||||
});
|
||||
}
|
||||
|
||||
// C files common to all platforms
|
||||
ret.addCSourceFiles(&.{
|
||||
root() ++ "src/fs-poll.c",
|
||||
root() ++ "src/idna.c",
|
||||
root() ++ "src/inet.c",
|
||||
root() ++ "src/random.c",
|
||||
root() ++ "src/strscpy.c",
|
||||
root() ++ "src/strtok.c",
|
||||
root() ++ "src/threadpool.c",
|
||||
root() ++ "src/timer.c",
|
||||
root() ++ "src/uv-common.c",
|
||||
root() ++ "src/uv-data-getter-setters.c",
|
||||
root() ++ "src/version.c",
|
||||
}, flags.items);
|
||||
|
||||
if (!target.isWindows()) {
|
||||
ret.addCSourceFiles(&.{
|
||||
root() ++ "src/unix/async.c",
|
||||
root() ++ "src/unix/core.c",
|
||||
root() ++ "src/unix/dl.c",
|
||||
root() ++ "src/unix/fs.c",
|
||||
root() ++ "src/unix/getaddrinfo.c",
|
||||
root() ++ "src/unix/getnameinfo.c",
|
||||
root() ++ "src/unix/loop-watcher.c",
|
||||
root() ++ "src/unix/loop.c",
|
||||
root() ++ "src/unix/pipe.c",
|
||||
root() ++ "src/unix/poll.c",
|
||||
root() ++ "src/unix/process.c",
|
||||
root() ++ "src/unix/random-devurandom.c",
|
||||
root() ++ "src/unix/signal.c",
|
||||
root() ++ "src/unix/stream.c",
|
||||
root() ++ "src/unix/tcp.c",
|
||||
root() ++ "src/unix/thread.c",
|
||||
root() ++ "src/unix/tty.c",
|
||||
root() ++ "src/unix/udp.c",
|
||||
}, flags.items);
|
||||
}
|
||||
|
||||
if (target.isLinux() or target.isDarwin()) {
|
||||
ret.addCSourceFiles(&.{
|
||||
root() ++ "src/unix/proctitle.c",
|
||||
}, flags.items);
|
||||
}
|
||||
|
||||
if (target.isLinux()) {
|
||||
ret.addCSourceFiles(&.{
|
||||
root() ++ "src/unix/linux-core.c",
|
||||
root() ++ "src/unix/linux-inotify.c",
|
||||
root() ++ "src/unix/linux-syscalls.c",
|
||||
root() ++ "src/unix/procfs-exepath.c",
|
||||
root() ++ "src/unix/random-getrandom.c",
|
||||
root() ++ "src/unix/random-sysctl-linux.c",
|
||||
root() ++ "src/unix/epoll.c",
|
||||
}, flags.items);
|
||||
}
|
||||
|
||||
ret.addIncludeDir(include_dir);
|
||||
ret.addIncludeDir(root() ++ "src");
|
||||
if (target.isWindows()) {
|
||||
ret.linkSystemLibrary("psapi");
|
||||
ret.linkSystemLibrary("user32");
|
||||
ret.linkSystemLibrary("advapi32");
|
||||
ret.linkSystemLibrary("iphlpapi");
|
||||
ret.linkSystemLibrary("userenv");
|
||||
ret.linkSystemLibrary("ws2_32");
|
||||
}
|
||||
if (target.isLinux()) {
|
||||
ret.linkSystemLibrary("pthread");
|
||||
}
|
||||
ret.linkLibC();
|
||||
|
||||
return Library{ .step = ret };
|
||||
}
|
||||
|
||||
fn root() []const u8 {
|
||||
return (std.fs.path.dirname(@src().file) orelse unreachable) ++ "/../../vendor/libuv/";
|
||||
}
|
||||
|
||||
/// Directories with our includes.
|
||||
const include_dir = root() ++ "include";
|
3
src/libuv/c.zig
Normal file
3
src/libuv/c.zig
Normal file
@ -0,0 +1,3 @@
|
||||
pub usingnamespace @cImport({
|
||||
@cInclude("uv.h");
|
||||
});
|
185
src/libuv/error.zig
Normal file
185
src/libuv/error.zig
Normal file
@ -0,0 +1,185 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const c = @import("c.zig");
|
||||
|
||||
/// Errors that libuv can produce
|
||||
///
|
||||
/// http://docs.libuv.org/en/v1.x/errors.html
|
||||
pub const Error = error{
|
||||
E2BIG,
|
||||
EACCES,
|
||||
EADDRINUSE,
|
||||
EADDRNOTAVAIL,
|
||||
EAFNOSUPPORT,
|
||||
EAGAIN,
|
||||
EAI_ADDRFAMILY,
|
||||
EAI_AGAIN,
|
||||
EAI_BADFLAGS,
|
||||
EAI_BADHINTS,
|
||||
EAI_CANCELED,
|
||||
EAI_FAIL,
|
||||
EAI_FAMILY,
|
||||
EAI_MEMORY,
|
||||
EAI_NODATA,
|
||||
EAI_NONAME,
|
||||
EAI_OVERFLOW,
|
||||
EAI_PROTOCOL,
|
||||
EAI_SERVICE,
|
||||
EAI_SOCKTYPE,
|
||||
EALREADY,
|
||||
EBADF,
|
||||
EBUSY,
|
||||
ECANCELED,
|
||||
ECHARSET,
|
||||
ECONNABORTED,
|
||||
ECONNREFUSED,
|
||||
ECONNRESET,
|
||||
EDESTADDRREQ,
|
||||
EEXIST,
|
||||
EFAULT,
|
||||
EFBIG,
|
||||
EHOSTUNREACH,
|
||||
EINTR,
|
||||
EINVAL,
|
||||
EIO,
|
||||
EISCONN,
|
||||
EISDIR,
|
||||
ELOOP,
|
||||
EMFILE,
|
||||
EMSGSIZE,
|
||||
ENAMETOOLONG,
|
||||
ENETDOWN,
|
||||
ENETUNREACH,
|
||||
ENFILE,
|
||||
ENOBUFS,
|
||||
ENODEV,
|
||||
ENOENT,
|
||||
ENOMEM,
|
||||
ENONET,
|
||||
ENOPROTOOPT,
|
||||
ENOSPC,
|
||||
ENOSYS,
|
||||
ENOTCONN,
|
||||
ENOTDIR,
|
||||
ENOTEMPTY,
|
||||
ENOTSOCK,
|
||||
ENOTSUP,
|
||||
EPERM,
|
||||
EPIPE,
|
||||
EPROTO,
|
||||
EPROTONOSUPPORT,
|
||||
EPROTOTYPE,
|
||||
ERANGE,
|
||||
EROFS,
|
||||
ESHUTDOWN,
|
||||
ESPIPE,
|
||||
ESRCH,
|
||||
ETIMEDOUT,
|
||||
ETXTBSY,
|
||||
EXDEV,
|
||||
UNKNOWN,
|
||||
EOF,
|
||||
ENXIO,
|
||||
EMLINK,
|
||||
EHOSTDOWN,
|
||||
EREMOTEIO,
|
||||
ENOTTY,
|
||||
EFTYPE,
|
||||
EILSEQ,
|
||||
ESOCKTNOSUPPORT,
|
||||
};
|
||||
|
||||
/// Convert the result of a libuv API call to an error (or no error).
|
||||
pub fn convertError(r: i32) !void {
|
||||
if (r >= 0) return;
|
||||
|
||||
return switch (r) {
|
||||
c.UV_E2BIG => Error.E2BIG,
|
||||
c.UV_EACCES => Error.EACCES,
|
||||
c.UV_EADDRINUSE => Error.EADDRINUSE,
|
||||
c.UV_EADDRNOTAVAIL => Error.EADDRNOTAVAIL,
|
||||
c.UV_EAFNOSUPPORT => Error.EAFNOSUPPORT,
|
||||
c.UV_EAGAIN => Error.EAGAIN,
|
||||
c.UV_EAI_ADDRFAMILY => Error.EAI_ADDRFAMILY,
|
||||
c.UV_EAI_AGAIN => Error.EAI_AGAIN,
|
||||
c.UV_EAI_BADFLAGS => Error.EAI_BADFLAGS,
|
||||
c.UV_EAI_BADHINTS => Error.EAI_BADHINTS,
|
||||
c.UV_EAI_CANCELED => Error.EAI_CANCELED,
|
||||
c.UV_EAI_FAIL => Error.EAI_FAIL,
|
||||
c.UV_EAI_FAMILY => Error.EAI_FAMILY,
|
||||
c.UV_EAI_MEMORY => Error.EAI_MEMORY,
|
||||
c.UV_EAI_NODATA => Error.EAI_NODATA,
|
||||
c.UV_EAI_NONAME => Error.EAI_NONAME,
|
||||
c.UV_EAI_OVERFLOW => Error.EAI_OVERFLOW,
|
||||
c.UV_EAI_PROTOCOL => Error.EAI_PROTOCOL,
|
||||
c.UV_EAI_SERVICE => Error.EAI_SERVICE,
|
||||
c.UV_EAI_SOCKTYPE => Error.EAI_SOCKTYPE,
|
||||
c.UV_EALREADY => Error.EALREADY,
|
||||
c.UV_EBADF => Error.EBADF,
|
||||
c.UV_EBUSY => Error.EBUSY,
|
||||
c.UV_ECANCELED => Error.ECANCELED,
|
||||
c.UV_ECHARSET => Error.ECHARSET,
|
||||
c.UV_ECONNABORTED => Error.ECONNABORTED,
|
||||
c.UV_ECONNREFUSED => Error.ECONNREFUSED,
|
||||
c.UV_ECONNRESET => Error.ECONNRESET,
|
||||
c.UV_EDESTADDRREQ => Error.EDESTADDRREQ,
|
||||
c.UV_EEXIST => Error.EEXIST,
|
||||
c.UV_EFAULT => Error.EFAULT,
|
||||
c.UV_EFBIG => Error.EFBIG,
|
||||
c.UV_EHOSTUNREACH => Error.EHOSTUNREACH,
|
||||
c.UV_EINTR => Error.EINTR,
|
||||
c.UV_EINVAL => Error.EINVAL,
|
||||
c.UV_EIO => Error.EIO,
|
||||
c.UV_EISCONN => Error.EISCONN,
|
||||
c.UV_EISDIR => Error.EISDIR,
|
||||
c.UV_ELOOP => Error.ELOOP,
|
||||
c.UV_EMFILE => Error.EMFILE,
|
||||
c.UV_EMSGSIZE => Error.EMSGSIZE,
|
||||
c.UV_ENAMETOOLONG => Error.ENAMETOOLONG,
|
||||
c.UV_ENETDOWN => Error.ENETDOWN,
|
||||
c.UV_ENETUNREACH => Error.ENETUNREACH,
|
||||
c.UV_ENFILE => Error.ENFILE,
|
||||
c.UV_ENOBUFS => Error.ENOBUFS,
|
||||
c.UV_ENODEV => Error.ENODEV,
|
||||
c.UV_ENOENT => Error.ENOENT,
|
||||
c.UV_ENOMEM => Error.ENOMEM,
|
||||
c.UV_ENONET => Error.ENONET,
|
||||
c.UV_ENOPROTOOPT => Error.ENOPROTOOPT,
|
||||
c.UV_ENOSPC => Error.ENOSPC,
|
||||
c.UV_ENOSYS => Error.ENOSYS,
|
||||
c.UV_ENOTCONN => Error.ENOTCONN,
|
||||
c.UV_ENOTDIR => Error.ENOTDIR,
|
||||
c.UV_ENOTEMPTY => Error.ENOTEMPTY,
|
||||
c.UV_ENOTSOCK => Error.ENOTSOCK,
|
||||
c.UV_ENOTSUP => Error.ENOTSUP,
|
||||
c.UV_EPERM => Error.EPERM,
|
||||
c.UV_EPIPE => Error.EPIPE,
|
||||
c.UV_EPROTO => Error.EPROTO,
|
||||
c.UV_EPROTONOSUPPORT => Error.EPROTONOSUPPORT,
|
||||
c.UV_EPROTOTYPE => Error.EPROTOTYPE,
|
||||
c.UV_ERANGE => Error.ERANGE,
|
||||
c.UV_EROFS => Error.EROFS,
|
||||
c.UV_ESHUTDOWN => Error.ESHUTDOWN,
|
||||
c.UV_ESPIPE => Error.ESPIPE,
|
||||
c.UV_ESRCH => Error.ESRCH,
|
||||
c.UV_ETIMEDOUT => Error.ETIMEDOUT,
|
||||
c.UV_ETXTBSY => Error.ETXTBSY,
|
||||
c.UV_EXDEV => Error.EXDEV,
|
||||
c.UV_UNKNOWN => Error.UNKNOWN,
|
||||
c.UV_EOF => Error.EOF,
|
||||
c.UV_ENXIO => Error.ENXIO,
|
||||
c.UV_EHOSTDOWN => Error.EHOSTDOWN,
|
||||
c.UV_EREMOTEIO => Error.EREMOTEIO,
|
||||
c.UV_ENOTTY => Error.ENOTTY,
|
||||
c.UV_EFTYPE => Error.EFTYPE,
|
||||
c.UV_EILSEQ => Error.EILSEQ,
|
||||
c.UV_ESOCKTNOSUPPORT => Error.ESOCKTNOSUPPORT,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
test {
|
||||
// This is mostly just forcing our error type and function to be
|
||||
// codegenned and run once to ensure we have all the types.
|
||||
try testing.expectError(Error.EFTYPE, convertError(c.UV_EFTYPE));
|
||||
}
|
7
src/libuv/main.zig
Normal file
7
src/libuv/main.zig
Normal file
@ -0,0 +1,7 @@
|
||||
const Loop = @import("Loop.zig");
|
||||
const Error = @import("error.zig").Error;
|
||||
|
||||
test {
|
||||
_ = Loop;
|
||||
_ = Error;
|
||||
}
|
@ -26,4 +26,7 @@ test {
|
||||
_ = @import("Command.zig");
|
||||
_ = @import("TempDir.zig");
|
||||
_ = @import("terminal/Terminal.zig");
|
||||
|
||||
// TEMP
|
||||
_ = @import("libuv/main.zig");
|
||||
}
|
||||
|
1
vendor/libuv
vendored
Submodule
1
vendor/libuv
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9e59aa1bc8c4d215ea3e05eafec7181747206f67
|
Reference in New Issue
Block a user