diff --git a/build.zig b/build.zig index fbd4a9a76..c99995eb8 100644 --- a/build.zig +++ b/build.zig @@ -9,6 +9,7 @@ const harfbuzz = @import("pkg/harfbuzz/build.zig"); const libxml2 = @import("vendor/zig-libxml2/libxml2.zig"); const libuv = @import("pkg/libuv/build.zig"); const libpng = @import("pkg/libpng/build.zig"); +const macos = @import("pkg/macos/build.zig"); const utf8proc = @import("pkg/utf8proc/build.zig"); const zlib = @import("pkg/zlib/build.zig"); const tracylib = @import("pkg/tracy/build.zig"); @@ -183,6 +184,7 @@ fn addDeps( step.addPackage(glfw.pkg); step.addPackage(libuv.pkg); step.addPackage(utf8proc.pkg); + if (step.target.isDarwin()) step.addPackage(macos.pkg); // We always statically compile glad step.addIncludePath("vendor/glad/include/"); diff --git a/pkg/macos/build.zig b/pkg/macos/build.zig new file mode 100644 index 000000000..9f1eb1796 --- /dev/null +++ b/pkg/macos/build.zig @@ -0,0 +1,24 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub const pkg = std.build.Pkg{ + .name = "macos", + .source = .{ .path = thisDir() ++ "/main.zig" }, +}; + +fn thisDir() []const u8 { + return std.fs.path.dirname(@src().file) orelse "."; +} + +pub const Options = struct {}; + +pub fn link( + b: *std.build.Builder, + step: *std.build.LibExeObjStep, + opt: Options, +) !*std.build.LibExeObjStep { + _ = opt; + const lib = b.addStaticLibrary("macos", null); + step.linkFramework("CoreFoundation"); + return lib; +} diff --git a/pkg/macos/foundation.zig b/pkg/macos/foundation.zig new file mode 100644 index 000000000..f2abe233a --- /dev/null +++ b/pkg/macos/foundation.zig @@ -0,0 +1,6 @@ +pub usingnamespace @import("foundation/string.zig"); +pub usingnamespace @import("foundation/type.zig"); + +test { + @import("std").testing.refAllDecls(@This()); +} diff --git a/pkg/macos/foundation/string.zig b/pkg/macos/foundation/string.zig new file mode 100644 index 000000000..60feb19b2 --- /dev/null +++ b/pkg/macos/foundation/string.zig @@ -0,0 +1,54 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const cftype = @import("type.zig"); + +pub const String = opaque { + pub fn createWithBytes( + bs: []const u8, + encoding: StringEncoding, + external: bool, + ) Allocator.Error!*String { + return CFStringCreateWithBytes( + null, + bs.ptr, + bs.len, + @enumToInt(encoding), + external, + ) orelse Allocator.Error.OutOfMemory; + } + + pub fn release(self: *String) void { + cftype.CFRelease(self); + } + + pub extern "c" fn CFStringCreateWithBytes( + allocator: ?*anyopaque, + bytes: [*]const u8, + numBytes: usize, + encooding: u32, + is_external: bool, + ) ?*String; +}; + +/// https://developer.apple.com/documentation/corefoundation/cfstringencoding?language=objc +pub const StringEncoding = enum(u32) { + invalid = 0xffffffff, + mac_roman = 0, + windows_latin1 = 0x0500, + iso_latin1 = 0x0201, + nextstep_latin = 0x0B01, + ascii = 0x0600, + unicode = 0x0100, + utf8 = 0x08000100, + non_lossy_ascii = 0x0BFF, + utf16_be = 0x10000100, + utf16_le = 0x14000100, + utf32 = 0x0c000100, + utf32_be = 0x18000100, + utf32_le = 0x1c000100, +}; + +test "string" { + const str = try String.createWithBytes("hello world", .ascii, false); + defer str.release(); +} diff --git a/pkg/macos/foundation/type.zig b/pkg/macos/foundation/type.zig new file mode 100644 index 000000000..e3ee150f2 --- /dev/null +++ b/pkg/macos/foundation/type.zig @@ -0,0 +1 @@ +pub extern "c" fn CFRelease(*anyopaque) void; diff --git a/pkg/macos/main.zig b/pkg/macos/main.zig new file mode 100644 index 000000000..e651c0103 --- /dev/null +++ b/pkg/macos/main.zig @@ -0,0 +1,5 @@ +pub const foundation = @import("foundation.zig"); + +test { + @import("std").testing.refAllDecls(@This()); +}