diff --git a/build.zig b/build.zig index 47016d552..7d1d47f83 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; } @@ -164,7 +202,13 @@ pub fn framework(fizzy_dep: *std.Build.Dependency, platform: Platform) Framework /// 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")); /// ``` @@ -266,10 +310,17 @@ fn withFizzys(b: *std.Build, linked: []const BundledPlugin) ![]const BundledPlug /// 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"); @@ -322,7 +373,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 @@ -340,6 +394,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, + ), + ); } } 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");