From 098b1b3bc7774aa0f9e6a4facf641c3d6e793e68 Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Sat, 24 Oct 2026 07:57:09 -0500 Subject: [PATCH 1/6] lint: line-length (codex) Agent-Team: linux Worker: codex --- scripts/demos.zig | 22 ++++++++++++-- scripts/lint.zig | 60 ++++++++++++++++++++++++++++++--------- scripts/tests_reached.zig | 6 +++- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/scripts/demos.zig b/scripts/demos.zig index 59bfb9ffd..b6b821731 100644 --- a/scripts/demos.zig +++ b/scripts/demos.zig @@ -83,19 +83,35 @@ pub fn main(init: std.process.Init) !void { /// Write `t` as `.tape` in `out`, having read it back from those bytes. The row is `arena`'s: /// the tape goes before the index is written. -fn emit(arena: std.mem.Allocator, gpa: std.mem.Allocator, io: std.Io, out: std.Io.Dir, rows: []const Row, name: []const u8, t: Tape, live: bool) !Row { +fn emit( + arena: std.mem.Allocator, + gpa: std.mem.Allocator, + io: std.Io, + out: std.Io.Dir, + rows: []const Row, + name: []const u8, + t: Tape, + live: bool, +) !Row { for (rows) |r| if (std.mem.eql(u8, r.name, name)) return fail("two tapes are named '{s}'", .{name}); var bytes: std.Io.Writer.Allocating = .init(arena); try tape.binary.write(gpa, t, &bytes.writer, .{ .deflate = true }); var c = check; c.live = live; - var back = tape.binary.read(gpa, bytes.written(), c) catch |err| return fail("{s}: its tape does not read back: {t}", .{ name, err }); + var back = tape.binary.read(gpa, bytes.written(), c) catch |err| + return fail("{s}: its tape does not read back: {t}", .{ name, err }); defer back.deinit(); if (back.tape.ops.len != t.ops.len or back.tape.duration() != t.duration()) return fail("{s}: its tape reads back as another", .{name}); const file = try arena.print("{s}.tape", .{name}); try out.writeFile(io, .{ .sub_path = file, .data = bytes.written() }); - return .{ .name = try arena.dupe(u8, name), .title = try arena.dupe(u8, t.title), .file = file, .ms = t.duration(), .live = live }; + return .{ + .name = try arena.dupe(u8, name), + .title = try arena.dupe(u8, t.title), + .file = file, + .ms = t.duration(), + .live = live, + }; } fn fail(comptime fmt: []const u8, args: anytype) error{DemoFailed} { diff --git a/scripts/lint.zig b/scripts/lint.zig index 2cc3087b4..10ef9af94 100644 --- a/scripts/lint.zig +++ b/scripts/lint.zig @@ -1,7 +1,14 @@ //! Repository lint with per-file budgets for existing findings. const std = @import("std"); -const Rule = enum { @"fn-length", @"create-needs-destroy", @"lint-allow-reason", @"file-alias", anyerror, @"deprecated-names-replacement" }; +const Rule = enum { + @"fn-length", + @"create-needs-destroy", + @"lint-allow-reason", + @"file-alias", + anyerror, + @"deprecated-names-replacement", +}; const Finding = struct { rule: Rule, line: usize, message: []const u8 }; const Allow = struct { rule: Rule, file: []const u8, count: usize }; const Suppression = struct { rule: []const u8, line: usize }; @@ -60,7 +67,10 @@ pub fn main(init: std.process.Init) !void { } } for (parsed, seen) |allow, visited| if (!visited) { - try output.writer.print("{s}:1: {s}: file not found; remove its allowance of {d}\n", .{ allow.file, @tagName(allow.rule), allow.count }); + try output.writer.print( + "{s}:1: {s}: file not found; remove its allowance of {d}\n", + .{ allow.file, @tagName(allow.rule), allow.count }, + ); failed = true; }; std.debug.print("{s}", .{output.written()}); @@ -98,11 +108,17 @@ fn reportFile( } switch (status) { .over => { - try writer.print("{s}:1: {s}: count {d} exceeds allowance {d}\n", .{ path, @tagName(rule), count, budget }); + try writer.print( + "{s}:1: {s}: count {d} exceeds allowance {d}\n", + .{ path, @tagName(rule), count, budget }, + ); failed = true; }, .under => { - try writer.print("{s}:1: {s}: count {d} is under allowance {d}; lower the allowance to {d}\n", .{ path, @tagName(rule), count, budget, count }); + try writer.print( + "{s}:1: {s}: count {d} is under allowance {d}; lower the allowance to {d}\n", + .{ path, @tagName(rule), count, budget, count }, + ); failed = true; }, .equal => {}, @@ -135,7 +151,11 @@ fn analyze(allocator: std.mem.Allocator, source: [:0]const u8) ![]Finding { const close = std.mem.findScalar(u8, text, ')') orelse text.len; const tail = if (close < text.len) std.mem.trim(u8, text[close + 1 ..], " \t\r") else ""; if (tail.len < 2 or tail[0] != ':' or std.mem.trim(u8, tail[1..], " \t\r").len == 0) { - try findings.append(allocator, .{ .rule = .@"lint-allow-reason", .line = line_number, .message = "lint-allow requires a reason after ':'" }); + try findings.append(allocator, .{ + .rule = .@"lint-allow-reason", + .line = line_number, + .message = "lint-allow requires a reason after ':'", + }); } else { try suppressions.append(allocator, .{ .rule = text[prefix.len..close], .line = line_number }); } @@ -175,7 +195,11 @@ fn analyze(allocator: std.mem.Allocator, source: [:0]const u8) ![]Finding { const end = tree.tokenLocation(0, tree.lastToken(node)).line + 1; const length = end - line + 1; if (length > 150 and !silenced(suppressions.items, .@"fn-length", line)) { - try findings.append(allocator, .{ .rule = .@"fn-length", .line = line, .message = try allocator.print("function {s} is {d} lines (limit 150)", .{ name, length }) }); + try findings.append(allocator, .{ + .rule = .@"fn-length", + .line = line, + .message = try allocator.print("function {s} is {d} lines (limit 150)", .{ name, length }), + }); } } if (create_line != null and !has_destroy) try findings.append(allocator, .{ @@ -264,11 +288,12 @@ fn deprecatedReplacement(allocator: std.mem.Allocator, source: [:0]const u8, pat } } const line = std.mem.count(u8, source[0..token.loc.start], "\n") + 1; - if (!replacement and !silenced(suppressions.items, .@"deprecated-names-replacement", line)) try findings.append(allocator, .{ - .rule = .@"deprecated-names-replacement", - .line = line, - .message = "Deprecated marker must name a backticked replacement", - }); + if (!replacement and !silenced(suppressions.items, .@"deprecated-names-replacement", line)) + try findings.append(allocator, .{ + .rule = .@"deprecated-names-replacement", + .line = line, + .message = "Deprecated marker must name a backticked replacement", + }); } return findings.toOwnedSlice(allocator); } @@ -535,14 +560,18 @@ test "SDK deprecated markers name a backticked replacement" { "const text = \"/// Deprecated\";", "/// DeprecatedThing is an identifier.\npub const old = 1;", "/// Foo\n/// Deprecated, see below\npub const old = 1;", - }) |source| try std.testing.expectEqual(@as(usize, 0), (try deprecatedReplacement(a, source, "sdk/src/old.zig")).len); + }) |source| try std.testing.expectEqual( + @as(usize, 0), + (try deprecatedReplacement(a, source, "sdk/src/old.zig")).len, + ); } test "deprecated marker honors lint-allow suppression and a file budget" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const a = arena.allocator(); - const suppressed = "// lint-allow(deprecated-names-replacement): removed with the next SDK\n/// Deprecated\npub const old = 1;"; + const suppressed = "// lint-allow(deprecated-names-replacement): removed with the next SDK\n" ++ + "/// Deprecated\npub const old = 1;"; try std.testing.expectEqual(@as(usize, 0), (try deprecatedReplacement(a, suppressed, "sdk/src/old.zig")).len); const inside_doc = "/// Deprecated // lint-allow(deprecated-names-replacement): not a comment\npub const old = 1;"; try std.testing.expectEqual(@as(usize, 1), (try deprecatedReplacement(a, inside_doc, "sdk/src/old.zig")).len); @@ -553,7 +582,10 @@ test "deprecated marker honors lint-allow suppression and a file budget" { for ([_][:0]const u8{ "// lint-allow(anyerror): wrong rule\n/// Deprecated\npub const old = 1;", "// lint-allow(deprecated-names-replacement): too far\n\n/// Deprecated\npub const old = 1;", - }) |source| try std.testing.expectEqual(@as(usize, 1), (try deprecatedReplacement(a, source, "sdk/src/old.zig")).len); + }) |source| try std.testing.expectEqual( + @as(usize, 1), + (try deprecatedReplacement(a, source, "sdk/src/old.zig")).len, + ); const hit = try deprecatedReplacement(a, "/// Deprecated\npub const old = 1;", "sdk/src/old.zig"); const allowances = [_]Allow{ diff --git a/scripts/tests_reached.zig b/scripts/tests_reached.zig index 936257f51..34017de5d 100644 --- a/scripts/tests_reached.zig +++ b/scripts/tests_reached.zig @@ -72,7 +72,11 @@ pub fn main(init: std.process.Init) !void { const name = testName(arena, line) orelse continue; file_tests += 1; if (reached(arena, binaries.items, abs, name)) continue; - if (missing == 0) std.debug.print("Tests no test binary compiles (none of `zig build test` / `test-integration` reaches the file):\n", .{}); + if (missing == 0) std.debug.print( + "Tests no test binary compiles " ++ + "(none of `zig build test` / `test-integration` reaches the file):\n", + .{}, + ); std.debug.print(" {s}: {s} \"{s}\"\n", .{ rel, name.kind, name.name }); missing += 1; } From acea9acedec6a9d494bd257d7365ad8325282cf4 Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 03:28:04 -0500 Subject: [PATCH 2/6] lint: line-length (codex) Agent-Team: linux Worker: codex --- scripts/lint.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/lint.zig b/scripts/lint.zig index 06e06fc5b..87549125d 100644 --- a/scripts/lint.zig +++ b/scripts/lint.zig @@ -745,14 +745,17 @@ test "changelog words report hits, honor line allows, and never fail the runner" "const s =\n \\\\// now fixed\n;", "// Unknown prefix and renewed storage.\nconst n = 1;", }) |source| try std.testing.expectEqual(@as(usize, 0), (try analyze(a, source)).len); - for ([_][]const u8{ "fixed", "NOW", "used to", "previously", "formerly", "no longer", "New:", "new:behavior" }) |word| { + for ([_][]const u8{ + "fixed", "NOW", "used to", "previously", "formerly", "no longer", "New:", "new:behavior", + }) |word| { const source = try a.printSentinel("//! {s} works.\n", .{word}, 0); try std.testing.expectEqual(@as(usize, 1), (try analyze(a, source)).len); } var output: std.Io.Writer.Allocating = .init(a); try std.testing.expect(!try reportFile(&output.writer, "hit.zig", hit, &.{}, &.{}, false)); try std.testing.expectEqualStrings( - "hit.zig:1: changelog-words: comment contains 'previously': Previously used a different buffer. (report-only)\n", + "hit.zig:1: changelog-words: comment contains 'previously': " ++ + "Previously used a different buffer. (report-only)\n", output.written(), ); } From bc3d8651f1132d94a7659d3b98cb83baad95468e Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 07:00:56 -0500 Subject: [PATCH 3/6] lint: line-length (codex) Agent-Team: linux Worker: codex --- build.zig | 99 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/build.zig b/build.zig index fa9ff2827..7af90062b 100644 --- a/build.zig +++ b/build.zig @@ -23,23 +23,55 @@ pub fn build(b: *std.Build) !void { run_lint.has_side_effects = true; b.step("lint", "Check Zig source against lint budgets").dependOn(&run_lint.step); - const windows_msvc_libc_opt = b.option([]const u8, "windows-msvc-libc", "zig libc manifest for *-windows-msvc when cross-compiling; forwarded by packageall for Windows children") orelse null; - const fetch_msvc_opt = b.option(bool, "fetch-msvc", "If *-windows-msvc libc is missing under .velopack-msvc/, run msvcup-setup first (downloads MSVC+SDK; requires network). Defaults to true on Windows hosts targeting *-windows-msvc.") orelse null; + const windows_msvc_libc_opt = b.option( + []const u8, + "windows-msvc-libc", + "zig libc manifest for *-windows-msvc when cross-compiling; forwarded by " ++ + "packageall for Windows children", + ) orelse null; + const fetch_msvc_opt = b.option( + bool, + "fetch-msvc", + "If *-windows-msvc libc is missing under .velopack-msvc/, run msvcup-setup " ++ + "first (downloads MSVC+SDK; requires network). Defaults to true on Windows " ++ + "hosts targeting *-windows-msvc.", + ) orelse null; // Options only, never the environment: Zig 0.17 caches the build's configuration without // regard to it, so a variable read here would be seen once and then ignored. // `scripts/release.sh` and `release.yml` turn the FIZZY_MACOS_* variables into these. - const macos_sign_app_identity = b.option([]const u8, "macos-sign-app", "macOS codesign identity for the app bundle (e.g. 'Developer ID Application: NAME (TEAMID)')"); - const macos_sign_install_identity = b.option([]const u8, "macos-sign-installer", "macOS codesign identity for the installer pkg (e.g. 'Developer ID Installer: NAME (TEAMID)')"); - const macos_notary_profile = b.option([]const u8, "macos-notary-profile", "notarytool keychain profile name (run `xcrun notarytool store-credentials ` first)"); - const macos_sdk = b.option([]const u8, "macos-sdk", "macOS SDK path for an explicit -Dtarget=*-macos (default: `xcrun --sdk macosx --show-sdk-path`)"); + const macos_sign_app_identity = b.option( + []const u8, + "macos-sign-app", + "macOS codesign identity for the app bundle (e.g. 'Developer ID " ++ + "Application: NAME (TEAMID)')", + ); + const macos_sign_install_identity = b.option( + []const u8, + "macos-sign-installer", + "macOS codesign identity for the installer pkg (e.g. 'Developer ID " ++ + "Installer: NAME (TEAMID)')", + ); + const macos_notary_profile = b.option( + []const u8, + "macos-notary-profile", + "notarytool keychain profile name (run `xcrun notarytool store-credentials " ++ + "` first)", + ); + const macos_sdk = b.option( + []const u8, + "macos-sdk", + "macOS SDK path for an explicit -Dtarget=*-macos (default: `xcrun --sdk " ++ + "macosx --show-sdk-path`)", + ); // Windows 10 1803 at least: AF_UNIX arrived there, and std offers it only to a target whose // minimum is that (`std.Io.net.has_unix_sockets`) — the control server's socket // (`app/control/Server.zig`). Every Windows still supported by Microsoft is newer. const target = target: { const asked = b.standardTargetOptions(.{}); - if (asked.result.os.tag != .windows or asked.result.os.isAtLeast(.windows, .win10_rs4) == true) break :target asked; + if (asked.result.os.tag != .windows or + asked.result.os.isAtLeast(.windows, .win10_rs4) == true) break :target asked; if (asked.result.os.version_range.windows.max.isAtLeast(.win10_rs4) != true) std.debug.panic("fizzy needs Windows 10 1803 (win10_rs4) or newer; -Dtarget asks for an older range", .{}); var query = asked.query; @@ -84,7 +116,13 @@ pub fn build(b: *std.Build) !void { // `defer-app` here and calls `buildApp` below with its plugin modules instead. const app = @import("build/app.zig"); const cfg = try app.readConfig(b, target, base); - if (b.option(bool, "defer-app", "Do not build the application here; the consumer calls `buildApp` with its own plugins") orelse false) { + const defer_app = b.option( + bool, + "defer-app", + "Do not build the application here; the consumer calls `buildApp` with its " ++ + "own plugins", + ) orelse false; + if (defer_app) { deferred = .{ .target = target, .optimize = optimize, .base = base, .cfg = cfg }; return; } @@ -126,7 +164,13 @@ pub const plugins = @import("build/plugins.zig").entries; /// try fizzy.buildApp(fizzy_dep, &.{ /// fizzy.plugins.workbench, /// fizzy.plugins.text, -/// .{ .name = "pixi", .module = b.dependency("pixi", .{ .target = target, .optimize = optimize }).module("plugin") }, +/// .{ +/// .name = "pixi", +/// .module = b.dependency("pixi", .{ +/// .target = target, +/// .optimize = optimize, +/// }).module("plugin"), +/// }, /// }); /// b.installArtifact(fizzy_dep.artifact("myapp")); /// ``` @@ -136,7 +180,10 @@ pub const plugins = @import("build/plugins.zig").entries; /// (its root's `plugin_id`) and `module` its static module, which the plugin package exports and /// which fizzy wires to `dvui`, `core`, `fizzy_sdk` and `icons`. pub fn buildApp(fizzy_dep: *std.Build.Dependency, linked: []const BundledPlugin) !void { - const d = deferred orelse @panic("fizzy.buildApp: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\", …) first"); + const d = deferred orelse @panic( + "fizzy.buildApp: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\", " ++ + "…) first", + ); var opts = d.base; // Until fizzyedit/example-app lists fizzy's plugins itself (its CI and fizzy's build each // other's main): a list naming none of fizzy's gets all of them ahead of its own, as before. @@ -144,7 +191,11 @@ pub fn buildApp(fizzy_dep: *std.Build.Dependency, linked: []const BundledPlugin) const names_fizzys = for (linked) |p| { if (p.module == null) break true; } else false; - opts.app_plugins = if (names_fizzys) linked else try std.mem.concat(fizzy_dep.builder.allocator, BundledPlugin, &.{ &plugins.all, linked }); + opts.app_plugins = if (names_fizzys) linked else try std.mem.concat( + fizzy_dep.builder.allocator, + BundledPlugin, + &.{ &plugins.all, linked }, + ); try @import("build/app.zig").construct(fizzy_dep.builder, d.target, d.optimize, opts, d.cfg); deferred.?.built = true; } @@ -173,10 +224,17 @@ pub fn buildApp(fizzy_dep: *std.Build.Dependency, linked: []const BundledPlugin) /// Windows MSVC ones reach fizzy only if the app declares `windows-msvc-libc` / `fetch-msvc` and /// passes them on in `b.dependency`. Without them, a `*-windows-msvc` run fetches MSVC itself. pub fn addPackageSteps(b: *std.Build, fizzy_dep: *std.Build.Dependency) !void { - const d = deferred orelse @panic("fizzy.addPackageSteps: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\", …) and call fizzy.buildApp first"); + const d = deferred orelse @panic( + "fizzy.addPackageSteps: pass `.@\"defer-app\" = true` to " ++ + "b.dependency(\"fizzy\", …) and call fizzy.buildApp first", + ); const names = [_][]const u8{ "package", "desktop", "packageall" }; for (names) |name| if (b.top_level_steps.contains(name)) { - std.log.err("fizzy.addPackageSteps: this build already has a `{s}` step; `package`, `desktop` and `packageall` are the names it adds", .{name}); + std.log.err( + "fizzy.addPackageSteps: this build already has a `{s}` step; `package`, " ++ + "`desktop` and `packageall` are the names it adds", + .{name}, + ); return error.PackageStepTaken; }; if (!d.built) @panic("fizzy.addPackageSteps: call fizzy.buildApp first"); @@ -207,7 +265,10 @@ pub const NativeBackend = @import("build/exe.zig").NativeBackend; /// /// ```zig /// const backend = @import("backend"); -/// const viewports = if (@hasDecl(backend, "viewports")) backend.viewports else @import("viewports_none"); +/// const viewports = if (@hasDecl(backend, "viewports")) +/// backend.viewports +/// else +/// @import("viewports_none"); /// ``` /// /// On fizzy's backend it also gets `platform` (the window's chrome and state), and on macOS the @@ -225,6 +286,14 @@ pub fn addDvui(fizzy_dep: *std.Build.Dependency, root_module: *std.Build.Module, root_module.addImport("viewports_none", @import("fizzy_backend").viewportsNoneModule(backend_dep, native.dvui)); if (backend == .fizzy) { root_module.addImport("platform", exe.platformModule(b, native, target, optimize, macos_sdl_paths)); - @import("fizzy_backend").addPlatformObjC(backend_dep, root_module, exe.backendOptions(target, optimize, macos_sdl_paths)); + @import("fizzy_backend").addPlatformObjC( + backend_dep, + root_module, + exe.backendOptions( + target, + optimize, + macos_sdl_paths, + ), + ); } } From 4bfabbf28cb81fa26d1b0e8f93e11b00acf523b5 Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 19:18:31 -0500 Subject: [PATCH 4/6] lint: line-length (codex) Agent-Team: linux Worker: codex --- build/common.zig | 15 ++++- build/exe.zig | 130 +++++++++++++++++++++++++++++++++------ build/package.zig | 22 +++++-- build/plugins.zig | 99 ++++++++++++++++++++++++----- build/rehome_fixture.zig | 17 +++-- build/sdk.zig | 19 ++++-- build/set_aside.zig | 6 +- build/velopack.zig | 22 +++++-- build/web.zig | 77 ++++++++++++++++++++--- 9 files changed, 342 insertions(+), 65 deletions(-) diff --git a/build/common.zig b/build/common.zig index e8012b344..953f3c4bc 100644 --- a/build/common.zig +++ b/build/common.zig @@ -25,7 +25,8 @@ pub fn installDirPath(dir: std.Build.InstallDir) std.Build.LazyPath { }; } -/// Installed artifacts go under `zig-out//…` so `packageall` and parallel targets never clobber each other. +/// Installed artifacts go under `zig-out//…` so `packageall` and parallel targets never +/// clobber each other. pub fn zigOutSubdirForTarget(b: *std.Build, rt: std.Build.ResolvedTarget) []const u8 { const arch_name: []const u8 = switch (rt.result.cpu.arch) { .x86_64 => "x86-64", @@ -82,7 +83,11 @@ fn resolveMacosSdkPath(b: *std.Build, explicit: ?[]const u8) ![]const u8 { } switch (run.term) { .exited => |code| if (code != 0) { - std.log.err("SDL on macOS: explicit -Dtarget=*-macos needs an SDK path. xcrun exited with code {d}. Install Xcode Command Line Tools or pass -Dmacos-sdk=.", .{code}); + std.log.err( + "SDL on macOS: explicit -Dtarget=*-macos needs an SDK path. xcrun exited with " ++ + "code {d}. Install Xcode Command Line Tools or pass -Dmacos-sdk=.", + .{code}, + ); return error.MacosSdkPath; }, else => { @@ -95,7 +100,11 @@ fn resolveMacosSdkPath(b: *std.Build, explicit: ?[]const u8) ![]const u8 { return b.dupePath(path); } -pub fn macosSdlPathsForExplicitTarget(b: *std.Build, target: std.Build.ResolvedTarget, macos_sdk: ?[]const u8) !?MacosSdlPaths { +pub fn macosSdlPathsForExplicitTarget( + b: *std.Build, + target: std.Build.ResolvedTarget, + macos_sdk: ?[]const u8, +) !?MacosSdlPaths { if (target.result.os.tag != .macos) return null; if (b.graph.host.result.os.tag != .macos) return null; if (target.query.isNative()) return null; diff --git a/build/exe.zig b/build/exe.zig index 1039e2f80..ca0f19ceb 100644 --- a/build/exe.zig +++ b/build/exe.zig @@ -110,7 +110,10 @@ pub fn nativeDvui( .library_path = p.lib, }) else - sdk.dvuiDependency(b, .{ .target = target, .optimize = optimize, .backend = .sdl3, .accesskit = accesskit }); + sdk.dvuiDependency( + b, + .{ .target = target, .optimize = optimize, .backend = .sdl3, .accesskit = accesskit }, + ); break :blk .{ .dep = dep, .dvui = dep.module("dvui_sdl3"), .backend = dep.module("sdl3") }; }, }; @@ -138,7 +141,11 @@ fn fizzyNativeDvui( .@"tree-sitter" = true, }); const dvui_mod = dep.module("dvui"); - const backend = fizzy_backend.backendModule(backendDependency(b), dvui_mod, backendOptions(target, optimize, macos_sdl_paths)); + const backend = fizzy_backend.backendModule( + backendDependency(b), + dvui_mod, + backendOptions(target, optimize, macos_sdl_paths), + ); return .{ .dep = dep, .dvui = dvui_mod, .backend = backend }; } @@ -147,11 +154,19 @@ pub fn backendDependency(b: *std.Build) *std.Build.Dependency { return b.dependency("fizzy_backend", .{}); } -pub fn backendOptions(target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, macos_sdl_paths: ?MacosSdlPaths) fizzy_backend.Options { +pub fn backendOptions( + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + macos_sdl_paths: ?MacosSdlPaths, +) fizzy_backend.Options { return .{ .target = target, .optimize = optimize, - .macos_sdk = if (macos_sdl_paths) |p| .{ .include = p.include, .framework = p.framework, .lib = p.lib } else null, + .macos_sdk = if (macos_sdl_paths) |p| .{ + .include = p.include, + .framework = p.framework, + .lib = p.lib, + } else null, }; } @@ -164,7 +179,12 @@ pub fn platformModule( optimize: std.lang.OptimizeMode, macos_sdl_paths: ?MacosSdlPaths, ) *std.Build.Module { - return fizzy_backend.platformModule(backendDependency(b), native.dvui, native.backend, backendOptions(target, optimize, macos_sdl_paths)); + return fizzy_backend.platformModule( + backendDependency(b), + native.dvui, + native.backend, + backendOptions(target, optimize, macos_sdl_paths), + ); } /// What every native executable of one target links and builds its plugins against: dvui on the @@ -189,7 +209,8 @@ pub fn nativeFramework( ) NativeFramework { const native = nativeDvui(b, native_backend, target, optimize, accesskit, macos_sdl_paths); const glass_look = fizzy_backend.glassLookModule(backendDependency(b)); - // Its in-app glass, the backend's (`glassModule`): `core` over the same dvui takes the same one. + // Its in-app glass, the backend's (`glassModule`): `core` over the same dvui takes the same + // one. const glass = fizzy_backend.glassModule(backendDependency(b), native.dvui); // Shared `core` module (gfx/math/fs/generated atlas/platform/paths/dvui hub + @@ -199,7 +220,16 @@ pub fn nativeFramework( .optimize = optimize, .root_source_file = b.path("core/core.zig"), }); - const icons = core_mod.addImports(b, core_module, native.dvui, b.dependency("fizzy_sdk", .{}).builder, target, optimize, glass_look, glass); + const icons = core_mod.addImports( + b, + core_module, + native.dvui, + b.dependency("fizzy_sdk", .{}).builder, + target, + optimize, + glass_look, + glass, + ); const proxy_bridge_host_mod = sdk.addProxyBridgeModule(b, target, optimize, native.dep, native.dvui); return .{ .native = native, @@ -281,7 +311,8 @@ pub fn addFizzyExecutableForTarget( .windows => { exe.subsystem = .windows; // MSVC's libcmt links `WinMainCRTStartup` (needs `WinMain`) for /SUBSYSTEM:WINDOWS. - // Fizzy exposes `main`, so force the C `main` entry which works for either subsystem. + // Fizzy exposes `main`, so force the C `main` entry which works for either + // subsystem. if (resolved_target.result.abi == .msvc) { exe.entry = .{ .symbol_name = "mainCRTStartup" }; } @@ -310,7 +341,16 @@ pub fn addFizzyExecutableForTarget( .optimize = optimize, .root_source_file = b.path("core/core.zig"), }); - _ = core_mod.addImports(b, core_proxy_module, dvui_proxy_mod, b.dependency("fizzy_sdk", .{}).builder, resolved_target, optimize, framework.glass_look, null); + _ = core_mod.addImports( + b, + core_proxy_module, + dvui_proxy_mod, + b.dependency("fizzy_sdk", .{}).builder, + resolved_target, + optimize, + framework.glass_look, + null, + ); // `macos_fsevents` is load-bearing for `FolderWatcher`: it watches a whole project folder, // and the kqueue fallback needs a file descriptor per directory *and* per file — exactly the @@ -326,7 +366,15 @@ pub fn addFizzyExecutableForTarget( const sdk_module = framework.sdk; exe.root_module.addImport("fizzy_sdk", sdk_module); - const sdk_proxy_module = sdk.wireSdkModule(b, resolved_target, optimize, dvui_proxy_mod, proxy_bridge_plugin_mod, core_proxy_module, null); + const sdk_proxy_module = sdk.wireSdkModule( + b, + resolved_target, + optimize, + dvui_proxy_mod, + proxy_bridge_plugin_mod, + core_proxy_module, + null, + ); // What this application links, as build data: a generated module whose `modules` tuple // names every statically linked plugin, so the runtime registers, probes and falls back // to whatever is listed here and never a plugin by name. An app built on fizzy lists its @@ -355,13 +403,38 @@ pub fn addFizzyExecutableForTarget( // The `app` framework module: the plugin store and what it needs. Fizzy is its first // consumer, not its owner — see `app/root.zig`. - const app_module = sdk.wireAppModule(b, resolved_target, optimize, dvui_mod, core_module, sdk_module, icons_module, markdown_module, if (nightwatch_dep) |dep| dep.module("nightwatch") else null, build_opts, singleton_app_dep.module("singleton_app"), exe.root_module); + const app_module = sdk.wireAppModule( + b, + resolved_target, + optimize, + dvui_mod, + core_module, + sdk_module, + icons_module, + markdown_module, + if (nightwatch_dep) |dep| dep.module("nightwatch") else null, + build_opts, + singleton_app_dep.module("singleton_app"), + exe.root_module, + ); app_module.addImport("bundled_plugins", bundled); - sdk.wireAppLayout(b, resolved_target, optimize, app_layout, dvui_mod, app_module, core_module, sdk_module, exe.root_module); + sdk.wireAppLayout( + b, + resolved_target, + optimize, + app_layout, + dvui_mod, + app_module, + core_module, + sdk_module, + exe.root_module, + ); var dylibs: std.ArrayList(Dylib) = .empty; - const workbench_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32) blk: { + const workbench_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and + resolved_target.result.cpu.arch != .wasm32) + blk: { break :blk workbench_plugin.addDylib(b, resolved_target, optimize, .{ .dvui = dvui_proxy_mod, .core = core_proxy_module, @@ -372,7 +445,9 @@ pub fn addFizzyExecutableForTarget( }, workbench_opts); } else null; - const text_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32 and plugins.linksFizzys(app_plugins, "text")) blk: { + const text_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32 and + plugins.linksFizzys(app_plugins, "text")) + blk: { break :blk text_plugin.addDylib(b, resolved_target, optimize, .{ .dvui = dvui_proxy_mod, .core = core_proxy_module, @@ -382,7 +457,10 @@ pub fn addFizzyExecutableForTarget( }); } else null; - const markdown_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32 and plugins.linksFizzys(app_plugins, "markdown")) blk: { + const markdown_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and + resolved_target.result.cpu.arch != .wasm32 and + plugins.linksFizzys(app_plugins, "markdown")) + blk: { break :blk markdown_plugin.addDylib(b, resolved_target, optimize, .{ .dvui = dvui_proxy_mod, .core = core_proxy_module, @@ -391,7 +469,9 @@ pub fn addFizzyExecutableForTarget( }); } else null; - const image_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32 and plugins.linksFizzys(app_plugins, "image")) blk: { + const image_dylib: ?*std.Build.Step.Compile = if (dynamic_plugins and resolved_target.result.cpu.arch != .wasm32 and + plugins.linksFizzys(app_plugins, "image")) + blk: { break :blk image_plugin.addDylib(b, resolved_target, optimize, .{ .dvui = dvui_proxy_mod, .core = core_proxy_module, @@ -419,10 +499,17 @@ pub fn addFizzyExecutableForTarget( } // zig-objc from the backend package's pin, and the platform's Objective-C, which calls back // into the platform's Zig and so is linked here, where the executable reaches it. - if (fizzy_backend.objcModule(backendDependency(b), backendOptions(resolved_target, optimize, macos_sdl_paths))) |objc| { + if (fizzy_backend.objcModule( + backendDependency(b), + backendOptions(resolved_target, optimize, macos_sdl_paths), + )) |objc| { exe.root_module.addImport("objc", objc); } - fizzy_backend.addPlatformObjC(backendDependency(b), exe.root_module, backendOptions(resolved_target, optimize, macos_sdl_paths)); + fizzy_backend.addPlatformObjC( + backendDependency(b), + exe.root_module, + backendOptions(resolved_target, optimize, macos_sdl_paths), + ); } else if (resolved_target.result.os.tag == .windows) { if (fizzy_backend.win32Module(backendDependency(b))) |win32| { exe.root_module.addImport("win32", win32); @@ -451,7 +538,12 @@ pub fn addFizzyExecutableForTarget( resolved_target.result.abi == .msvc; exe.root_module.link_libcpp = !exe_is_windows_msvc; if (velopack_enabled) if (vz) |v| { - try velopack.linkVelopack(b, v, exe, .{ .target = resolved_target, .optimize = optimize, .c_modules = &.{app_module} }); + try velopack.linkVelopack( + b, + v, + exe, + .{ .target = resolved_target, .optimize = optimize, .c_modules = &.{app_module} }, + ); }; return .{ diff --git a/build/package.zig b/build/package.zig index 4d264f985..c39247fe4 100644 --- a/build/package.zig +++ b/build/package.zig @@ -55,7 +55,9 @@ pub fn addSteps(opts: Options) *std.Build.Step { // installer, but the install hook never runs: Setup.exe hangs with "the // application install hook failed". Fail loudly instead of shipping that trap. const windows_non_msvc = target.result.os.tag == .windows and target.result.abi != .msvc; - const failure: ?*std.Build.Step = if (velopack_required_fail) |fail_step| fail_step else if (windows_non_msvc) &b.addFail( + const failure: ?*std.Build.Step = if (velopack_required_fail) |fail_step| + fail_step + else if (windows_non_msvc) &b.addFail( \\`zig build package` for Windows requires the MSVC ABI so Velopack is linked. \\The default native target resolves to x86_64-windows-gnu, which builds a binary \\WITHOUT the Velopack runtime. vpk would still wrap it as a Velopack installer, but @@ -190,7 +192,9 @@ pub fn addSteps(opts: Options) *std.Build.Step { // Without this, Apple's notary service rejects with "signature does not // include a secure timestamp" / "hardened runtime not enabled". vpk_pkg_sh.addArg("--signEntitlements"); - const entitlements_path = b.root.joinString(b.allocator, "assets/macos/Fizzy.entitlements") catch |e| std.debug.panic("entitlements path: {}", .{e}); + const entitlements_path = + b.root.joinString(b.allocator, "assets/macos/Fizzy.entitlements") catch |e| + std.debug.panic("entitlements path: {}", .{e}); vpk_pkg_sh.addArg(entitlements_path); } if (macos_sign_install_identity) |id| { @@ -257,7 +261,12 @@ pub fn addSteps(opts: Options) *std.Build.Step { /// fizzy's own (`build.zig`), or an app's built on fizzy (`fizzy.addPackageSteps`), whose /// `build.zig` passes fizzy its options again in each run. pub fn addPackageAllStep(b: *std.Build, no_emit: bool) void { - const packageall_step = b.step("packageall", "zig build package for each of the six release targets, with this build's -D options but the target's; -Dwindows-msvc-libc= and -Dfetch-msvc reach the *-windows-msvc runs only"); + const packageall_step = b.step( + "packageall", + "zig build package for each of the six release targets, with this build's -D " ++ + "options but the target's; -Dwindows-msvc-libc= and -Dfetch-msvc reach the " ++ + "*-windows-msvc runs only", + ); if (no_emit) { packageall_step.dependOn(&b.addFail("cannot run `packageall` with -Dno-emit").step); return; @@ -283,7 +292,8 @@ pub fn addPackageAllStep(b: *std.Build, no_emit: bool) void { switch (entry.value_ptr.*) { .flag => list.append(b.allocator, b.fmt("-D{s}", .{name})) catch @panic("OOM"), .scalar => |v| list.append(b.allocator, b.fmt("-D{s}={s}", .{ name, v })) catch @panic("OOM"), - .list => |l| for (l.items) |v| list.append(b.allocator, b.fmt("-D{s}={s}", .{ name, v })) catch @panic("OOM"), + .list => |l| for (l.items) |v| + list.append(b.allocator, b.fmt("-D{s}={s}", .{ name, v })) catch @panic("OOM"), // Only a `b.dependency` call passes these, never a command line. .map, .lazy_path, .lazy_path_list => {}, } @@ -311,7 +321,9 @@ pub fn addPackageAllStep(b: *std.Build, no_emit: bool) void { var prev_step: ?*std.Build.Step = null; for (packageall_triples) |triple| { - const zig_pkg_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "package", b.fmt("-Dtarget={s}", .{triple}) }); + const zig_pkg_run = b.addSystemCommand( + &.{ b.graph.zig_exe, "build", "package", b.fmt("-Dtarget={s}", .{triple}) }, + ); zig_pkg_run.addArgs(common.items); if (std.mem.endsWith(u8, triple, "-windows-msvc")) zig_pkg_run.addArgs(msvc_only.items); // This build's own build file, from the cwd this build was run in (inherited): a diff --git a/build/plugins.zig b/build/plugins.zig index d001fee6a..2d6c6d219 100644 --- a/build/plugins.zig +++ b/build/plugins.zig @@ -28,7 +28,15 @@ pub const entries = struct { pub const guides: BundledPlugin = .{ .name = "guides" }; /// What fizzy itself links, in its sidebar order. - pub const all = [_]BundledPlugin{ @This().workbench, @This().text, @This().image, @This().archive, @This().markdown, @This().devtools, @This().guides }; + pub const all = [_]BundledPlugin{ + @This().workbench, + @This().text, + @This().image, + @This().archive, + @This().markdown, + @This().devtools, + @This().guides, + }; }; /// Whether `plugins` links fizzy's own `name`, rather than leaving it out or bringing a module of @@ -69,7 +77,11 @@ pub const Linked = struct { /// re-homed onto it. workbench must be listed, because the editor still holds its state /// (fizzyedit/plans#13). pub fn link(b: *std.Build, w: Wiring, plugins: []const BundledPlugin) Linked { - if (!linksFizzys(plugins, "workbench")) std.debug.panic("fizzy: the plugin list must include `fizzy.plugins.workbench`; the editor still holds its state (fizzyedit/plans#13)", .{}); + if (!linksFizzys(plugins, "workbench")) std.debug.panic( + "fizzy: the plugin list must include `fizzy.plugins.workbench`; the editor " ++ + "still holds its state (fizzyedit/plans#13)", + .{}, + ); const workbench_mod = workbench.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, @@ -78,28 +90,69 @@ pub fn link(b: *std.Build, w: Wiring, plugins: []const BundledPlugin) Linked { .icons = w.icons, .backend = w.backend, }, w.workbench_opts, w.consumer); - const markdown_mod: ?*std.Build.Module = if (w.markdown) markdown.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, w.consumer) else null; + const markdown_mod: ?*std.Build.Module = if (w.markdown) markdown.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, + w.consumer, + ) else null; var graph: Rehome = .{ .b = b, .w = w }; defer graph.deinit(); var out: std.ArrayList(BundledPlugin) = .empty; for (plugins) |p| { - const m: ?*std.Build.Module = if (p.module) |src| graph.copy(p.name, src) else if (std.mem.eql(u8, p.name, "workbench")) + const m: ?*std.Build.Module = if (p.module) |src| + graph.copy(p.name, src) + else if (std.mem.eql(u8, p.name, "workbench")) workbench_mod else if (std.mem.eql(u8, p.name, "markdown")) markdown_mod else if (std.mem.eql(u8, p.name, "text")) - text.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk, .icons = w.icons }, w.consumer) + text.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk, .icons = w.icons }, + w.consumer, + ) else if (std.mem.eql(u8, p.name, "image")) - image.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk, .icons = w.icons }, w.consumer) + image.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk, .icons = w.icons }, + w.consumer, + ) else if (std.mem.eql(u8, p.name, "archive")) - archive.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, w.consumer) + archive.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, + w.consumer, + ) else if (std.mem.eql(u8, p.name, "devtools")) - devtools.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, w.consumer) + devtools.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, + w.consumer, + ) else if (std.mem.eql(u8, p.name, "guides")) - guides.addStaticModule(b, w.target, w.optimize, .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, w.consumer) + guides.addStaticModule( + b, + w.target, + w.optimize, + .{ .dvui = w.dvui, .core = w.core, .sdk = w.sdk }, + w.consumer, + ) else - std.debug.panic("fizzy: plugin '{s}' has no module and is not one of fizzy's own (`fizzy.plugins`)", .{p.name}); + std.debug.panic( + "fizzy: plugin '{s}' has no module and is not one of fizzy's own (`fizzy.plugins`)", + .{p.name}, + ); // A plugin this target does not build (markdown for the native exe on wasm) is left out. if (m) |module| { // Only an application's re-homed module is imported here, as `rehome` always did; @@ -165,7 +218,8 @@ const Rehome = struct { fn pinnedElsewhere(self: *const Rehome, m: *const std.Build.Module) bool { if (m.resolved_target) |t| { const mine = self.w.target.result; - if (t.result.cpu.arch != mine.cpu.arch or t.result.os.tag != mine.os.tag or t.result.abi != mine.abi) return true; + if (t.result.cpu.arch != mine.cpu.arch or + t.result.os.tag != mine.os.tag or t.result.abi != mine.abi) return true; } if (m.optimize) |o| if (o != self.w.optimize) return true; return false; @@ -220,7 +274,12 @@ const Rehome = struct { .root_source_file = src.root_source_file, .target = self.w.target, .optimize = self.w.optimize, - .link_libc = if (wasm) false else if (src == self.root) true else (src.link_libc orelse self.w.consumer.link_libc), + .link_libc = if (wasm) + false + else if (src == self.root) + true + else + (src.link_libc orelse self.w.consumer.link_libc), .link_libcpp = src.link_libcpp, .single_threaded = self.w.consumer.single_threaded, .strip = src.strip, @@ -243,11 +302,13 @@ const Rehome = struct { m.export_symbol_names = src.export_symbol_names; for (src.link_objects.items) |object| switch (object) { .c_source_file => |f| { - if (wasm and src.link_libc == true) std.debug.panic("fizzy: web module '{s}' has C sources requiring libc", .{name}); + if (wasm and src.link_libc == true) + std.debug.panic("fizzy: web module '{s}' has C sources requiring libc", .{name}); m.addCSourceFile(f.*); }, .c_source_files => |f| { - if (wasm and src.link_libc == true) std.debug.panic("fizzy: web module '{s}' has C sources requiring libc", .{name}); + if (wasm and src.link_libc == true) + std.debug.panic("fizzy: web module '{s}' has C sources requiring libc", .{name}); m.addCSourceFiles(.{ .root = f.root, .files = f.files, .flags = f.flags, .language = f.language }); }, .static_path => |p| m.addObjectFile(p), @@ -261,7 +322,11 @@ const Rehome = struct { }), .win32_resource_file => |f| m.addWin32ResourceFile(f.*), // A compile step is built for one target and cannot follow the module to another. - .other_step => std.debug.panic("fizzy: module '{s}' links a compile step, which cannot be re-homed to another target", .{name}), + .other_step => std.debug.panic( + "fizzy: module '{s}' links a compile step, which cannot be re-homed to another " ++ + "target", + .{name}, + ), }; for (src.include_dirs.items) |dir| switch (dir) { .path => |p| m.addIncludePath(p), @@ -301,7 +366,9 @@ const Rehome = struct { self.root = src; const m = self.copyAnalyzed(name, src); for (framework_names) |import_name| { - if (m.import_table.get(import_name) == null) if (self.framework(import_name)) |fw| m.addImport(import_name, fw); + if (m.import_table.get(import_name) == null) { + if (self.framework(import_name)) |fw| m.addImport(import_name, fw); + } } return m; } diff --git a/build/rehome_fixture.zig b/build/rehome_fixture.zig index 4ec996aab..4f63f8bb4 100644 --- a/build/rehome_fixture.zig +++ b/build/rehome_fixture.zig @@ -13,11 +13,16 @@ var chosen: ?Fault = null; fn fault(b: *std.Build) Fault { if (chosen) |f| return f; - chosen = b.option(Fault, "rehome-fixture-fault", "Break the rehome fixture on purpose (libc, cycle, plain); the build must fail") orelse .none; + chosen = b.option( + Fault, + "rehome-fixture-fault", + "Break the rehome fixture on purpose (libc, cycle, plain); the build must fail", + ) orelse .none; return chosen.?; } -/// root -> child (dvui, C sources, framework-free "plain" module, and a way back to root) and root -> same_child. +/// root -> child (dvui, C sources, framework-free "plain" module, and a way back to root) and root +/// -> same_child. pub fn graph(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode) *std.Build.Module { const old_dvui = sdk.dvuiDependency(b, .{ .target = target, @@ -57,7 +62,8 @@ fn expect(ok: bool, what: []const u8) void { } /// `source` is what `create` made, `copy` what `rehome` made of it. `same_target` is whether the -/// copy was made for the target the source is pinned to, so its framework-free module may be shared. +/// copy was made for the target the source is pinned to, so its framework-free module may be +/// shared. pub fn check(b: *std.Build, source: *std.Build.Module, copy: *std.Build.Module, same_target: bool) void { const f = fault(b); const source_child = source.import_table.get("child").?; @@ -67,5 +73,8 @@ pub fn check(b: *std.Build, source: *std.Build.Module, copy: *std.Build.Module, const back = copied_child.import_table.get("back").?; expect(if (f == .cycle) back == source else back == copy, "a cycle maps to the copy of its root"); const shared = copied_child.import_table.get("plain") == source_child.import_table.get("plain"); - expect(if (f == .plain) shared != same_target else shared == same_target, "a framework-free module is shared only where the target is the same"); + expect( + if (f == .plain) shared != same_target else shared == same_target, + "a framework-free module is shared only where the target is the same", + ); } diff --git a/build/sdk.zig b/build/sdk.zig index 04d528b03..40e333e70 100644 --- a/build/sdk.zig +++ b/build/sdk.zig @@ -9,7 +9,8 @@ const std = @import("std"); /// /// Worth the indirection because the two are not free to disagree. dvui types reachable from the /// plugin boundary feed `dylib.sdk_shape_fingerprint`, which both the app build and the plugin-SDK -/// build check against the single `recorded_sdk_shape_fingerprint` literal in `sdk/src/version.zig`. +/// build check against the single `recorded_sdk_shape_fingerprint` literal in +/// `sdk/src/version.zig`. /// When each build compiled a different dvui, they computed different fingerprints from that one /// literal and no value satisfied both — every fix broke the other side, and the error blamed /// `sdk_version`, which a bump cannot repair. One pin makes that state unreachable rather than @@ -118,7 +119,10 @@ pub fn wireAppModule( app_module.addImport("crash", crashModule(b, target, optimize)); // The remote-view protocol (`sdk/remote/`): std-only, so a host application's adapter links the // same files. - app_module.addImport("remote", b.createModule(.{ .target = target, .optimize = optimize, .root_source_file = b.path("sdk/remote/root.zig") })); + app_module.addImport( + "remote", + b.createModule(.{ .target = target, .optimize = optimize, .root_source_file = b.path("sdk/remote/root.zig") }), + ); if (consumer) |c| { c.addImport("app", app_module); // The bundled demos' scripts (`src/editor/demos/`) need only `tape`, so they build on the @@ -183,7 +187,10 @@ pub const BundledPlugin = struct { /// The entry as `platform`'s executables link it, or null if they do not. pub fn forPlatform(self: BundledPlugin, platform: Platform) ?BundledPlugin { const targets = self.targets orelse return self; - for (targets) |t| if (t.target == platform) return .{ .name = self.name, .module = t.module orelse self.module }; + for (targets) |t| if (t.target == platform) return .{ + .name = self.name, + .module = t.module orelse self.module, + }; return null; } }; @@ -213,7 +220,11 @@ pub fn bundledPluginsModule( plugins: []const BundledPlugin, ) *std.Build.Module { var src = std.ArrayList(u8).empty; - src.appendSlice(b.allocator, "//! Generated by the build: the plugins this application links in.\npub const modules = .{\n") catch @panic("OOM"); + src.appendSlice( + b.allocator, + "//! Generated by the build: the plugins this application links in.\npub const " ++ + "modules = .{\n", + ) catch @panic("OOM"); for (plugins) |p| { if (p.module == null) continue; src.appendSlice(b.allocator, " @import(\"") catch @panic("OOM"); diff --git a/build/set_aside.zig b/build/set_aside.zig index 3a43137c5..2e52b5a47 100644 --- a/build/set_aside.zig +++ b/build/set_aside.zig @@ -21,7 +21,11 @@ pub fn main(init: std.process.Init) !void { // Held: a running app. Renamed, the install's path is free. const aside = try arena.print("{s}.{d}.old", .{ path, std.Io.Clock.real.now(io).nanoseconds }); std.Io.Dir.rename(cwd, path, cwd, aside, io) catch |rename_err| { - std.log.warn("{s} is in use and could not be set aside ({t}); the install will fail until it quits", .{ path, rename_err }); + std.log.warn( + "{s} is in use and could not be set aside ({t}); the install will fail until it " ++ + "quits", + .{ path, rename_err }, + ); return; }; std.log.info("{s} is running: set aside as {s}", .{ path, std.fs.path.basename(aside) }); diff --git a/build/velopack.zig b/build/velopack.zig index 9d965d875..335fa1d54 100644 --- a/build/velopack.zig +++ b/build/velopack.zig @@ -79,7 +79,12 @@ pub fn addVpkRun(b: *std.Build, vz: Dep, target: std.Build.ResolvedTarget) !*std /// `Velopack.h` as a Zig module, through translate-c: Zig 0.17 removed `@cImport`. Imported as /// `velopack_c` by the modules `linkVelopack` is given. -fn velopackCModule(b: *std.Build, vz: Dep, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode) *std.Build.Module { +fn velopackCModule( + b: *std.Build, + vz: Dep, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, +) *std.Build.Module { const tc: Translator = .init(b.dependency("translate_c", .{}), .{ .c_source_file = vz.builder.dependency("velopack", .{}).path("include/Velopack.h"), .target = target, @@ -249,7 +254,10 @@ pub fn resolveWindowsMsvcLibc( return .{ .libc_path = null, .needs_setup = false }; if (opts.explicit_path) |p| { - const abs = if (std.fs.path.isAbsolute(p)) b.dupePath(p) else (b.root.joinString(b.allocator, p) catch @panic("OOM")); + const abs = if (std.fs.path.isAbsolute(p)) + b.dupePath(p) + else + (b.root.joinString(b.allocator, p) catch @panic("OOM")); b.dependOnFileContents(b.graph.cwdRelativePath(abs)); return .{ .libc_path = abs, .needs_setup = false }; } @@ -267,8 +275,14 @@ pub fn resolveWindowsMsvcLibc( break :blk true; }; - if (exists) return .{ .libc_path = (b.root.joinString(b.allocator, rel) catch @panic("OOM")), .needs_setup = false }; - if (opts.fetch_if_missing) return .{ .libc_path = (b.root.joinString(b.allocator, rel) catch @panic("OOM")), .needs_setup = true }; + if (exists) return .{ + .libc_path = (b.root.joinString(b.allocator, rel) catch @panic("OOM")), + .needs_setup = false, + }; + if (opts.fetch_if_missing) return .{ + .libc_path = (b.root.joinString(b.allocator, rel) catch @panic("OOM")), + .needs_setup = true, + }; return .{ .libc_path = null, .needs_setup = false }; } diff --git a/build/web.zig b/build/web.zig index 3163a0a5c..01ac9c1ef 100644 --- a/build/web.zig +++ b/build/web.zig @@ -73,7 +73,16 @@ pub fn framework(b: *std.Build, optimize: std.lang.OptimizeMode) Framework { .single_threaded = true, }); // What the page calls into (`web/web.js`): dvui's web exports. - web_backend.export_symbol_names = &.{ "dvui_init", "dvui_deinit", "dvui_update", "add_event", "arena_u8", "gpa_u8", "gpa_free", "new_font" }; + web_backend.export_symbol_names = &.{ + "dvui_init", + "dvui_deinit", + "dvui_update", + "add_event", + "arena_u8", + "gpa_u8", + "gpa_free", + "new_font", + }; web_backend.addImport("dvui", dvui_web); dvui_web.addImport("backend", web_backend); const dvui_web_proxy_bridge = sdk.addProxyBridgeModule(b, web_target, optimize, dvui_web_dep, dvui_web); @@ -86,7 +95,16 @@ pub fn framework(b: *std.Build, optimize: std.lang.OptimizeMode) Framework { .link_libc = false, .single_threaded = true, }); - const icons_web = core_mod.addImports(b, core_module_web, dvui_web, b.dependency("fizzy_sdk", .{}).builder, web_target, optimize, null, null); + const icons_web = core_mod.addImports( + b, + core_module_web, + dvui_web, + b.dependency("fizzy_sdk", .{}).builder, + web_target, + optimize, + null, + null, + ); return .{ .dvui_dep = dvui_web_dep, .dvui = dvui_web, @@ -135,7 +153,10 @@ pub fn build( web_exe.entry = .disabled; web_exe.root_module.addImport("dvui", dvui_web); // A page has one canvas: `backend_web.viewports`. - web_exe.root_module.addImport("viewports_none", @import("fizzy_backend").viewportsNoneModule(@import("exe.zig").backendDependency(b), dvui_web)); + web_exe.root_module.addImport( + "viewports_none", + @import("fizzy_backend").viewportsNoneModule(@import("exe.zig").backendDependency(b), dvui_web), + ); web_exe.root_module.addImport("web-backend", web_backend); // Extra wasm exports beyond dvui's own (`dvui_init`/`dvui_update`/etc.). The wasm @@ -253,7 +274,10 @@ pub fn build( // And the named dependencies, resolved directly for wasm. for (web_plugin_deps) |dep_name| { const dep = b.lazyDependency(dep_name, .{ .target = web_target, .optimize = optimize }) orelse continue; - bundled_list.append(b.allocator, .{ .name = dep_name, .module = plugins.rehome(b, wiring, dep_name, dep.module("plugin")) }) catch @panic("OOM"); + bundled_list.append( + b.allocator, + .{ .name = dep_name, .module = plugins.rehome(b, wiring, dep_name, dep.module("plugin")) }, + ) catch @panic("OOM"); } // A plugin may ship pages of its own beside the app (its `web/` directory → `plugins//`): // the far end of a popup round trip that is the plugin's, not fizzy's — a provider's @@ -301,9 +325,32 @@ pub fn build( // The `app` framework module (the plugin store). Wired exactly as the native build wires // it — one helper, so the two cannot drift. - const app_module_web = sdk.wireAppModule(b, web_target, optimize, dvui_web, core_module_web, sdk_module_web, icons_web, markdown_module_web, null, build_opts, null, web_exe.root_module); + const app_module_web = sdk.wireAppModule( + b, + web_target, + optimize, + dvui_web, + core_module_web, + sdk_module_web, + icons_web, + markdown_module_web, + null, + build_opts, + null, + web_exe.root_module, + ); app_module_web.addImport("bundled_plugins", bundled_web); - sdk.wireAppLayout(b, web_target, optimize, app_layout, dvui_web, app_module_web, core_module_web, sdk_module_web, web_exe.root_module); + sdk.wireAppLayout( + b, + web_target, + optimize, + app_layout, + dvui_web, + app_module_web, + core_module_web, + sdk_module_web, + web_exe.root_module, + ); // Cache-buster: stamps a 64-char hash into the index.html / web.js placeholders so // the browser picks up new wasm builds without manual hard-reloads. Re-implements @@ -355,7 +402,9 @@ pub fn build( const rehome_check: ?*std.Build.Step.Compile = if (own) blk: { const fixture = rehome_fixture.graph(b, b.resolveTargetQuery(.{}), optimize); var fixture_wiring = wiring; - fixture_wiring.consumer = b.createModule(.{ .target = web_target, .optimize = optimize, .link_libc = false, .single_threaded = true }); + fixture_wiring.consumer = b.createModule( + .{ .target = web_target, .optimize = optimize, .link_libc = false, .single_threaded = true }, + ); const module = plugins.rehome(b, fixture_wiring, "rehome_fixture", fixture); rehome_fixture.check(b, fixture, module, false); break :blk b.addObject(.{ .name = "rehome-fixture-web", .root_module = module }); @@ -433,14 +482,24 @@ pub fn install(b: *std.Build, web: Web) void { /// the browser's storage for it, so a test build served beside the real one — fizzyed.it/testapp/ /// beside /app/ — is built with a name of its own and keeps out of the real one's settings. fn stampStorage(b: *std.Build) std.Build.LazyPath { - const name = b.option([]const u8, "web-storage", "What the web app files its browser storage under (default \"fizzy\"); give a test build served beside the real one a name of its own") orelse "fizzy"; + const name = b.option( + []const u8, + "web-storage", + "What the web app files its browser storage under (default \"fizzy\"); give a " ++ + "test build served beside the real one a name of its own", + ) orelse "fizzy"; for (name) |c| switch (c) { 'a'...'z', '0'...'9', '-', '_' => {}, else => std.debug.panic("-Dweb-storage={s}: only a-z, 0-9, '-' and '_'", .{name}), }; const token = "__FIZZY_WEB_STORAGE__"; b.dependOnFileContents(b.path("web/index.html")); - const html = std.Io.Dir.cwd().readFileAlloc(b.graph.io, b.root.joinString(b.allocator, "web/index.html") catch @panic("OOM"), b.allocator, .unlimited) catch |err| + const html = std.Io.Dir.cwd().readFileAlloc( + b.graph.io, + b.root.joinString(b.allocator, "web/index.html") catch @panic("OOM"), + b.allocator, + .unlimited, + ) catch |err| std.debug.panic("web/index.html: {t}", .{err}); if (std.mem.find(u8, html, token) == null) std.debug.panic("web/index.html: no {s} to stamp", .{token}); const stamped = std.mem.replaceOwned(u8, b.allocator, html, token, name) catch @panic("OOM"); From 6dbe77af4d1ab0719cc0e605feab10a866d7f627 Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Sun, 25 Oct 2026 23:41:15 -0500 Subject: [PATCH 5/6] lint: line-length (codex) Agent-Team: linux Worker: codex --- build.zig | 45 ++++- build/app.zig | 480 +++++++++++++++++++++++++++++++++++++++-------- scripts/lint.zig | 5 +- 3 files changed, 446 insertions(+), 84 deletions(-) diff --git a/build.zig b/build.zig index 7d1d47f83..60b6ac9fc 100644 --- a/build.zig +++ b/build.zig @@ -169,7 +169,9 @@ pub const Platform = @import("build/sdk.zig").Platform; /// const hello = b.dependency("hello", .{}); /// try fizzy.buildApp(fizzy_dep, &.{ /// fizzy.plugins.workbench, -/// .{ .name = "hello", .module = @import("hello").staticModule(hello.builder, fizzy.framework(fizzy_dep, .native)) }, +/// .{ .name = "hello", .module = @import("hello").staticModule( +/// hello.builder, fizzy.framework(fizzy_dep, .native), +/// ) }, /// }); /// ``` pub fn framework(fizzy_dep: *std.Build.Dependency, platform: Platform) Framework { @@ -179,11 +181,25 @@ pub fn framework(fizzy_dep: *std.Build.Dependency, platform: Platform) Framework switch (platform) { .native => { const fw = d.frameworks.getNative(b, d.target, d.optimize, d.cfg); - return .{ .target = d.target, .optimize = d.optimize, .dvui = fw.native.dvui, .core = fw.core, .sdk = fw.sdk, .icons = fw.icons }; + return .{ + .target = d.target, + .optimize = d.optimize, + .dvui = fw.native.dvui, + .core = fw.core, + .sdk = fw.sdk, + .icons = fw.icons, + }; }, .web => { const fw = d.frameworks.getWeb(b, d.optimize); - return .{ .target = @import("build/web.zig").target(b), .optimize = d.optimize, .dvui = fw.dvui, .core = fw.core, .sdk = fw.sdk, .icons = fw.icons }; + return .{ + .target = @import("build/web.zig").target(b), + .optimize = d.optimize, + .dvui = fw.dvui, + .core = fw.core, + .sdk = fw.sdk, + .icons = fw.icons, + }; }, } } @@ -244,17 +260,29 @@ pub const App = struct { /// const app = try fizzy.addApp(fizzy_dep, &.{ /// fizzy.plugins.workbench, /// .{ .name = "hello", .targets = &.{ -/// .{ .target = .native, .module = hello.staticModule(hello_dep.builder, fizzy.framework(fizzy_dep, .native)) }, -/// .{ .target = .web, .module = hello.staticModule(hello_dep.builder, fizzy.framework(fizzy_dep, .web)) }, +/// .{ .target = .native, .module = hello.staticModule( +/// hello_dep.builder, fizzy.framework(fizzy_dep, .native), +/// ) }, +/// .{ .target = .web, .module = hello.staticModule( +/// hello_dep.builder, fizzy.framework(fizzy_dep, .web), +/// ) }, /// } }, -/// .{ .name = "shell", .module = shell_dep.module("plugin"), .targets = &.{.{ .target = .native }} }, +/// .{ .name = "shell", .module = shell_dep.module("plugin"), +/// .targets = &.{.{ .target = .native }} }, /// }); /// ``` pub fn addApp(fizzy_dep: *std.Build.Dependency, linked: []const BundledPlugin) !App { const d = deferred orelse @panic("fizzy.addApp: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\", …) first"); var opts = d.base; opts.app_plugins = try withFizzys(fizzy_dep.builder, linked); - const built = try @import("build/app.zig").construct(fizzy_dep.builder, d.target, d.optimize, opts, d.cfg, &deferred.?.frameworks); + const built = try @import("build/app.zig").construct( + fizzy_dep.builder, + d.target, + d.optimize, + opts, + d.cfg, + &deferred.?.frameworks, + ); deferred.?.built = true; return .{ .exe = built.native.main.exe, @@ -354,7 +382,8 @@ pub fn addWebSteps(b: *std.Build, fizzy_dep: *std.Build.Dependency) !void { std.log.err("fizzy.addWebSteps: this build already has a `web` step", .{}); return error.WebStepTaken; } - const d = deferred orelse @panic("fizzy.addWebSteps: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\", …) and call fizzy.buildApp first"); + const d = deferred orelse @panic("fizzy.addWebSteps: pass `.@\"defer-app\" = true` to b.dependency(\"fizzy\"," ++ + " …) and call fizzy.buildApp first"); if (!d.built) @panic("fizzy.addWebSteps: call fizzy.buildApp first"); b.step("web", "Build the web (wasm) app into zig-out/web/").dependOn(&b.addInstallDirectory(.{ .source_dir = fizzy_dep.namedLazyPath("web"), diff --git a/build/app.zig b/build/app.zig index bc774487a..1085e4c31 100644 --- a/build/app.zig +++ b/build/app.zig @@ -167,12 +167,36 @@ pub const Own = struct { /// and a plist vpk writes. `-Dapp-windows-rc` / `-Dapp-macos-plist` override either. fn readBranding(b: *std.Build, id: Identity, own: ?Own, renamed: bool) Branding { const LazyPath = std.Build.LazyPath; - const png_opt = b.option(LazyPath, "app-icon", "PNG icon: the window's, the infobar's and the Linux package's (default: fizzy's)"); - const ico_opt = b.option(LazyPath, "app-icon-ico", "Windows .ico: the installer's, the Start Menu shortcut's, and the generated resource script's (default: fizzy's)"); + const png_opt = b.option( + LazyPath, + "app-icon", + "PNG icon: the window's, the infobar's and the Linux package's (default: fizzy's)", + ); + const ico_opt = b.option( + LazyPath, + "app-icon-ico", + "Windows .ico: the installer's, the Start Menu shortcut's, and the generated" ++ + " resource script's (default: fizzy's)", + ); const icns_opt = b.option(LazyPath, "app-icon-icns", "macOS .icns: the bundle's icon (default: fizzy's)"); - const rc_opt = b.option(LazyPath, "app-windows-rc", "Windows resource script embedded in the exe (default: fizzy's for fizzy, else one generated from the icon, names and version)"); - const plist_opt = b.option(LazyPath, "app-macos-plist", "macOS Info.plist (default: fizzy's for fizzy, else one vpk writes from app-bundle-id)"); - const package_title = b.option([]const u8, "app-package-title", "The installers' name for the app: the macOS bundle, the Windows shortcut (default: app-name)") orelse id.name; + const rc_opt = b.option( + LazyPath, + "app-windows-rc", + "Windows resource script embedded in the exe (default: fizzy's for fizzy, " ++ + "else one generated from the icon, names and version)", + ); + const plist_opt = b.option( + LazyPath, + "app-macos-plist", + "macOS Info.plist (default: fizzy's for fizzy, else one vpk writes from " ++ + "app-bundle-id)", + ); + const package_title = b.option( + []const u8, + "app-package-title", + "The installers' name for the app: the macOS bundle, the Windows shortcut " ++ + "(default: app-name)", + ) orelse id.name; const own_set = if (renamed or png_opt != null or ico_opt != null or icns_opt != null) null else own; if (own_set) |o| return .{ .png = b.path(o.png), @@ -200,7 +224,11 @@ fn readBranding(b: *std.Build, id: Identity, own: ?Own, renamed: bool) Branding fn windowsRc(b: *std.Build, id: Identity, ico: std.Build.LazyPath) std.Build.LazyPath { // `v1.2.3-dev+5` → 1,2,3,0: up to four numeric parts, anything else 0. var parts = [4]u16{ 0, 0, 0, 0 }; - const core = std.mem.trimStart(u8, id.version[0 .. std.mem.findAny(u8, id.version, "-+") orelse id.version.len], "vV"); + const core = std.mem.trimStart( + u8, + id.version[0 .. std.mem.findAny(u8, id.version, "-+") orelse id.version.len], + "vV", + ); var it = std.mem.splitScalar(u8, core, '.'); for (&parts) |*part| part.* = std.fmt.parseInt(u16, it.next() orelse break, 10) catch 0; // An rc string literal holds no control characters (they are dropped), doubles its quotes @@ -297,7 +325,8 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options .fetch_if_missing = fetch_msvc, }); - // Only `-Dwindows-msvc-libc` or the managed `.velopack-msvc/` tree: Zig 0.17 has no global `--libc`. + // Only `-Dwindows-msvc-libc` or the managed `.velopack-msvc/` tree: Zig 0.17 has no global + // `--libc`. const effective_win_libc: ?[]const u8 = win_libc.libc_path; // Velopack in the dev/install exe is opt-in (`-Dvelopack=true`). Release @@ -309,12 +338,14 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options const velopack_enabled = b.option( bool, "velopack", - "Link Velopack runtime in the install/run exe (auto-update). Default: false. `package` still produces a Velopack-linked binary when supported.", + "Link Velopack runtime in the install/run exe (auto-update). Default: false." ++ + " `package` still produces a Velopack-linked binary when supported.", ) orelse false; if (velopack_enabled and !velopack_supported_for_target) { std.log.err( - "-Dvelopack=true is unsupported for target ABI {s}: Velopack on Windows requires -Dtarget=x86_64-windows-msvc or -Dtarget=aarch64-windows-msvc.", + "-Dvelopack=true is unsupported for target ABI {s}: Velopack on Windows " ++ + "requires -Dtarget=x86_64-windows-msvc or -Dtarget=aarch64-windows-msvc.", .{@tagName(target.result.abi)}, ); return error.WindowsMsvcAbiRequired; @@ -327,26 +358,35 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // with `-Dfetch-msvc=false` — in which case Zig falls back to system Visual Studio // auto-detection, which we can't validate here. const velopack_required_fail: ?*std.Build.Step = if (cross_win_msvc and effective_win_libc == null) - &b.addFail( - \\*-windows-msvc needs MSVC + Windows SDK headers/libs. - \\ One-shot install (macOS/Linux/Windows): zig build msvcup-setup - \\ Then: zig build package -Dtarget=x86_64-windows-msvc (auto-uses .velopack-msvc/zig-libc-x64.ini) - \\ Or auto-download in this build: add -Dfetch-msvc (default on Windows hosts; forwards through packageall) - \\ Or pass: --libc path.ini / -Dwindows-msvc-libc=path.ini - ).step + &b.addFail("*-windows-msvc needs MSVC + Windows SDK headers/libs.\n" ++ + " One-shot install (macOS/Linux/Windows): zig build msvcup-setup\n" ++ + " Then: zig build package -Dtarget=x86_64-windows-msvc (auto-uses .velopack-msvc/zig-libc-x64.ini)\n" ++ + " Or auto-download in this build: add -Dfetch-msvc (default on " ++ + "Windows hosts; forwards through packageall)\n" ++ + " Or pass: --libc path.ini / -Dwindows-msvc-libc=path.ini").step else null; const no_emit = b.option(bool, "no-emit", "Check for compile errors without emitting any code") orelse false; - const app_version_opt = b.option([]const u8, "app_version", "App version for vpk packVersion and startup log (default: fizzy's VERSION file for fizzy, else 0.0.0)"); + const app_version_opt = b.option( + []const u8, + "app_version", + "App version for vpk packVersion and startup log (default: fizzy's VERSION " ++ + "file for fizzy, else 0.0.0)", + ); // GitHub repo URL baked into the binary so Velopack's auto-update can find // the latest release via the GitHub Releases API. Override at build time // with `-Drepo-url=...` (e.g. when shipping a fork). At runtime, the env // var `FIZZY_AUTOUPDATE_URL` still overrides this for local feed testing. // An app built on fizzy has no feed unless it names one: fizzy's releases are not its updates. - const repo_url_opt = b.option([]const u8, "repo-url", "GitHub repo URL used by Velopack auto-update (default: fizzy's for fizzy, else none)"); + const repo_url_opt = b.option( + []const u8, + "repo-url", + "GitHub repo URL used by Velopack auto-update (default: fizzy's for fizzy, " ++ + "else none)", + ); const app_repo_url = repo_url_opt orelse if (opts.own) |own| own.repo_url else ""; // Comma-separated fallback repo URLs checked (in order) after `app_repo_url` @@ -354,7 +394,12 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // whose primary points at the new home and whose fallback points at the old // one (where the transitional release is published), then transfer the repo. // Empty by default (no fallback). - const app_repo_url_fallback = b.option([]const u8, "repo-url-fallback", "Comma-separated fallback GitHub repo URLs for Velopack auto-update, tried after -Drepo-url") orelse ""; + const app_repo_url_fallback = b.option( + []const u8, + "repo-url-fallback", + "Comma-separated fallback GitHub repo URLs for Velopack auto-update, tried " ++ + "after -Drepo-url", + ) orelse ""; var version_owned: ?[]u8 = null; // lives as long as the build process @@ -362,7 +407,12 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // package's, so its VERSION file is out of reach here), else 0.0.0. const app_version: []const u8 = if (app_version_opt) |v| v else if (opts.own) |own| blk: { b.dependOnFileContents(b.path(own.version_file)); - const raw = std.Io.Dir.cwd().readFileAlloc(b.graph.io, b.root.joinString(b.allocator, own.version_file) catch @panic("OOM"), b.allocator, std.Io.Limit.limited(256)) catch |e| std.debug.panic("read VERSION: {}", .{e}); + const raw = std.Io.Dir.cwd().readFileAlloc( + b.graph.io, + b.root.joinString(b.allocator, own.version_file) catch @panic("OOM"), + b.allocator, + std.Io.Limit.limited(256), + ) catch |e| std.debug.panic("read VERSION: {}", .{e}); version_owned = raw; break :blk std.mem.trimEnd(u8, raw, "\r\n"); } else "0.0.0"; @@ -372,16 +422,41 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // Application identity (see app/AppInfo.zig). Options rather than literals so an app built // on fizzy as a library can set them; fizzy passes its own values. - const app_name_opt = b.option([]const u8, "app-name", "Short lowercase app identifier (exe name, packId, config dir)"); + const app_name_opt = b.option( + []const u8, + "app-name", + "Short lowercase app identifier (exe name, packId, config dir)", + ); const app_name = app_name_opt orelse "fizzy"; const app_display_name = b.option([]const u8, "app-display-name", "Human-facing application name") orelse "Fizzy"; // An app that names no bundle id gets one of its own, not fizzy's: `dev.fizzy.`, // with anything a bundle id cannot hold made `-`. - const app_bundle_id = b.option([]const u8, "app-bundle-id", "Reverse-DNS application identifier (default: fizzy's for fizzy, else dev.fizzy.)") orelse - if (opts.own) |own| own.bundle_id else b.fmt("dev.fizzy.{s}", .{@import("bundle_id.zig").component(b.allocator, app_name)}); - const app_config_dir = b.option([]const u8, "app-config-dir", "Config directory name (defaults to app-name)") orelse app_name; - const app_registry_url = b.option([]const u8, "app-registry-url", "Plugin registry catalog URL; empty disables the store") orelse "https://plugins.fizzyed.it/catalog"; - const branding = readBranding(b, .{ .name = app_name, .display_name = app_display_name, .version = app_version }, opts.own, app_name_opt != null); + const app_bundle_id = b.option( + []const u8, + "app-bundle-id", + "Reverse-DNS application identifier (default: fizzy's for fizzy, else " ++ + "dev.fizzy.)", + ) orelse + if (opts.own) |own| own.bundle_id else b.fmt( + "dev.fizzy.{s}", + .{@import("bundle_id.zig").component(b.allocator, app_name)}, + ); + const app_config_dir = b.option( + []const u8, + "app-config-dir", + "Config directory name (defaults to app-name)", + ) orelse app_name; + const app_registry_url = b.option( + []const u8, + "app-registry-url", + "Plugin registry catalog URL; empty disables the store", + ) orelse "https://plugins.fizzyed.it/catalog"; + const branding = readBranding( + b, + .{ .name = app_name, .display_name = app_display_name, .version = app_version }, + opts.own, + app_name_opt != null, + ); build_opts.addOption([]const u8, "app_name", app_name); build_opts.addOption([]const u8, "app_display_name", app_display_name); build_opts.addOption([]const u8, "app_bundle_id", app_bundle_id); @@ -395,7 +470,12 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options const app_is_fizzy = opts.own != null; // Where Report a Bug goes. Not `repo-url` as such, which is the update feed and defaults to // fizzy's: an app reports to its own repo only when it named one (`issues_url.zig`). - const app_issues_url = b.option([]const u8, "app-issues-url", "Where Report a Bug goes; empty disables it (default: an explicit repo-url's issues, fizzy's for fizzy)") orelse + const app_issues_url = b.option( + []const u8, + "app-issues-url", + "Where Report a Bug goes; empty disables it (default: an explicit repo-url's" ++ + " issues, fizzy's for fizzy)", + ) orelse try @import("issues_url.zig").derive(b.allocator, repo_url_opt, app_is_fizzy); const app_repo_url_set = repo_url_opt != null and repo_url_opt.?.len > 0; build_opts.addOption(bool, "app_is_fizzy", app_is_fizzy); @@ -405,13 +485,22 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // Off, the app runs only the plugins it links (`buildApp`'s list): no plugin dylib is built, // and nothing loads at runtime — not fizzy's own dylibs, not the user plugins directory, not // the store, not a web page's `?plugin=`. Comptime, so none of it is checked per frame. - const dynamic_plugins = b.option(bool, "dynamic-plugins", "Load plugins at runtime: fizzy's own dylibs, the user plugins directory, the store (default: true)") orelse true; + const dynamic_plugins = b.option( + bool, + "dynamic-plugins", + "Load plugins at runtime: fizzy's own dylibs, the user plugins directory, " ++ + "the store (default: true)", + ) orelse true; build_opts.addOption(bool, "dynamic_plugins", dynamic_plugins); // A consumer that wants its own shape passes `-Dapp-layout=` (a LazyPath to // `pub fn layout(?*anyopaque, *Layout)`). Fizzy itself uses `src/editor/layout.zig`. // There is no `-Dlayout=` enum of shipped presets: the shapes are fizzyedit/example-app's. - const app_layout_path = b.option(std.Build.LazyPath, "app-layout", "App-owned layout file (pub fn layout(?*anyopaque, *Layout))"); + const app_layout_path = b.option( + std.Build.LazyPath, + "app-layout", + "App-owned layout file (pub fn layout(?*anyopaque, *Layout))", + ); build_opts.addOption(bool, "has_app_layout", app_layout_path != null); const static_workbench = b.option( bool, @@ -439,8 +528,15 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options const workbench_opts = b.addOptions(); workbench_opts.addOption(bool, "file_tree", workbench_file_tree); - const msvcup_before_compile: ?*std.Build.Step.Run = if (vz) |v| velopack.addMsvcupSetupStep(b, v, ".velopack-msvc") else null; - const msvcup_setup_step = b.step("msvcup-setup", "Download MSVC SDK into .velopack-msvc/ via velopack-zig (writes zig-libc-*.ini)"); + const msvcup_before_compile: ?*std.Build.Step.Run = if (vz) |v| velopack.addMsvcupSetupStep( + b, + v, + ".velopack-msvc", + ) else null; + const msvcup_setup_step = b.step( + "msvcup-setup", + "Download MSVC SDK into .velopack-msvc/ via velopack-zig (writes zig-libc-*.ini)", + ); if (msvcup_before_compile) |m| msvcup_setup_step.dependOn(&m.step); const accesskit = b.option(dvui.AccesskitOptions, "accesskit", "Enable accesskit") orelse .off; @@ -448,7 +544,8 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options const native_backend = b.option( fizzy_exe.NativeBackend, "native-backend", - "Native renderer: fizzy (fizzy's own SDL_GPU backend, custom programs) or sdl3 (dvui's SDL_Renderer backend). Default: fizzy", + "Native renderer: fizzy (fizzy's own SDL_GPU backend, custom programs) or " ++ + "sdl3 (dvui's SDL_Renderer backend). Default: fizzy", ) orelse fizzy_exe.defaultNativeBackend(target); const test_filters = b.option( @@ -459,8 +556,16 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // What an app's installers carry besides the executable and the plugin dylibs (a helper // program it starts, say), and what it tells vpk besides fizzy's own arguments. - const package_dirs = b.option([]const std.Build.LazyPath, "package-dirs", "Directories whose files `package` ships beside the executable") orelse &.{}; - const vpk_args = b.option([]const []const u8, "vpk-args", "Arguments `package` passes `vpk pack` after its own") orelse &.{}; + const package_dirs = b.option( + []const std.Build.LazyPath, + "package-dirs", + "Directories whose files `package` ships beside the executable", + ) orelse &.{}; + const vpk_args = b.option( + []const []const u8, + "vpk-args", + "Arguments `package` passes `vpk pack` after its own", + ) orelse &.{}; return .{ .vz = vz, .macos_sdl_paths = macos_sdl_paths, @@ -513,7 +618,14 @@ pub const Built = struct { /// Phase two of `build`: the executables, the web build, tests, packaging. `frameworks` holds any /// an app asked for first (`fizzy.framework`), and gets the rest. -pub fn construct(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, opts: Options, cfg: Config, frameworks: *Frameworks) !Built { +pub fn construct( + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + opts: Options, + cfg: Config, + frameworks: *Frameworks, +) !Built { const assetpack = @import("assetpack"); const assets_module = assetpack.pack(b, b.path("assets"), .{}); // The window's icon, apart from `assets` so an app built on fizzy can give its own. @@ -528,10 +640,33 @@ pub fn construct(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. , .{cfg.branding.pixel_art})), }); - // `zig build web` produces `zig-out/web/{web.wasm, web.js, index.html, NotoSansKR-Regular.ttf}`, + // `zig build web` produces `zig-out/web/{web.wasm, web.js, index.html, + // NotoSansKR-Regular.ttf}`, // deployable as-is to a static host. - const w = web.build(b, frameworks.getWeb(b, optimize), optimize, cfg.build_opts, cfg.workbench_opts, assets_module, app_icon_module, cfg.app_layout_path, try @import("sdk.zig").pluginsFor(b, opts.app_plugins, .web), opts.web_plugin_deps, opts.web_plugin_dirs, opts.own != null); - const built = try native(b, target, optimize, opts, cfg, frameworks.getNative(b, target, optimize, cfg), assets_module, app_icon_module); + const w = web.build( + b, + frameworks.getWeb(b, optimize), + optimize, + cfg.build_opts, + cfg.workbench_opts, + assets_module, + app_icon_module, + cfg.app_layout_path, + try @import("sdk.zig").pluginsFor(b, opts.app_plugins, .web), + opts.web_plugin_deps, + opts.web_plugin_dirs, + opts.own != null, + ); + const built = try native( + b, + target, + optimize, + opts, + cfg, + frameworks.getNative(b, target, optimize, cfg), + assets_module, + app_icon_module, + ); install(b, target, optimize, cfg, w, built); try addTests(b, target, optimize, cfg, built, assets_module, app_icon_module); return .{ .native = built, .web = w }; @@ -544,8 +679,21 @@ pub const Frameworks = struct { native: ?NativeFramework = null, web: ?web.Framework = null, - pub fn getNative(self: *Frameworks, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, cfg: Config) NativeFramework { - if (self.native == null) self.native = @import("exe.zig").nativeFramework(b, target, optimize, cfg.accesskit, cfg.native_backend, cfg.macos_sdl_paths); + pub fn getNative( + self: *Frameworks, + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + cfg: Config, + ) NativeFramework { + if (self.native == null) self.native = @import("exe.zig").nativeFramework( + b, + target, + optimize, + cfg.accesskit, + cfg.native_backend, + cfg.macos_sdl_paths, + ); return self.native.?; } @@ -562,7 +710,16 @@ pub const Native = struct { package: FizzyExecutable, }; -fn native(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, opts: Options, cfg: Config, framework: NativeFramework, assets_module: *std.Build.Module, app_icon_module: *std.Build.Module) !Native { +fn native( + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + opts: Options, + cfg: Config, + framework: NativeFramework, + assets_module: *std.Build.Module, + app_icon_module: *std.Build.Module, +) !Native { const fizzy_exe = @import("exe.zig"); const vz = cfg.vz; const macos_sdl_paths = cfg.macos_sdl_paths; @@ -586,7 +743,25 @@ fn native(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.Op const native_backend = cfg.native_backend; const app_plugins = try @import("sdk.zig").pluginsFor(b, opts.app_plugins, .native); - const main_fizzy = try fizzy_exe.addFizzyExecutableForTarget(b, vz, target, optimize, framework, native_backend, build_opts, workbench_opts, assets_module, app_icon_module, cfg.branding.rc, macos_sdl_paths, velopack_enabled, app_name, app_layout_path, app_plugins, dynamic_plugins); + const main_fizzy = try fizzy_exe.addFizzyExecutableForTarget( + b, + vz, + target, + optimize, + framework, + native_backend, + build_opts, + workbench_opts, + assets_module, + app_icon_module, + cfg.branding.rc, + macos_sdl_paths, + velopack_enabled, + app_name, + app_layout_path, + app_plugins, + dynamic_plugins, + ); const package_fizzy: FizzyExecutable = package_blk: { if (velopack_enabled) break :package_blk main_fizzy; @@ -612,14 +787,40 @@ fn native(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.Op pack_opts.addOption(bool, "static_image", static_image); pack_opts.addOption(bool, "dynamic_plugins", dynamic_plugins); pack_opts.addOption(bool, "has_app_layout", app_layout_path != null); - break :package_blk try fizzy_exe.addFizzyExecutableForTarget(b, vz, target, optimize, framework, native_backend, pack_opts, workbench_opts, assets_module, app_icon_module, cfg.branding.rc, macos_sdl_paths, true, app_name, app_layout_path, app_plugins, dynamic_plugins); + break :package_blk try fizzy_exe.addFizzyExecutableForTarget( + b, + vz, + target, + optimize, + framework, + native_backend, + pack_opts, + workbench_opts, + assets_module, + app_icon_module, + cfg.branding.rc, + macos_sdl_paths, + true, + app_name, + app_layout_path, + app_plugins, + dynamic_plugins, + ); }; return .{ .main = main_fizzy, .package = package_fizzy }; } -/// The steps over what `web.build` and `native` made: the installs, `run`, the dylib steps, packaging. -fn install(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, cfg: Config, w: web.Web, built: Native) void { +/// The steps over what `web.build` and `native` made: the installs, `run`, the dylib steps, +/// packaging. +fn install( + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + cfg: Config, + w: web.Web, + built: Native, +) void { const common = @import("common.zig"); const package = @import("package.zig"); const vz = cfg.vz; @@ -640,12 +841,19 @@ fn install(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.O const plugins_install_dir: std.Build.InstallDir = .{ .custom = b.fmt("{s}/plugins", .{zig_out_subdir}) }; if (no_emit) { b.getInstallStep().dependOn(&exe.step); - for (built.main.dylibs) |dylib| common.attachBuiltinPluginInstall(b, b.getInstallStep(), dylib.compile, dylib.id, plugins_install_dir); + for (built.main.dylibs) |dylib| common.attachBuiltinPluginInstall( + b, + b.getInstallStep(), + dylib.compile, + dylib.id, + plugins_install_dir, + ); } else { const install_artifact = b.addInstallArtifact(exe, .{ .dest_dir = .{ .override = zig_out_install_dir }, }); - // A running fizzy holds its executable on Windows: set it aside first, or the install fails. + // A running fizzy holds its executable on Windows: set it aside first, or the install + // fails. if (b.graph.host.result.os.tag == .windows and target.result.os.tag == .windows) { const aside_exe = b.addExecutable(.{ .name = "set-aside", @@ -681,7 +889,11 @@ fn install(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.O const install_dylib = plugin.installBuiltinPlugin(b, dylib.compile, dylib.id, plugins_install_dir); b.step( b.fmt("{s}-dylib", .{dylib.id}), - b.fmt("Build the {s} plugin as a dynamic library into zig-out//plugins/ (native only)", .{dylib.id}), + b.fmt( + "Build the {s} plugin as a dynamic library into zig-out//plugins/ " ++ + "(native only)", + .{dylib.id}, + ), ).dependOn(&install_dylib.step); } @@ -709,7 +921,15 @@ fn install(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.O } /// The unit and integration tests, the benchmarks, and the checks over them. -fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang.OptimizeMode, cfg: Config, built: Native, assets_module: *std.Build.Module, app_icon_module: *std.Build.Module) !void { +fn addTests( + b: *std.Build, + target: std.Build.ResolvedTarget, + optimize: std.lang.OptimizeMode, + cfg: Config, + built: Native, + assets_module: *std.Build.Module, + app_icon_module: *std.Build.Module, +) !void { const plugins = @import("plugins.zig"); const sdk = @import("sdk.zig"); const fizzy_exe = @import("exe.zig"); @@ -814,7 +1034,8 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // Profiles: taking `--profile` out of argv, and each profile's own lock name. std-only; // where a profile's folders go is `single_instance` and the editor's, run by hand. .{ "fizzy-profile-tests", "app/profile.zig" }, - // `FIZZY_QUIET`: read from the environment (the flag is `single_instance.resolveArgs`). std-only. + // `FIZZY_QUIET`: read from the environment (the flag is `single_instance.resolveArgs`). + // std-only. .{ "fizzy-quiet-tests", "app/quiet.zig" }, // `` scanning for the markdown preview's raw-HTML blocks. Under plugins/ // but std-only by design (see html_images.zig), so it tests from the app build. @@ -874,7 +1095,8 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // A state packed for a track file (zero runs, then deflate): lossless, so a canvas of // transparent pixels is not stored as tens of megabytes. std-only (see state_pack.zig). .{ "fizzy-state-pack-tests", "app/state_pack.zig" }, - // Image diff (RGBA8 to rects) and text diff (histogram lines, unified output). std-only (see + // Image diff (RGBA8 to rects) and text diff (histogram lines, unified output). std-only + // (see // core/diff.zig); `bench-diff` measures it. .{ "fizzy-diff-tests", "core/diff.zig" }, // When a document's transport shows and for how long, how far a held undo goes, which @@ -1100,7 +1322,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // steps so `zig build test` stays MSVC-free on Windows CI runners. Skipped // when cross-compiling to *-windows-msvc without an MSVC libc INI. // --------------------------------------------------------------- - const test_integration_step = b.step("test-integration", "Run fizzy headless integration tests (dvui-testing; needs MSVC on Windows)"); + const test_integration_step = b.step( + "test-integration", + "Run fizzy headless integration tests (dvui-testing; needs MSVC on Windows)", + ); const check_integration_step = b.step("check-integration", "Compile fizzy integration tests without running them"); const test_all_step = b.step("test-all", "Run unit + integration tests"); test_all_step.dependOn(test_step); @@ -1128,7 +1353,13 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. .backend = .testing, .accesskit = accesskit, }); - const dvui_test_proxy_bridge = sdk.addProxyBridgeModule(b, target, optimize, dvui_testing_dep, dvui_testing_dep.module("dvui_testing")); + const dvui_test_proxy_bridge = sdk.addProxyBridgeModule( + b, + target, + optimize, + dvui_testing_dep, + dvui_testing_dep.module("dvui_testing"), + ); // Build a module rooted at `src/fizzy.zig` carrying all the same // imports the production exe carries. Because fizzy.zig's transitive @@ -1144,7 +1375,13 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. fizzy_test_module.addImport("dvui", dvui_testing_dep.module("dvui_testing")); fizzy_test_module.addImport("backend", dvui_testing_dep.module("testing")); // The testing backend has no viewports (`backend_web.viewports`). - fizzy_test_module.addImport("viewports_none", @import("fizzy_backend").viewportsNoneModule(fizzy_exe.backendDependency(b), dvui_testing_dep.module("dvui_testing"))); + fizzy_test_module.addImport( + "viewports_none", + @import("fizzy_backend").viewportsNoneModule( + fizzy_exe.backendDependency(b), + dvui_testing_dep.module("dvui_testing"), + ), + ); fizzy_test_module.addImport("assets", assets_module); fizzy_test_module.addImport("app_icon", app_icon_module); fizzy_test_module.addImport("build_opts", sdk.buildOptsModule(build_opts)); @@ -1155,7 +1392,16 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. .optimize = optimize, .root_source_file = b.path("core/core.zig"), }); - const icons_test = core_mod.addImports(b, core_module_test, dvui_testing_dep.module("dvui_testing"), b.dependency("fizzy_sdk", .{}).builder, target, optimize, null, null); + const icons_test = core_mod.addImports( + b, + core_module_test, + dvui_testing_dep.module("dvui_testing"), + b.dependency("fizzy_sdk", .{}).builder, + target, + optimize, + null, + null, + ); fizzy_test_module.addImport("core", core_module_test); if (icons_test) |icons| fizzy_test_module.addImport("icons", icons); @@ -1208,7 +1454,15 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. fizzy_test_module.addImport("nightwatch", dep.module("nightwatch")); } - const sdk_module_test = sdk.wireSdkModule(b, target, optimize, dvui_testing_dep.module("dvui_testing"), dvui_test_proxy_bridge, core_module_test, fizzy_test_module); + const sdk_module_test = sdk.wireSdkModule( + b, + target, + optimize, + dvui_testing_dep.module("dvui_testing"), + dvui_test_proxy_bridge, + core_module_test, + fizzy_test_module, + ); if (cfg.app_is_fizzy) { const fixture = rehome_fixture.graph(b, target, optimize); const consumer = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true }); @@ -1251,7 +1505,20 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // The single-instance backend too, so its argv and profile handling are tested where the exe // is not built (`tests/integration.zig`, "profile"). const singleton_test_dep = b.dependency("dvui_singleton_app", .{ .target = target, .optimize = optimize }); - const app_module_test = sdk.wireAppModule(b, target, optimize, dvui_testing_dep.module("dvui_testing"), core_module_test, sdk_module_test, icons_test, markdown_module_test, if (nightwatch_test_dep) |dep| dep.module("nightwatch") else null, build_opts, singleton_test_dep.module("singleton_app"), fizzy_test_module); + const app_module_test = sdk.wireAppModule( + b, + target, + optimize, + dvui_testing_dep.module("dvui_testing"), + core_module_test, + sdk_module_test, + icons_test, + markdown_module_test, + if (nightwatch_test_dep) |dep| dep.module("nightwatch") else null, + build_opts, + singleton_test_dep.module("singleton_app"), + fizzy_test_module, + ); const image_module_test = image_plugin.addStaticModule(b, target, optimize, .{ .dvui = dvui_testing_dep.module("dvui_testing"), .core = core_module_test, @@ -1281,7 +1548,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. })); if (target.result.os.tag == .macos) { - if (@import("fizzy_backend").objcModule(fizzy_exe.backendDependency(b), fizzy_exe.backendOptions(target, optimize, macos_sdl_paths))) |objc| { + if (@import("fizzy_backend").objcModule( + fizzy_exe.backendDependency(b), + fizzy_exe.backendOptions(target, optimize, macos_sdl_paths), + )) |objc| { fizzy_test_module.addImport("objc", objc); } } else if (target.result.os.tag == .windows) { @@ -1328,12 +1598,19 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. integration_module.addImport("workbench", workbench_module_test); integration_module.addAnonymousImport("markdown_sample", .{ .root_source_file = b.path("docs/PLUGINS.md") }); // The synthetic document with the 48KB table of wrapping cells — the case table-row culling - // exists for, and the one it could get wrong. Generated by `markdown_sample_tables.py` beside it. - integration_module.addAnonymousImport("markdown_sample_tables", .{ .root_source_file = b.path("tests/data/markdown_sample_tables.md") }); + // exists for, and the one it could get wrong. Generated by `markdown_sample_tables.py` beside + // it. + integration_module.addAnonymousImport( + "markdown_sample_tables", + .{ .root_source_file = b.path("tests/data/markdown_sample_tables.md") }, + ); // The image-heavy fixture. Both docs above are prose and tables, so without this no test ever // laid out an image block — the one block kind whose height nothing in the source predicts // and which rescales with the pane right up until the pane is wider than the image. - integration_module.addAnonymousImport("markdown_sample_images", .{ .root_source_file = b.path("tests/data/markdown_sample_images.md") }); + integration_module.addAnonymousImport( + "markdown_sample_images", + .{ .root_source_file = b.path("tests/data/markdown_sample_images.md") }, + ); // A real tree-sitter grammar + queries, so the markdown code-fence highlighting path can be // executed rather than only compiled. The grammar itself is already linked into this binary // through the text module; the queries come from dvui's examples rather than a vendored copy, @@ -1349,7 +1626,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // The hand-written sample tape `docs/AUTOMATION.md` points at, so it cannot rot. integration_module.addAnonymousImport("demo_sample_tape", .{ .root_source_file = b.path("docs/demos/hello.zon") }); integration_module.addAnonymousImport("soak_tape", .{ .root_source_file = b.path("tests/tapes/soak.zon") }); - integration_module.addAnonymousImport("soak_expect", .{ .root_source_file = b.path("tests/tapes/soak.expect.zon") }); + integration_module.addAnonymousImport( + "soak_expect", + .{ .root_source_file = b.path("tests/tapes/soak.expect.zon") }, + ); const integration_tests = b.addTest(.{ .name = "fizzy-integration-tests", @@ -1365,7 +1645,12 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // off for the msvc ABI regardless of host (cross or native Windows). integration_tests.root_module.link_libcpp = !target_is_windows_msvc; if (velopack_enabled) if (vz) |v| { - try velopack.linkVelopack(b, v, integration_tests, .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }); + try velopack.linkVelopack( + b, + v, + integration_tests, + .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }, + ); }; test_integration_step.dependOn(&b.addRunArtifact(integration_tests).step); @@ -1393,7 +1678,12 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. if (target.result.os.tag == .windows) demo_tests.root_module.linkSystemLibrary("comctl32", .{}); demo_tests.root_module.link_libcpp = !target_is_windows_msvc; if (velopack_enabled) if (vz) |v| { - try velopack.linkVelopack(b, v, demo_tests, .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }); + try velopack.linkVelopack( + b, + v, + demo_tests, + .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }, + ); }; test_integration_step.dependOn(&b.addRunArtifact(demo_tests).step); check_integration_step.dependOn(&demo_tests.step); @@ -1418,7 +1708,12 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. if (target.result.os.tag == .windows) fuzz_tests.root_module.linkSystemLibrary("comctl32", .{}); fuzz_tests.root_module.link_libcpp = !target_is_windows_msvc; if (velopack_enabled) if (vz) |v| { - try velopack.linkVelopack(b, v, fuzz_tests, .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }); + try velopack.linkVelopack( + b, + v, + fuzz_tests, + .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }, + ); }; // Its output is the report, so a cached run must not hide it. const fuzz_run = b.addRunArtifact(fuzz_tests); @@ -1539,9 +1834,15 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // reasoning as `bench-text`'s samples. `PLUGINS.md` is the document that prompted the // benchmark. bench_module.addAnonymousImport("sample_huge", .{ .root_source_file = b.path("docs/PLUGINS.md") }); - bench_module.addAnonymousImport("sample_prose", .{ .root_source_file = b.path("tests/data/markdown_sample_tables.md") }); + bench_module.addAnonymousImport( + "sample_prose", + .{ .root_source_file = b.path("tests/data/markdown_sample_tables.md") }, + ); bench_module.addAnonymousImport("sample_medium", .{ .root_source_file = b.path("AGENTS.md") }); - bench_module.addAnonymousImport("sample_small", .{ .root_source_file = b.path("docs/MODULARIZATION_RELEASE_NOTES.md") }); + bench_module.addAnonymousImport( + "sample_small", + .{ .root_source_file = b.path("docs/MODULARIZATION_RELEASE_NOTES.md") }, + ); const bench_markdown = b.addTest(.{ .name = "fizzy-bench-markdown", .root_module = bench_module }); bench_markdown.root_module.link_libcpp = !target_is_windows_msvc; @@ -1549,7 +1850,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. bench_markdown.root_module.linkSystemLibrary("comctl32", .{}); } - const bench_step = b.step("bench-markdown", "Benchmark the markdown preview's per-frame draw cost (prints timings)"); + const bench_step = b.step( + "bench-markdown", + "Benchmark the markdown preview's per-frame draw cost (prints timings)", + ); const run_bench = b.addRunArtifact(bench_markdown); run_bench.has_side_effects = true; bench_step.dependOn(&run_bench.step); @@ -1575,13 +1879,21 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. bench_replay.root_module.linkSystemLibrary("comctl32", .{}); } if (velopack_enabled) if (vz) |v| { - try velopack.linkVelopack(b, v, bench_replay, .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }); + try velopack.linkVelopack( + b, + v, + bench_replay, + .{ .target = target, .optimize = optimize, .c_modules = &.{app_module_test} }, + ); }; const check_bench_replay_step = b.step("check-bench-replay", "Compile fizzy bench-replay without running it"); check_bench_replay_step.dependOn(&bench_replay.step); - const bench_step = b.step("bench-replay", "Benchmark a demo seek, silent against shown frame by frame (prints timings)"); + const bench_step = b.step( + "bench-replay", + "Benchmark a demo seek, silent against shown frame by frame (prints timings)", + ); const run_bench = b.addRunArtifact(bench_replay); run_bench.has_side_effects = true; bench_step.dependOn(&run_bench.step); @@ -1607,13 +1919,17 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. try velopack.linkVelopack(b, v, bench_tracks, .{ .target = target, .optimize = optimize }); }; - const bench_step = b.step("bench-tracks", "Benchmark a document's track: steps, checkpoints, replays (prints timings)"); + const bench_step = b.step( + "bench-tracks", + "Benchmark a document's track: steps, checkpoints, replays (prints timings)", + ); const run_bench = b.addRunArtifact(bench_tracks); run_bench.has_side_effects = true; bench_step.dependOn(&run_bench.step); } - // `zig build bench-diff` — core.diff on a 4K image, a 2048x2048 sprite of 50 layers and 1 MB of text (prints + // `zig build bench-diff` — core.diff on a 4K image, a 2048x2048 sprite of 50 layers and 1 MB of + // text (prints // timings). Same rules as `bench-tape`; std-only, so it needs no window. { const bench_module = b.createModule(.{ @@ -1628,7 +1944,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. })); const bench_diff = b.addTest(.{ .name = "fizzy-bench-diff", .root_module = bench_module }); - const bench_step = b.step("bench-diff", "Benchmark core.diff: a 4K image, a 50-layer sprite, 1 MB of text (prints timings)"); + const bench_step = b.step( + "bench-diff", + "Benchmark core.diff: a 4K image, a 50-layer sprite, 1 MB of text (prints timings)", + ); const run_bench = b.addRunArtifact(bench_diff); run_bench.has_side_effects = true; bench_step.dependOn(&run_bench.step); @@ -1650,7 +1969,10 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. })); const bench_tape = b.addTest(.{ .name = "fizzy-bench-tape", .root_module = bench_module }); - const bench_step = b.step("bench-tape", "Benchmark saving and loading demo tapes, ZON against binary (prints timings)"); + const bench_step = b.step( + "bench-tape", + "Benchmark saving and loading demo tapes, ZON against binary (prints timings)", + ); const run_bench = b.addRunArtifact(bench_tape); run_bench.has_side_effects = true; bench_step.dependOn(&run_bench.step); @@ -1665,7 +1987,15 @@ fn addTests(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.lang. // why Manifest.zig has its own root in the unit list above); when adding tests // to a new SDK file, check the reported test count actually went up. { - const sdk_tests_module = sdk.wireSdkModule(b, target, optimize, dvui_testing_dep.module("dvui_testing"), dvui_test_proxy_bridge, core_module_test, null); + const sdk_tests_module = sdk.wireSdkModule( + b, + target, + optimize, + dvui_testing_dep.module("dvui_testing"), + dvui_test_proxy_bridge, + core_module_test, + null, + ); const plugin_loader_module = b.createModule(.{ .target = target, .optimize = optimize, diff --git a/scripts/lint.zig b/scripts/lint.zig index da4b18c18..b37aa16c5 100644 --- a/scripts/lint.zig +++ b/scripts/lint.zig @@ -272,7 +272,10 @@ fn rawTransientSurfaces( try findings.append(allocator, .{ .rule = .@"raw-transient-surface", .line = line, - .message = try allocator.print("dvui.{s} paints its own surface; use the core.widgets / core.dialogs wrapper", .{name}), + .message = try allocator.print( + "dvui.{s} paints its own surface; use the core.widgets / core.dialogs wrapper", + .{name}, + ), }); break; } From 50dfc9c1e87f157fb2ee90c4b1bb447e8bc3b5fd Mon Sep 17 00:00:00 2001 From: "fizzy-linux[bot]" <346940526+fizzy-linux[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 01:01:07 -0500 Subject: [PATCH 6/6] lint: keep the multiline string literal in build/app.zig Agent-Team: linux Worker: claude --- build/app.zig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/build/app.zig b/build/app.zig index 1085e4c31..814a182ab 100644 --- a/build/app.zig +++ b/build/app.zig @@ -358,12 +358,13 @@ pub fn readConfig(b: *std.Build, target: std.Build.ResolvedTarget, opts: Options // with `-Dfetch-msvc=false` — in which case Zig falls back to system Visual Studio // auto-detection, which we can't validate here. const velopack_required_fail: ?*std.Build.Step = if (cross_win_msvc and effective_win_libc == null) - &b.addFail("*-windows-msvc needs MSVC + Windows SDK headers/libs.\n" ++ - " One-shot install (macOS/Linux/Windows): zig build msvcup-setup\n" ++ - " Then: zig build package -Dtarget=x86_64-windows-msvc (auto-uses .velopack-msvc/zig-libc-x64.ini)\n" ++ - " Or auto-download in this build: add -Dfetch-msvc (default on " ++ - "Windows hosts; forwards through packageall)\n" ++ - " Or pass: --libc path.ini / -Dwindows-msvc-libc=path.ini").step + &b.addFail( + \\*-windows-msvc needs MSVC + Windows SDK headers/libs. + \\ One-shot install (macOS/Linux/Windows): zig build msvcup-setup + \\ Then: zig build package -Dtarget=x86_64-windows-msvc (auto-uses .velopack-msvc/zig-libc-x64.ini) + \\ Or auto-download in this build: add -Dfetch-msvc (default on Windows hosts; forwards through packageall) + \\ Or pass: --libc path.ini / -Dwindows-msvc-libc=path.ini + ).step else null;