diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f7c4a9..779d03b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,8 @@ jobs: - name: Setup Zig for OpenHarmony uses: openharmony-zig/setup-zig-ohos@v0.1.0 id: setup-zig + with: + tag: '0.16.0' - name: Build run: | diff --git a/README.md b/README.md index bfbc609..8a1ad8a 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,10 @@ We recommend you use ZON(Zig Package Manager) to install it. .{ .name = "appname", .version = "0.0.0", + .minimum_zig_version = "0.16.0", .dependencies = .{ - .network = .{ - .url = "https://github.com/openharmony-zig/zig-addon/archive/refs/tags/.tar.gz", + .@"zig-napi" = .{ + .url = "https://github.com/openharmony-zig/zig-napi/archive/refs/tags/.tar.gz", .hash = "HASH_GOES_HERE", }, }, @@ -43,9 +44,11 @@ pub fn build(b: *std.Build) !void { const result = try napi_build.nativeAddonBuild(b, .{ .name = "hello", - .root_source_file = b.path("./src/hello.zig"), - .target = target, - .optimize = optimize, + .root_module_options = .{ + .root_source_file = b.path("./src/hello.zig"), + .target = target, + .optimize = optimize, + }, }); if (result.arm64) |arm64| { diff --git a/build.zig.zon b/build.zig.zon index ff36ebe..bc382b2 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .zig_napi, .version = "0.0.1-beta.2", - .minimum_zig_version = "0.15.1", + .minimum_zig_version = "0.16.0", .dependencies = .{}, .fingerprint = 0x6093bdd26bb0a31f, .paths = .{ diff --git a/examples/basic/build.zig.zon b/examples/basic/build.zig.zon index 2ddf71a..1d49e63 100644 --- a/examples/basic/build.zig.zon +++ b/examples/basic/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .add, .version = "0.0.1", - .minimum_zig_version = "0.15.1", + .minimum_zig_version = "0.16.0", .fingerprint = 0xfd1a73e7f96390fb, .dependencies = .{ .@"zig-napi" = .{ .path = "../.." } }, .paths = .{ "build.zig", "build.zig.zon", "src" }, diff --git a/examples/basic/src/thread_safe_function.zig b/examples/basic/src/thread_safe_function.zig index a9d8f7c..1e09dea 100644 --- a/examples/basic/src/thread_safe_function.zig +++ b/examples/basic/src/thread_safe_function.zig @@ -4,13 +4,21 @@ const napi = @import("napi"); const Args = struct { i32, i32 }; const Return = i32; +fn sleepForFiveSeconds() void { + var req = std.c.timespec{ + .sec = 5, + .nsec = 0, + }; + _ = std.c.nanosleep(&req, null); +} + fn execute_thread_safe_function(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) void { - std.Thread.sleep(5_000_000_000); + sleepForFiveSeconds(); tsfn.Ok(.{ 1, 2 }, .NonBlocking); } fn execute_thread_safe_function_with_error(tsfn: *napi.ThreadSafeFunction(Args, Return, true, 0)) void { - std.Thread.sleep(5_000_000_000); + sleepForFiveSeconds(); tsfn.Err(napi.Error.withReason("TSFN Error"), .NonBlocking); } diff --git a/examples/init/build.zig.zon b/examples/init/build.zig.zon index e54059c..1d49e63 100644 --- a/examples/init/build.zig.zon +++ b/examples/init/build.zig.zon @@ -1,7 +1,7 @@ .{ .name = .add, .version = "0.0.1", - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.16.0", .fingerprint = 0xfd1a73e7f96390fb, .dependencies = .{ .@"zig-napi" = .{ .path = "../.." } }, .paths = .{ "build.zig", "build.zig.zon", "src" }, diff --git a/src/build/napi-build.zig b/src/build/napi-build.zig index 76f34b0..7d9ab99 100644 --- a/src/build/napi-build.zig +++ b/src/build/napi-build.zig @@ -1,12 +1,7 @@ const std = @import("std"); -fn getEnvVarOptional(allocator: std.mem.Allocator, name: []const u8) !?[]const u8 { - return std.process.getEnvVarOwned(allocator, name) catch |err| { - if (err == error.EnvironmentVariableNotFound) { - return null; - } - return err; - }; +fn getEnvVarOptional(build: *std.Build, name: []const u8) ?[]const u8 { + return build.graph.environ_map.get(name); } pub fn cloneLibraryOptions(build: *std.Build, option: NativeAddonBuildOptionsWithModule, target: std.Build.ResolvedTarget) std.Build.LibraryOptions { @@ -49,20 +44,13 @@ pub fn cloneLibraryOptions(build: *std.Build, option: NativeAddonBuildOptionsWit } pub fn resolveNdkPath(build: *std.Build) ![]const u8 { - const allocator = build.allocator; - - var ndkRoot: ?[]const u8 = null; - - const home = try getEnvVarOptional(allocator, "OHOS_NDK_HOME"); - if (home) |v| { - ndkRoot = try std.fs.path.join(allocator, &[_][]const u8{ v, "native" }); - } else { - const ohos_sdk_native = try getEnvVarOptional(allocator, "ohos_sdk_native"); - if (ohos_sdk_native) |v| { - ndkRoot = v; - } + if (getEnvVarOptional(build, "OHOS_NDK_HOME")) |home| { + return build.pathJoin(&.{ home, "native" }); + } + if (getEnvVarOptional(build, "ohos_sdk_native")) |native| { + return native; } - return ndkRoot orelse ""; + return ""; } const targets: []const std.Target.Query = &.{ diff --git a/src/build/napi-tsgen.zig b/src/build/napi-tsgen.zig index a1ffa9e..e79d4b7 100644 --- a/src/build/napi-tsgen.zig +++ b/src/build/napi-tsgen.zig @@ -261,11 +261,13 @@ const ParsedSourceParams = struct { const SourceResolver = struct { allocator: std.mem.Allocator, + io: std.Io, root_source_path: []const u8, - fn init(allocator: std.mem.Allocator, root_source_path: []const u8) SourceResolver { + fn init(allocator: std.mem.Allocator, io: std.Io, root_source_path: []const u8) SourceResolver { return .{ .allocator = allocator, + .io = io, .root_source_path = root_source_path, }; } @@ -515,10 +517,10 @@ const SourceResolver = struct { if (param.len == 0 or std.mem.eql(u8, param, "...")) return; if (std.mem.startsWith(u8, param, "comptime ")) { - param = std.mem.trimLeft(u8, param["comptime ".len..], " \t"); + param = std.mem.trimStart(u8, param["comptime ".len..], " \t"); } if (std.mem.startsWith(u8, param, "noalias ")) { - param = std.mem.trimLeft(u8, param["noalias ".len..], " \t"); + param = std.mem.trimStart(u8, param["noalias ".len..], " \t"); } const colon = std.mem.indexOfScalar(u8, param, ':') orelse return; @@ -538,10 +540,10 @@ const SourceResolver = struct { if (std.mem.eql(u8, param, "...")) return; if (std.mem.startsWith(u8, param, "comptime ")) { - param = std.mem.trimLeft(u8, param["comptime ".len..], " \t"); + param = std.mem.trimStart(u8, param["comptime ".len..], " \t"); } if (std.mem.startsWith(u8, param, "noalias ")) { - param = std.mem.trimLeft(u8, param["noalias ".len..], " \t"); + param = std.mem.trimStart(u8, param["noalias ".len..], " \t"); } const colon = std.mem.indexOfScalar(u8, param, ':') orelse return; @@ -551,7 +553,7 @@ const SourceResolver = struct { } fn readFile(self: *SourceResolver, file_path: []const u8) ![]const u8 { - return try std.fs.cwd().readFileAlloc(file_path, self.allocator, .unlimited); + return try std.Io.Dir.cwd().readFileAlloc(self.io, file_path, self.allocator, .limited(std.math.maxInt(usize))); } fn resolveImportPath(self: *SourceResolver, file_path: []const u8, alias: []const u8) !?[]const u8 { @@ -608,7 +610,7 @@ fn trimAfterBalancedCall(text: []const u8) ?[]const u8 { ')' => { depth -= 1; if (depth == 0) { - return std.mem.trimLeft(u8, text[i + 1 ..], " \t\r\n"); + return std.mem.trimStart(u8, text[i + 1 ..], " \t\r\n"); } }, else => {}, @@ -640,7 +642,7 @@ fn matchConstAssignment(line: []const u8, symbol: []const u8) ?[]const u8 { if (!std.mem.eql(u8, lhs, symbol)) return null; const rhs_full = std.mem.trim(u8, rest[eq_index + 1 ..], " \t"); - return std.mem.trimRight(u8, rhs_full, ";"); + return std.mem.trimEnd(u8, rhs_full, ";"); } fn tryMatchConstPrefix(line: []const u8) ?usize { @@ -666,7 +668,7 @@ const ObjectSetCall = struct { fn matchObjectSetCall(line: []const u8, object_name: []const u8) ?ObjectSetCall { var rest = std.mem.trim(u8, line, " \t\r\n"); if (std.mem.startsWith(u8, rest, "try ")) { - rest = std.mem.trimLeft(u8, rest["try ".len..], " \t"); + rest = std.mem.trimStart(u8, rest["try ".len..], " \t"); } if (!std.mem.startsWith(u8, rest, object_name)) return null; @@ -677,9 +679,9 @@ fn matchObjectSetCall(line: []const u8, object_name: []const u8) ?ObjectSetCall const name_end = std.mem.indexOfScalar(u8, rest, '"') orelse return null; const name = rest[0..name_end]; - rest = std.mem.trimLeft(u8, rest[name_end + 1 ..], " \t"); + rest = std.mem.trimStart(u8, rest[name_end + 1 ..], " \t"); if (rest.len == 0 or rest[0] != ',') return null; - rest = std.mem.trimLeft(u8, rest[1..], " \t"); + rest = std.mem.trimStart(u8, rest[1..], " \t"); const call_end = std.mem.lastIndexOfScalar(u8, rest, ')') orelse return null; const value_expr = std.mem.trim(u8, rest[0..call_end], " \t"); @@ -1361,7 +1363,7 @@ fn isSourceNumericType(type_expr: []const u8) bool { fn trimConstType(type_expr: []const u8) []const u8 { const trimmed = std.mem.trim(u8, type_expr, " \t\r\n"); if (std.mem.startsWith(u8, trimmed, "const ")) { - return std.mem.trimLeft(u8, trimmed["const ".len..], " \t"); + return std.mem.trimStart(u8, trimmed["const ".len..], " \t"); } return trimmed; } @@ -1684,8 +1686,8 @@ fn appendHeader(writer: *StringBuilder, header: []const u8) !void { try append(writer, "\n"); } -fn generate(allocator: std.mem.Allocator, root_source_path: []const u8, header: []const u8) ![]u8 { - var source = SourceResolver.init(allocator, root_source_path); +fn generate(allocator: std.mem.Allocator, io: std.Io, root_source_path: []const u8, header: []const u8) ![]u8 { + var source = SourceResolver.init(allocator, io, root_source_path); var state = State.init(allocator, &source); defer state.deinit(); @@ -1738,21 +1740,21 @@ fn generate(allocator: std.mem.Allocator, root_source_path: []const u8, header: return try output.toOwnedSlice(); } -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); +pub fn main(init: std.process.Init) !void { + const io = init.io; + const allocator = init.arena.allocator(); + const args = try init.minimal.args.toSlice(allocator); - var args = try std.process.argsWithAllocator(allocator); - defer args.deinit(); + if (args.len < 3) return error.InvalidArgument; - _ = args.next(); - const output_path = args.next() orelse return error.InvalidArgument; - const root_source_path = args.next() orelse return error.InvalidArgument; - const header = args.next() orelse ""; + const output_path = args[1]; + const root_source_path = args[2]; + const header = if (args.len > 3) args[3] else ""; - const content = try generate(allocator, root_source_path, header); - const file = try std.fs.cwd().createFile(output_path, .{ .truncate = true }); - defer file.close(); - try file.writeAll(content); + const content = try generate(allocator, io, root_source_path, header); + try std.Io.Dir.cwd().writeFile(io, .{ + .sub_path = output_path, + .data = content, + .flags = .{ .truncate = true }, + }); } diff --git a/src/napi/util/helper.zig b/src/napi/util/helper.zig index 4b84db6..cd0f5c4 100644 --- a/src/napi/util/helper.zig +++ b/src/napi/util/helper.zig @@ -185,24 +185,13 @@ pub fn collectFunctionArgs(comptime functions: anytype) type { const args_len = infos.@"fn".params.len; - var fields: [args_len]std.builtin.Type.StructField = undefined; + var field_types: [args_len]type = undefined; inline for (0..args_len) |i| { - fields[i] = std.builtin.Type.StructField{ - .name = std.fmt.comptimePrint("{d}", .{i}), - .type = infos.@"fn".params[i].type.?, - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(infos.@"fn".params[i].type.?), - }; - } - - return @Type(std.builtin.Type{ .@"struct" = std.builtin.Type.Struct{ - .layout = .auto, - .fields = &fields, - .decls = &[_]std.builtin.Type.Declaration{}, - .is_tuple = true, - } }); + field_types[i] = infos.@"fn".params[i].type.?; + } + + return std.meta.Tuple(&field_types); } pub fn shortTypeName(comptime T: type) []const u8 {