diff --git a/build.zig b/build.zig index 03c9e23..a55bd38 100644 --- a/build.zig +++ b/build.zig @@ -20,9 +20,11 @@ pub fn build(b: *std.Build) !void { const tests = b.addTest(.{ .name = "objc-test", - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }), }); tests.linkSystemLibrary("objc"); tests.linkFramework("Foundation"); @@ -66,7 +68,7 @@ pub fn addAppleSDK(b: *std.Build, m: *std.Build.Module) !void { if (!gop.found_existing) { gop.value_ptr.* = std.zig.system.darwin.getSdk( b.allocator, - m.resolved_target.?.result, + &m.resolved_target.?.result, ); } diff --git a/build.zig.zon b/build.zig.zon index 2720c3a..523777e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -2,6 +2,7 @@ .name = .zig_objc, .version = "0.0.0", .fingerprint = 0x8a91772ba7d2bf22, + .minimum_zig_version = "0.15.1", .paths = .{ "src/", "build.zig", diff --git a/flake.lock b/flake.lock index 6616332..3cb2c5c 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1668681692, - "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "owner": "edolstra", "repo": "flake-compat", - "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "type": "github" }, "original": { @@ -33,12 +33,15 @@ } }, "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -49,7 +52,7 @@ }, "flake-utils_2": { "inputs": { - "systems": "systems" + "systems": "systems_2" }, "locked": { "lastModified": 1705309234, @@ -67,18 +70,15 @@ }, "nixpkgs": { "locked": { - "lastModified": 1717895720, - "narHash": "sha256-Dl6JKx1rIDEuv4q9rtlt9QwyerSQbrk1bUtNHzx9bIY=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "0e0826ec06d2b3db8e28e280d68179f022b1d160", - "type": "github" + "lastModified": 1755770914, + "narHash": "sha256-CPJ7DELncy3IRAs0XDbGuHVyjPjPNDbIu/XASVjIupA=", + "rev": "9cb344e96d5b6918e94e1bca2d9f3ea1e9615545", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/25.05/nixos-25.05.808519.9cb344e96d5b/nixexprs.tar.xz" }, "original": { - "owner": "nixos", - "ref": "release-24.05", - "repo": "nixpkgs", - "type": "github" + "type": "tarball", + "url": "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz" } }, "nixpkgs_2": { @@ -120,6 +120,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "zig": { "inputs": { "flake-compat": "flake-compat_2", @@ -127,11 +142,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1741702955, - "narHash": "sha256-Emk3VnNByigCBlBN34IH2cMrsUqIhdex02uw9TSDsN0=", + "lastModified": 1755909141, + "narHash": "sha256-dogbHGpLmwfu0qkM/vntqMYazfi66DXWSQiCR1rxC4M=", "owner": "mitchellh", "repo": "zig-overlay", - "rev": "1152ce759114a94134081270affd970ae1b957ed", + "rev": "e010faa4eb9271b81cb6c30c828d972028465deb", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 6717cab..edde8fd 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Objective-C runtime bindings for Zig"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/release-24.05"; + nixpkgs.url = "https://channels.nixos.org/nixos-25.05/nixexprs.tar.xz"; flake-utils.url = "github:numtide/flake-utils"; zig.url = "github:mitchellh/zig-overlay"; @@ -35,7 +35,7 @@ in rec { devShells.default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ - zigpkgs."0.14.0" + zigpkgs."0.15.1" ]; }; diff --git a/src/block.zig b/src/block.zig index 550f8e4..4df6dca 100644 --- a/src/block.zig +++ b/src/block.zig @@ -120,7 +120,7 @@ pub fn Block( _Block_release(@ptrCast(@alignCast(ctx))); } - fn descCopyHelper(src: *anyopaque, dst: *anyopaque) callconv(.C) void { + fn descCopyHelper(src: *anyopaque, dst: *anyopaque) callconv(.c) void { const real_src: *Context = @ptrCast(@alignCast(src)); const real_dst: *Context = @ptrCast(@alignCast(dst)); inline for (captures_info.fields) |field| { @@ -134,7 +134,7 @@ pub fn Block( } } - fn descDisposeHelper(src: *anyopaque) callconv(.C) void { + fn descDisposeHelper(src: *anyopaque) callconv(.c) void { const real_src: *Context = @ptrCast(@alignCast(src)); inline for (captures_info.fields) |field| { if (field.type == objc.c.id) { @@ -158,7 +158,7 @@ pub fn Block( return @Type(.{ .@"fn" = .{ - .calling_convention = .C, + .calling_convention = .c, .is_generic = false, .is_var_args = false, .return_type = Return, @@ -249,16 +249,16 @@ const BlockFieldFlags = enum(c_int) { byref_caller = 128, // BLOCK_BYREF_CALLER }; -extern "C" fn _Block_copy(src: *const anyopaque) callconv(.c) ?*anyopaque; -extern "C" fn _Block_release(src: *const anyopaque) callconv(.c) void; -extern "C" fn _Block_object_assign(dst: *anyopaque, src: *const anyopaque, flag: BlockFieldFlags) void; -extern "C" fn _Block_object_dispose(src: *const anyopaque, flag: BlockFieldFlags) void; +extern "c" fn _Block_copy(src: *const anyopaque) callconv(.c) ?*anyopaque; +extern "c" fn _Block_release(src: *const anyopaque) callconv(.c) void; +extern "c" fn _Block_object_assign(dst: *anyopaque, src: *const anyopaque, flag: BlockFieldFlags) void; +extern "c" fn _Block_object_dispose(src: *const anyopaque, flag: BlockFieldFlags) void; const Descriptor = extern struct { reserved: c_ulong = 0, size: c_ulong, - copy_helper: *const fn (dst: *anyopaque, src: *anyopaque) callconv(.C) void, - dispose_helper: *const fn (src: *anyopaque) callconv(.C) void, + copy_helper: *const fn (dst: *anyopaque, src: *anyopaque) callconv(.c) void, + dispose_helper: *const fn (src: *anyopaque) callconv(.c) void, signature: ?[*:0]const u8, }; @@ -287,7 +287,7 @@ test "Block" { }; var block: AddBlock.Context = AddBlock.init(captures, (struct { - fn addFn(block: *const AddBlock.Context) callconv(.C) i32 { + fn addFn(block: *const AddBlock.Context) callconv(.c) i32 { return block.x + block.y; } }).addFn); @@ -317,7 +317,7 @@ test "Block copy objc id" { var block = TestBlock.init(.{ .id = obj.value, }, (struct { - fn addFn(block: *const TestBlock.Context) callconv(.C) i32 { + fn addFn(block: *const TestBlock.Context) callconv(.c) i32 { _ = block; return 0; } diff --git a/src/class.zig b/src/class.zig index bf92b7c..34feea1 100644 --- a/src/class.zig +++ b/src/class.zig @@ -167,7 +167,7 @@ test "allocatecClassPair and replaceMethod" { const NSObject = getClass("NSObject").?; var my_object = allocateClassPair(NSObject, "my_object").?; my_object.replaceMethod("hash", struct { - fn inner(target: c.id, sel: c.SEL) callconv(.C) u64 { + fn inner(target: c.id, sel: c.SEL) callconv(.c) u64 { _ = sel; _ = target; return 69; @@ -208,7 +208,7 @@ test "addMethod" { const My_Class = allocateClassPair(objc.getClass("NSObject").?, "my_class").?; defer registerClassPair(My_Class); std.debug.assert(My_Class.addMethod("my_addition", struct { - fn imp(target: objc.c.id, sel: objc.c.SEL, a: i32, b: i32) callconv(.C) i32 { + fn imp(target: objc.c.id, sel: objc.c.SEL, a: i32, b: i32) callconv(.c) i32 { _ = sel; _ = target; return a + b; diff --git a/src/encoding.zig b/src/encoding.zig index 7fdafac..7cfdf1b 100644 --- a/src/encoding.zig +++ b/src/encoding.zig @@ -10,9 +10,9 @@ fn comptimeN(comptime T: type) usize { const encoding = objc.Encoding.init(T); // Figure out how much space we need - var counting = std.io.countingWriter(std.io.null_writer); - try std.fmt.format(counting.writer(), "{}", .{encoding}); - return counting.bytes_written; + var stream: std.io.Writer.Discarding = .init(&.{}); + stream.writer.print("{f}", .{encoding}) catch unreachable; + return stream.count; } } @@ -23,8 +23,8 @@ pub fn comptimeEncode(comptime T: type) [comptimeN(T):0]u8 { // Build our final signature var buf: [comptimeN(T) + 1]u8 = undefined; - var fbs = std.io.fixedBufferStream(buf[0 .. buf.len - 1]); - try std.fmt.format(fbs.writer(), "{}", .{encoding}); + var fbs: std.io.Writer = .fixed(buf[0 .. buf.len - 1]); + fbs.print("{f}", .{encoding}) catch unreachable; buf[buf.len - 1] = 0; return buf[0 .. buf.len - 1 :0].*; @@ -107,9 +107,7 @@ pub const Encoding = union(enum) { pub fn format( comptime self: Encoding, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, - writer: anytype, + writer: *std.io.Writer, ) !void { switch (self) { .char => try writer.writeAll("c"), @@ -133,7 +131,7 @@ pub const Encoding = union(enum) { .array => |a| { try writer.print("[{}", .{a.len}); const encode_type = init(a.arr_type); - try encode_type.format(fmt, options, writer); + try encode_type.format(writer); try writer.writeAll("]"); }, .structure => |s| { @@ -152,7 +150,7 @@ pub const Encoding = union(enum) { try writer.writeAll("="); inline for (struct_info.@"struct".fields) |field| { const field_encode = init(field.type); - try field_encode.format(fmt, options, writer); + try field_encode.format(writer); } } @@ -174,7 +172,7 @@ pub const Encoding = union(enum) { try writer.writeAll("="); inline for (union_info.@"union".fields) |field| { const field_encode = init(field.type); - try field_encode.format(fmt, options, writer); + try field_encode.format(writer); } } @@ -209,7 +207,7 @@ pub const Encoding = union(enum) { } // call this format function again, this time with the child type encoding - try encoding.format(fmt, options, writer); + try encoding.format(writer); }, else => @compileError("Pointer size not supported for encoding"), } @@ -219,10 +217,10 @@ pub const Encoding = union(enum) { // Return type is first in a method encoding const ret_type_enc = init(fn_info.return_type.?); - try ret_type_enc.format(fmt, options, writer); + try ret_type_enc.format(writer); inline for (fn_info.params) |param| { const param_enc = init(param.type.?); - try param_enc.format(fmt, options, writer); + try param_enc.format(writer); } }, .unknown => {}, @@ -249,7 +247,7 @@ fn indirectionCountAndType(comptime T: type) struct { fn encodingMatchesType(comptime T: type, expected_encoding: []const u8) !void { var buf: [200]u8 = undefined; const enc = Encoding.init(T); - const enc_string = try std.fmt.bufPrint(&buf, "{s}", .{enc}); + const enc_string = try std.fmt.bufPrint(&buf, "{f}", .{enc}); try testing.expectEqualStrings(expected_encoding, enc_string); } @@ -400,7 +398,7 @@ test "**Union to Encoding.union encoding" { test "Fn to Encoding.function encoding" { const test_fn = struct { - fn add(_: c.id, _: c.SEL, _: i8) callconv(.C) void {} + fn add(_: c.id, _: c.SEL, _: i8) callconv(.c) void {} }; try encodingMatchesType(@TypeOf(test_fn.add), "v@:c"); diff --git a/src/msg_send.zig b/src/msg_send.zig index 39fb5a9..2382e2a 100644 --- a/src/msg_send.zig +++ b/src/msg_send.zig @@ -78,7 +78,7 @@ pub fn MsgSend(comptime T: type) type { fn msgSendPtr( comptime Return: type, comptime super: bool, - ) *const fn () callconv(.C) void { + ) *const fn () callconv(.c) void { // See objc/message.h. The high-level is that depending on the // target architecture and return type, we must use a different // objc_msgSend function. @@ -204,7 +204,7 @@ fn MsgSendFn( return @Type(.{ .@"fn" = .{ - .calling_convention = .C, + .calling_convention = .c, .is_generic = false, .is_var_args = false, .return_type = Return, @@ -218,8 +218,8 @@ test { try testing.expectEqual(fn ( c.id, c.SEL, - ) callconv(.C) u64, MsgSendFn(u64, c.id, @TypeOf(.{}))); - try testing.expectEqual(fn (c.id, c.SEL, u16, u32) callconv(.C) u64, MsgSendFn(u64, c.id, @TypeOf(.{ + ) callconv(.c) u64, MsgSendFn(u64, c.id, @TypeOf(.{}))); + try testing.expectEqual(fn (c.id, c.SEL, u16, u32) callconv(.c) u64, MsgSendFn(u64, c.id, @TypeOf(.{ @as(u16, 0), @as(u32, 0), }))); @@ -229,7 +229,7 @@ test "subClass" { const Subclass = objc.allocateClassPair(objc.getClass("NSObject").?, "subclass").?; defer objc.disposeClassPair(Subclass); const str = struct { - fn inner(target: objc.c.id, sel: objc.c.SEL) callconv(.C) objc.c.id { + fn inner(target: objc.c.id, sel: objc.c.SEL) callconv(.c) objc.c.id { _ = sel; const self = objc.Object.fromId(target); self.msgSendSuper(objc.getClass("NSObject").?, void, "init", .{});