From 4b6f66fd512c254b5a82220dc77411fe391dd258 Mon Sep 17 00:00:00 2001 From: David Czihak Date: Sat, 9 May 2026 13:01:50 +0200 Subject: Chore: Rework examples for thorough extension testing --- examples/multi-step/.gitignore | 2 + examples/multi-step/.nova/Configuration.json | 4 + examples/multi-step/.nova/Tasks/Zig Package.json | 10 +++ examples/multi-step/.nova/Tasks/Zig Test.json | 10 +++ examples/multi-step/.nova/Tasks/Zig Watch.json | 11 +++ examples/multi-step/build.zig | 96 ++++++++++++++++++++++++ examples/multi-step/build.zig.zon | 12 +++ examples/multi-step/src/lib.zig | 67 +++++++++++++++++ examples/multi-step/src/main.zig | 35 +++++++++ 9 files changed, 247 insertions(+) create mode 100644 examples/multi-step/.gitignore create mode 100644 examples/multi-step/.nova/Configuration.json create mode 100644 examples/multi-step/.nova/Tasks/Zig Package.json create mode 100644 examples/multi-step/.nova/Tasks/Zig Test.json create mode 100644 examples/multi-step/.nova/Tasks/Zig Watch.json create mode 100644 examples/multi-step/build.zig create mode 100644 examples/multi-step/build.zig.zon create mode 100644 examples/multi-step/src/lib.zig create mode 100644 examples/multi-step/src/main.zig (limited to 'examples/multi-step') diff --git a/examples/multi-step/.gitignore b/examples/multi-step/.gitignore new file mode 100644 index 0000000..3389c86 --- /dev/null +++ b/examples/multi-step/.gitignore @@ -0,0 +1,2 @@ +.zig-cache/ +zig-out/ diff --git a/examples/multi-step/.nova/Configuration.json b/examples/multi-step/.nova/Configuration.json new file mode 100644 index 0000000..44cadf8 --- /dev/null +++ b/examples/multi-step/.nova/Configuration.json @@ -0,0 +1,4 @@ +{ + "zls.enable_build_on_save" : false, + "zls.zig_exe_path" : "\/opt\/homebrew\/bin\/zig" +} diff --git a/examples/multi-step/.nova/Tasks/Zig Package.json b/examples/multi-step/.nova/Tasks/Zig Package.json new file mode 100644 index 0000000..db6905c --- /dev/null +++ b/examples/multi-step/.nova/Tasks/Zig Package.json @@ -0,0 +1,10 @@ +{ + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigBuildRun", + "extensionValues" : { + "runStep" : "run" + } +} diff --git a/examples/multi-step/.nova/Tasks/Zig Test.json b/examples/multi-step/.nova/Tasks/Zig Test.json new file mode 100644 index 0000000..7517ee7 --- /dev/null +++ b/examples/multi-step/.nova/Tasks/Zig Test.json @@ -0,0 +1,10 @@ +{ + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigTest", + "extensionValues" : { + "summary" : "failures" + } +} diff --git a/examples/multi-step/.nova/Tasks/Zig Watch.json b/examples/multi-step/.nova/Tasks/Zig Watch.json new file mode 100644 index 0000000..aed951a --- /dev/null +++ b/examples/multi-step/.nova/Tasks/Zig Watch.json @@ -0,0 +1,11 @@ +{ + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigWatch", + "extensionValues" : { + "incremental" : "on", + "step" : "run" + } +} diff --git a/examples/multi-step/build.zig b/examples/multi-step/build.zig new file mode 100644 index 0000000..f9a2d3d --- /dev/null +++ b/examples/multi-step/build.zig @@ -0,0 +1,96 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const lib_mod = b.addModule("multi_step", .{ + .root_source_file = b.path("src/lib.zig"), + .target = target, + }); + + const exe = b.addExecutable(.{ + .name = "multi-step", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ .name = "multi_step", .module = lib_mod }, + }, + }), + }); + b.installArtifact(exe); + + // ── Step: run ────────────────────────────────────────────────────────────── + const run_cmd = b.addRunArtifact(exe); + if (b.args) |args| run_cmd.addArgs(args); + const run_step = b.step("run", "Build and run the multi-step demo"); + run_step.dependOn(&run_cmd.step); + + // ── Step: test ───────────────────────────────────────────────────────────── + const lib_tests = b.addTest(.{ .root_module = lib_mod }); + const run_tests = b.addRunArtifact(lib_tests); + const test_step = b.step("test", "Run all unit tests"); + test_step.dependOn(&run_tests.step); + + // ── Step: check-fmt (hyphenated) ─────────────────────────────────────────── + const fmt_check = b.addFmt(.{ + .paths = &.{ "src", "build.zig" }, + .check = true, + }); + const fmt_step = b.step("check-fmt", "Verify source formatting without modifying files"); + fmt_step.dependOn(&fmt_check.step); + + // ── Step: gen-docs (hyphenated) ──────────────────────────────────────────── + const docs = b.addInstallDirectory(.{ + .source_dir = exe.getEmittedDocs(), + .install_dir = .prefix, + .install_subdir = "docs", + }); + const docs_step = b.step("gen-docs", "Generate and install HTML documentation"); + docs_step.dependOn(&docs.step); + + // ── Step: run_server (underscore) ────────────────────────────────────────── + const server_cmd = b.addRunArtifact(exe); + server_cmd.addArg("--server"); + const server_step = b.step("run_server", "Run the executable in server mode"); + server_step.dependOn(&server_cmd.step); + + // ── Step: bench (short name, ReleaseFast) ────────────────────────────────── + const bench_exe = b.addExecutable(.{ + .name = "bench", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = .ReleaseFast, + .imports = &.{ + .{ .name = "multi_step", .module = lib_mod }, + }, + }), + }); + const bench_cmd = b.addRunArtifact(bench_exe); + bench_cmd.addArg("--bench"); + const bench_step = b.step("bench", "Build and run benchmarks (ReleaseFast)"); + bench_step.dependOn(&bench_cmd.step); + + // ── Step: release-macos (compound hyphenated, cross-compile) ─────────────── + const macos_target = b.resolveTargetQuery(.{ + .cpu_arch = .aarch64, + .os_tag = .macos, + }); + const release_exe = b.addExecutable(.{ + .name = "multi-step", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = macos_target, + .optimize = .ReleaseSmall, + .imports = &.{ + .{ .name = "multi_step", .module = lib_mod }, + }, + }), + }); + const release_install = b.addInstallArtifact(release_exe, .{}); + const release_step = b.step("release-macos", "Build a ReleaseSmall binary for aarch64-macos"); + release_step.dependOn(&release_install.step); +} diff --git a/examples/multi-step/build.zig.zon b/examples/multi-step/build.zig.zon new file mode 100644 index 0000000..16f0449 --- /dev/null +++ b/examples/multi-step/build.zig.zon @@ -0,0 +1,12 @@ +.{ + .name = .multi_step, + .version = "0.1.0", + .fingerprint = 0x15810748d919d76b, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/examples/multi-step/src/lib.zig b/examples/multi-step/src/lib.zig new file mode 100644 index 0000000..ea244c1 --- /dev/null +++ b/examples/multi-step/src/lib.zig @@ -0,0 +1,67 @@ +const std = @import("std"); + +/// Returns the sum of a slice of i32 values. +pub fn sum(values: []const i32) i64 { + var total: i64 = 0; + for (values) |v| total += v; + return total; +} + +/// Returns the product of a slice of i32 values. +/// Returns 1 for an empty slice (identity element). +pub fn product(values: []const i32) i64 { + var result: i64 = 1; + for (values) |v| result *= v; + return result; +} + +/// Returns the minimum value, or null for an empty slice. +pub fn min(values: []const i32) ?i32 { + if (values.len == 0) return null; + var m = values[0]; + for (values[1..]) |v| { + if (v < m) m = v; + } + return m; +} + +/// Returns the maximum value, or null for an empty slice. +pub fn max(values: []const i32) ?i32 { + if (values.len == 0) return null; + var m = values[0]; + for (values[1..]) |v| { + if (v > m) m = v; + } + return m; +} + +test "sum empty" { + try std.testing.expectEqual(@as(i64, 0), sum(&.{})); +} + +test "sum positive values" { + try std.testing.expectEqual(@as(i64, 15), sum(&.{ 1, 2, 3, 4, 5 })); +} + +test "sum with negatives" { + try std.testing.expectEqual(@as(i64, 0), sum(&.{ -3, -2, -1, 0, 1, 2, 3 })); +} + +test "product empty" { + try std.testing.expectEqual(@as(i64, 1), product(&.{})); +} + +test "product small" { + try std.testing.expectEqual(@as(i64, 120), product(&.{ 1, 2, 3, 4, 5 })); +} + +test "min and max" { + const data = [_]i32{ 3, 1, 4, 1, 5, 9, 2, 6 }; + try std.testing.expectEqual(@as(?i32, 1), min(&data)); + try std.testing.expectEqual(@as(?i32, 9), max(&data)); +} + +test "min max empty" { + try std.testing.expectEqual(@as(?i32, null), min(&.{})); + try std.testing.expectEqual(@as(?i32, null), max(&.{})); +} diff --git a/examples/multi-step/src/main.zig b/examples/multi-step/src/main.zig new file mode 100644 index 0000000..a984b18 --- /dev/null +++ b/examples/multi-step/src/main.zig @@ -0,0 +1,35 @@ +const std = @import("std"); +const lib = @import("multi_step"); + +pub fn main(init: std.process.Init) !void { + const io = init.io; + var buf: [4096]u8 = undefined; + var fw: std.Io.File.Writer = .init(.stdout(), io, &buf); + defer fw.interface.flush() catch {}; + const w = &fw.interface; + + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const mode = if (args.len > 1) args[1] else ""; + + if (std.mem.eql(u8, mode, "--server")) { + try w.print("Server mode (simulated)\n", .{}); + return; + } + + if (std.mem.eql(u8, mode, "--bench")) { + const data = [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var i: u32 = 0; + while (i < 1_000_000) : (i += 1) { + _ = lib.sum(&data); + } + try w.print("bench: 1M sum() calls completed\n", .{}); + return; + } + + const data = [_]i32{ 10, 20, 30, 40, 50 }; + try w.print("data: {any}\n", .{data}); + try w.print("sum = {d}\n", .{lib.sum(&data)}); + try w.print("product = {d}\n", .{lib.product(&data)}); + try w.print("min = {?d}\n", .{lib.min(&data)}); + try w.print("max = {?d}\n", .{lib.max(&data)}); +} -- cgit v1.3