diff --git a/pkg/macos/build.zig b/pkg/macos/build.zig index ffa76ac08..670a7ccb9 100644 --- a/pkg/macos/build.zig +++ b/pkg/macos/build.zig @@ -22,6 +22,7 @@ pub fn link( defer flags.deinit(); const lib = b.addStaticLibrary("macos", null); + step.addCSourceFile(comptime thisDir() ++ "/os/log.c", flags.items); step.addCSourceFile(comptime thisDir() ++ "/text/ext.c", flags.items); step.linkFramework("CoreFoundation"); step.linkFramework("CoreText"); diff --git a/pkg/macos/main.zig b/pkg/macos/main.zig index 91b99ce48..73bc5d3f6 100644 --- a/pkg/macos/main.zig +++ b/pkg/macos/main.zig @@ -1,5 +1,6 @@ pub const foundation = @import("foundation.zig"); pub const graphics = @import("graphics.zig"); +pub const os = @import("os.zig"); pub const text = @import("text.zig"); test { diff --git a/pkg/macos/os.zig b/pkg/macos/os.zig new file mode 100644 index 000000000..81ece7314 --- /dev/null +++ b/pkg/macos/os.zig @@ -0,0 +1,6 @@ +pub const c = @import("os/c.zig"); +pub usingnamespace @import("os/log.zig"); + +test { + @import("std").testing.refAllDecls(@This()); +} diff --git a/pkg/macos/os/c.zig b/pkg/macos/os/c.zig new file mode 100644 index 000000000..74cf51791 --- /dev/null +++ b/pkg/macos/os/c.zig @@ -0,0 +1,3 @@ +pub usingnamespace @cImport({ + @cInclude("os/log.h"); +}); diff --git a/pkg/macos/os/log.c b/pkg/macos/os/log.c new file mode 100644 index 000000000..f024b3863 --- /dev/null +++ b/pkg/macos/os/log.c @@ -0,0 +1,10 @@ +#include + +// A wrapper so we can use the os_log_with_type macro. +void zig_os_log_with_type( + os_log_t log, + os_log_type_t type, + const char *message +) { + os_log_with_type(log, type, "%s", message); +} diff --git a/pkg/macos/os/log.zig b/pkg/macos/os/log.zig new file mode 100644 index 000000000..49c93f491 --- /dev/null +++ b/pkg/macos/os/log.zig @@ -0,0 +1,60 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const c = @import("c.zig"); + +pub const Log = opaque { + pub fn create( + subsystem: [:0]const u8, + category: [:0]const u8, + ) *Log { + return @intToPtr(?*Log, @ptrToInt(c.os_log_create( + subsystem.ptr, + category.ptr, + ))).?; + } + + pub fn release(self: *Log) void { + c.os_release(self); + } + + pub fn typeEnabled(self: *Log, typ: LogType) bool { + return c.os_log_type_enabled( + @ptrCast(c.os_log_t, self), + @enumToInt(typ), + ); + } + + pub fn log( + self: *Log, + alloc: Allocator, + typ: LogType, + comptime format: []const u8, + args: anytype, + ) void { + const str = nosuspend std.fmt.allocPrintZ(alloc, format, args) catch return; + defer alloc.free(str); + zig_os_log_with_type(self, typ, str.ptr); + } + + extern "c" fn zig_os_log_with_type(*Log, LogType, [*c]const u8) void; +}; + +/// https://developer.apple.com/documentation/os/os_log_type_t?language=objc +pub const LogType = enum(c.os_log_type_t) { + default = c.OS_LOG_TYPE_DEFAULT, + debug = c.OS_LOG_TYPE_DEBUG, + info = c.OS_LOG_TYPE_INFO, + err = c.OS_LOG_TYPE_ERROR, + fault = c.OS_LOG_TYPE_FAULT, +}; + +test { + const testing = std.testing; + + const log = Log.create("com.mitchellh.ghostty", "test"); + defer log.release(); + + try testing.expect(log.typeEnabled(.fault)); + log.log(testing.allocator, .default, "hello {d}", .{12}); +}