diff --git a/AGENTS.md b/AGENTS.md index dc0d5375f..4b9231d66 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -62,9 +62,13 @@ Full contract: **[`docs/PLUGINS.md`](docs/PLUGINS.md)**. Living reshape plan: ** Which plugins an executable links in is build data: `build/sdk.zig`'s `bundledPluginsModule` generates `bundled_plugins` (`pub const modules = .{ @import("workbench"), … }`) and the -runtime iterates it — nothing in `app/` or `src/` names a plugin except the workbench (its -state still lives on the Editor). An app built on fizzy adds its own with `defer-app` + -`fizzy.buildApp(fizzy_dep, &.{ .{ .name, .module = dep.module("plugin") } })`; see +runtime iterates it. Nothing in `app/` or `src/` registers a plugin by name, though two are +imported as libraries and so always built: workbench (its state still lives on the Editor, so +every list must include it) and markdown (the store draws READMEs with it). An app built on +fizzy lists every plugin it links with `defer-app` + `fizzy.buildApp(fizzy_dep, &.{ +fizzy.plugins.workbench, fizzy.plugins.text, .{ .name, .module = dep.module("plugin") } })`: +fizzy's own are entries with no module, built for each executable (`build/plugins.zig`'s +`link`), and only those listed register or get a dylib. See [`fizzyedit/example-app`](https://github.com/fizzyedit/example-app), which bundles `fizzyedit/example-plugin`. diff --git a/build.zig b/build.zig index d030c88be..12df859fc 100644 --- a/build.zig +++ b/build.zig @@ -63,6 +63,12 @@ var deferred: ?struct { pub const BundledPlugin = @import("build/sdk.zig").BundledPlugin; +/// Fizzy's own plugins, as entries in the list `buildApp` links: `fizzy.plugins.text`, or +/// `fizzy.plugins.all` for every one in fizzy's own order. Fizzy builds each for every executable. +/// `workbench` must be listed for now, because the editor still holds its state +/// (fizzyedit/plans#13). +pub const plugins = @import("build/plugins.zig").entries; + /// Build the application in a consumer's graph, with the plugins the consumer bundles. /// /// ```zig @@ -75,18 +81,27 @@ pub const BundledPlugin = @import("build/sdk.zig").BundledPlugin; /// .@"app-layout" = b.path("src/layout.zig"), /// }); /// try fizzy.buildApp(fizzy_dep, &.{ +/// fizzy.plugins.workbench, +/// fizzy.plugins.text, /// .{ .name = "pixi", .module = b.dependency("pixi", .{ .target = target, .optimize = optimize }).module("plugin") }, /// }); /// b.installArtifact(fizzy_dep.artifact("myapp")); /// ``` /// -/// `name` is the plugin's id (its root's `plugin_id`); `module` its static module, which the -/// plugin package exports and which fizzy wires to `dvui`, `core`, `fizzy_sdk` and `icons`. -/// Fizzy's own four are always bundled ahead of these. -pub fn buildApp(fizzy_dep: *std.Build.Dependency, plugins: []const BundledPlugin) !void { +/// `linked` is everything the app links, in registration order (the order of the sidebar's +/// views): fizzy's own (`fizzy.plugins`) and the app's. For an app's, `name` is the plugin's id +/// (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"); var opts = d.base; - opts.app_plugins = plugins; + // 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. + // Goes in fizzyedit/plans#13 step 2. + 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 }); try @import("build/app.zig").construct(fizzy_dep.builder, d.target, d.optimize, opts, d.cfg); } diff --git a/build/app.zig b/build/app.zig index 037a0eb87..b3e4c9c17 100644 --- a/build/app.zig +++ b/build/app.zig @@ -27,8 +27,8 @@ pub const WebPluginDir = struct { }; pub const Options = struct { - /// Plugins the application bundles beyond fizzy's own — see `build.zig`'s `buildApp`. - app_plugins: []const @import("sdk.zig").BundledPlugin = &.{}, + /// Every plugin the application links, fizzy's own among them — see `build.zig`'s `buildApp`. + app_plugins: []const @import("sdk.zig").BundledPlugin = &@import("plugins.zig").entries.all, /// Dependencies (by the name in `build.zig.zon`) whose `"plugin"` module the **web** build /// links in. The browser cannot `dlopen`, so a plugin exists there only if the application /// bundles it; this is fizzy-the-app's list, resolved for the wasm target. Each is looked diff --git a/build/exe.zig b/build/exe.zig index 82a1685d5..4db12a42d 100644 --- a/build/exe.zig +++ b/build/exe.zig @@ -15,8 +15,6 @@ const workbench_plugin = plugins.workbench; const text_plugin = plugins.text; const markdown_plugin = plugins.markdown; const image_plugin = plugins.image; -const archive_plugin = plugins.archive; -const devtools_plugin = plugins.devtools; const MacosSdlPaths = common.MacosSdlPaths; /// Install stripped exe + built-in plugin dylibs for `vpk pack --packDir`. @@ -201,9 +199,10 @@ pub fn addFizzyExecutableForTarget( /// `Host.layout_ctx`. The file imports `dvui`, `app`, `core`, and `fizzy_sdk` — not /// `fizzy` / `Editor` — so the module graph does not cycle. app_layout: ?std.Build.LazyPath, - /// Plugins the application bundles beyond fizzy's own four: each a static module from a - /// plugin package (`plugin_dep.module("plugin")`), linked in and listed in the generated - /// `bundled_plugins` module under its plugin id. + /// Every plugin the application links, in registration order: fizzy's own + /// (`fizzy.plugins`, built here) and the application's, each a static module from a plugin + /// package (`plugin_dep.module("plugin")`). Listed in the generated `bundled_plugins` module + /// under its plugin id. app_plugins: []const sdk.BundledPlugin, ) !FizzyExecutable { const native = nativeDvui(b, native_backend, resolved_target, optimize, accesskit, macos_sdl_paths); @@ -292,86 +291,24 @@ pub fn addFizzyExecutableForTarget( const sdk_module = sdk.wireSdkModule(b, resolved_target, optimize, dvui_mod, proxy_bridge_host_mod, core_module, exe.root_module); const sdk_proxy_module = sdk.wireSdkModule(b, resolved_target, optimize, dvui_proxy_mod, proxy_bridge_plugin_mod, core_proxy_module, null); - const workbench_module = workbench_plugin.addStaticModule(b, resolved_target, optimize, .{ + // 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 + // own (`buildApp`), fizzy's among them or not. + const linked = plugins.link(b, .{ + .target = resolved_target, + .optimize = optimize, .dvui = dvui_mod, .core = core_module, .sdk = sdk_module, .icons = icons_module, .backend = native.backend, - }, workbench_opts, exe.root_module); - const text_module = text_plugin.addStaticModule(b, resolved_target, optimize, .{ - .dvui = dvui_mod, - .core = core_module, - .sdk = sdk_module, - .icons = icons_module, - }, exe.root_module); - const image_module = image_plugin.addStaticModule(b, resolved_target, optimize, .{ - .dvui = dvui_mod, - .core = core_module, - .sdk = sdk_module, - }, exe.root_module); - const archive_module = archive_plugin.addStaticModule(b, resolved_target, optimize, .{ - .dvui = dvui_mod, - .core = core_module, - .sdk = sdk_module, - }, exe.root_module); - const devtools_module = devtools_plugin.addStaticModule(b, resolved_target, optimize, .{ - .dvui = dvui_mod, - .core = core_module, - .sdk = sdk_module, - }, exe.root_module); - const markdown_module: ?*std.Build.Module = if (resolved_target.result.cpu.arch != .wasm32) - markdown_plugin.addStaticModule(b, resolved_target, optimize, .{ - .dvui = dvui_mod, - .core = core_module, - .sdk = sdk_module, - }, exe.root_module) - else - null; - - // What this application bundles, 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 - // own. - var bundled_list: std.ArrayList(sdk.BundledPlugin) = .empty; - try bundled_list.appendSlice(b.allocator, &.{ - .{ .name = "workbench", .module = workbench_module }, - .{ .name = "text", .module = text_module }, - .{ .name = "image", .module = image_module }, - .{ .name = "archive", .module = archive_module }, - .{ .name = "markdown", .module = markdown_module }, - .{ .name = "devtools", .module = devtools_module }, - }); - for (app_plugins) |p| { - const src_mod = p.module orelse { - try bundled_list.append(b.allocator, p); - continue; - }; - // A copy per executable, not the plugin package's module itself: this function builds - // more than one exe (the packaged, Velopack-linked one beside the plain one), each with - // its own `dvui`/`core`/`fizzy_sdk`, and one module cannot import both sets. The copy - // keeps the plugin's own imports — its manifest options, its dependencies — and gets - // this exe's framework modules. - const m = b.createModule(.{ - .target = resolved_target, - .optimize = optimize, - .root_source_file = src_mod.root_source_file, - .link_libc = resolved_target.result.cpu.arch != .wasm32, - }); - var it = src_mod.import_table.iterator(); - while (it.next()) |kv| { - const name = kv.key_ptr.*; - if (std.mem.eql(u8, name, "dvui") or std.mem.eql(u8, name, "core") or std.mem.eql(u8, name, "fizzy_sdk") or std.mem.eql(u8, name, "icons")) continue; - m.addImport(name, kv.value_ptr.*); - } - m.addImport("dvui", dvui_mod); - m.addImport("core", core_module); - m.addImport("fizzy_sdk", sdk_module); - if (icons_module) |icons| m.addImport("icons", icons); - exe.root_module.addImport(p.name, m); - try bundled_list.append(b.allocator, .{ .name = p.name, .module = m }); - } - const bundled = sdk.bundledPluginsModule(b, resolved_target, optimize, bundled_list.items); + .workbench_opts = workbench_opts, + .consumer = exe.root_module, + .markdown = resolved_target.result.cpu.arch != .wasm32, + }, app_plugins); + const markdown_module = linked.markdown; + const bundled = sdk.bundledPluginsModule(b, resolved_target, optimize, linked.plugins); exe.root_module.addImport("bundled_plugins", bundled); const singleton_app_dep = b.dependency("dvui_singleton_app", .{ @@ -415,7 +352,7 @@ pub fn addFizzyExecutableForTarget( }, workbench_opts); } else null; - const text_dylib: ?*std.Build.Step.Compile = if (resolved_target.result.cpu.arch != .wasm32) blk: { + const text_dylib: ?*std.Build.Step.Compile = if (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, @@ -425,7 +362,7 @@ pub fn addFizzyExecutableForTarget( }); } else null; - const markdown_dylib: ?*std.Build.Step.Compile = if (resolved_target.result.cpu.arch != .wasm32) blk: { + const markdown_dylib: ?*std.Build.Step.Compile = if (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, @@ -434,7 +371,7 @@ pub fn addFizzyExecutableForTarget( }); } else null; - const image_dylib: ?*std.Build.Step.Compile = if (resolved_target.result.cpu.arch != .wasm32) blk: { + const image_dylib: ?*std.Build.Step.Compile = if (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, diff --git a/build/plugins.zig b/build/plugins.zig index 63ed36916..3ef9033f2 100644 --- a/build/plugins.zig +++ b/build/plugins.zig @@ -3,10 +3,127 @@ //! Each built-in plugin keeps its fizzy-internal static-embed glue self-contained in //! `plugins//static/integration.zig`, separate from the canonical third-party files //! at the plugin-folder root (fizzy's `@import("")` resolves to the root -//! `.zig`). Fizzy root aggregates those integration files here. +//! `.zig`). Fizzy root aggregates those integration files here, and `link` turns the list +//! an application gives into modules for one executable. +const std = @import("std"); +const BundledPlugin = @import("sdk.zig").BundledPlugin; + pub const workbench = @import("../plugins/workbench/static/integration.zig"); pub const text = @import("../plugins/text/static/integration.zig"); pub const markdown = @import("../plugins/markdown/static/integration.zig"); pub const image = @import("../plugins/image/static/integration.zig"); pub const archive = @import("../plugins/archive/static/integration.zig"); pub const devtools = @import("../plugins/devtools/static/integration.zig"); + +/// Fizzy's own plugins, as entries in the list an application links (`fizzy.plugins`). An entry +/// with no module is built by fizzy for each executable, wired to that executable's framework. +pub const entries = struct { + pub const workbench: BundledPlugin = .{ .name = "workbench" }; + pub const text: BundledPlugin = .{ .name = "text" }; + pub const image: BundledPlugin = .{ .name = "image" }; + pub const archive: BundledPlugin = .{ .name = "archive" }; + pub const markdown: BundledPlugin = .{ .name = "markdown" }; + pub const devtools: BundledPlugin = .{ .name = "devtools" }; + + /// What fizzy itself links, in its sidebar order. + pub const all = [_]BundledPlugin{ @This().workbench, @This().text, @This().image, @This().archive, @This().markdown, @This().devtools }; +}; + +/// Whether `plugins` links fizzy's own `name`, rather than leaving it out or bringing a module of +/// its own under that id. +pub fn linksFizzys(plugins: []const BundledPlugin, name: []const u8) bool { + for (plugins) |p| if (p.module == null and std.mem.eql(u8, p.name, name)) return true; + return false; +} + +/// What one executable gives the plugins it links. +pub const Wiring = struct { + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, + dvui: *std.Build.Module, + core: *std.Build.Module, + sdk: *std.Build.Module, + icons: ?*std.Build.Module, + /// workbench's: the native backend, null on the web. + backend: ?*std.Build.Module, + workbench_opts: *std.Build.Step.Options, + /// The executable's root module, which imports each plugin by its name. + consumer: *std.Build.Module, + /// False where markdown does not build (the native exe for wasm). + markdown: bool = true, +}; + +pub const Linked = struct { + /// The modules for `bundledPluginsModule`, in the order the application listed them. + plugins: []const BundledPlugin, + /// Built whether or not they are listed: fizzy's own code imports both. The editor holds + /// workbench's state, and the store draws a plugin's README with markdown. A module is made + /// once for its consumer, so a listed one is this one. + workbench: *std.Build.Module, + markdown: ?*std.Build.Module, +}; + +/// Make the modules for `plugins`: fizzy's own built for this executable, an application's +/// 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)", .{}); + + const workbench_mod = workbench.addStaticModule(b, w.target, w.optimize, .{ + .dvui = w.dvui, + .core = w.core, + .sdk = w.sdk, + .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; + + var out: std.ArrayList(BundledPlugin) = .empty; + for (plugins) |p| { + const m: ?*std.Build.Module = if (p.module) |src| rehome(b, w, 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) + 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 }, 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) + 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) + else + 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| out.append(b.allocator, .{ .name = p.name, .module = module }) catch @panic("OOM"); + } + return .{ .plugins = out.items, .workbench = workbench_mod, .markdown = markdown_mod }; +} + +/// A copy of an application's plugin module for this executable, not the plugin package's module +/// itself: one application builds several executables (the packaged, Velopack-linked one beside +/// the plain one, the web one), each with its own `dvui`/`core`/`fizzy_sdk`, and one module cannot +/// import both sets. The copy keeps the plugin's own imports (its manifest options, its +/// dependencies) and gets this executable's framework modules. +pub fn rehome(b: *std.Build, w: Wiring, name: []const u8, src: *std.Build.Module) *std.Build.Module { + const wasm = w.target.result.cpu.arch == .wasm32; + const m = b.createModule(.{ + .target = w.target, + .optimize = w.optimize, + .root_source_file = src.root_source_file, + .link_libc = !wasm, + .single_threaded = if (wasm) true else null, + }); + var it = src.import_table.iterator(); + while (it.next()) |kv| { + const import = kv.key_ptr.*; + if (std.mem.eql(u8, import, "dvui") or std.mem.eql(u8, import, "core") or std.mem.eql(u8, import, "fizzy_sdk") or std.mem.eql(u8, import, "icons")) continue; + m.addImport(import, kv.value_ptr.*); + } + m.addImport("dvui", w.dvui); + m.addImport("core", w.core); + m.addImport("fizzy_sdk", w.sdk); + if (w.icons) |icons| m.addImport("icons", icons); + w.consumer.addImport(name, m); + return m; +} diff --git a/build/sdk.zig b/build/sdk.zig index 836c58695..0a340532a 100644 --- a/build/sdk.zig +++ b/build/sdk.zig @@ -147,8 +147,9 @@ pub fn buildOptsModule(opts: *std.Build.Step.Options) *std.Build.Module { pub const BundledPlugin = struct { /// The plugin's import name and id — `plugin_id` in its root, `plugin.zig.zon`'s `.id`. name: []const u8, - /// Null for a plugin this target does not build (markdown on wasm); it is left out. - module: ?*std.Build.Module, + /// The plugin's static module. Null for one of fizzy's own (`fizzy.plugins`), which fizzy + /// builds for each executable. + module: ?*std.Build.Module = null, }; /// The generated `bundled_plugins` module: `pub const modules = .{ @import("a"), @import("b") … }` diff --git a/build/web.zig b/build/web.zig index 2ad8c320f..d0075f6f6 100644 --- a/build/web.zig +++ b/build/web.zig @@ -4,13 +4,6 @@ const core_mod = @import("fizzy_sdk").core_module; const plugins = @import("plugins.zig"); const sdk = @import("sdk.zig"); -const workbench_plugin = plugins.workbench; -const text_plugin = plugins.text; -const image_plugin = plugins.image; -const archive_plugin = plugins.archive; -const devtools_plugin = plugins.devtools; -const markdown_plugin = plugins.markdown; - pub fn addSteps( b: *std.Build, optimize: std.builtin.OptimizeMode, @@ -173,59 +166,28 @@ pub fn addSteps( // lazy analysis skips file-scope consts that no reachable body uses. // So no `backend` module is wired in for the web build. - const workbench_module_web = workbench_plugin.addStaticModule(b, web_target, optimize, .{ + // What the application links, as the native exe has it (`build/exe.zig`), fizzy's own built + // here for wasm and the application's re-homed: modules made for the native target get this + // build's framework modules, their own imports kept. + const wiring: plugins.Wiring = .{ + .target = web_target, + .optimize = optimize, .dvui = dvui_web, .core = core_module_web, .sdk = sdk_module_web, .icons = icons_web, .backend = null, - }, workbench_opts, web_exe.root_module); - const text_module_web = text_plugin.addStaticModule(b, web_target, optimize, .{ - .dvui = dvui_web, - .core = core_module_web, - .sdk = sdk_module_web, - .icons = icons_web, - }, web_exe.root_module); - const image_module_web = image_plugin.addStaticModule(b, web_target, optimize, .{ - .dvui = dvui_web, - .core = core_module_web, - .sdk = sdk_module_web, - }, web_exe.root_module); - const archive_module_web = archive_plugin.addStaticModule(b, web_target, optimize, .{ - .dvui = dvui_web, - .core = core_module_web, - .sdk = sdk_module_web, - }, web_exe.root_module); - const markdown_module_web = markdown_plugin.addStaticModule(b, web_target, optimize, .{ - .dvui = dvui_web, - .core = core_module_web, - .sdk = sdk_module_web, - }, web_exe.root_module); - const devtools_module_web = devtools_plugin.addStaticModule(b, web_target, optimize, .{ - .dvui = dvui_web, - .core = core_module_web, - .sdk = sdk_module_web, - }, web_exe.root_module); + .workbench_opts = workbench_opts, + .consumer = web_exe.root_module, + }; + const linked = plugins.link(b, wiring, app_plugins); + const markdown_module_web = linked.markdown; var bundled_list: std.ArrayList(sdk.BundledPlugin) = .empty; - bundled_list.appendSlice(b.allocator, &.{ - .{ .name = "workbench", .module = workbench_module_web }, - .{ .name = "text", .module = text_module_web }, - .{ .name = "image", .module = image_module_web }, - .{ .name = "archive", .module = archive_module_web }, - .{ .name = "markdown", .module = markdown_module_web }, - .{ .name = "devtools", .module = devtools_module_web }, - }) catch @panic("OOM"); - // Out-of-tree plugins the web build links in: the application's own list (`buildApp`), - // whose modules were made for the native target and are re-homed here, and the named - // dependencies resolved directly for wasm. Same re-homing the native exe does — a copy - // with this build's framework modules and the plugin's own imports kept. - for (app_plugins) |p| { - const src_mod = p.module orelse continue; - bundled_list.append(b.allocator, .{ .name = p.name, .module = rehome(b, web_target, optimize, src_mod, dvui_web, core_module_web, sdk_module_web, icons_web) }) catch @panic("OOM"); - } + bundled_list.appendSlice(b.allocator, linked.plugins) catch @panic("OOM"); + // 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 = rehome(b, web_target, optimize, dep.module("plugin"), dvui_web, core_module_web, sdk_module_web, icons_web) }) 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 @@ -387,33 +349,3 @@ fn stampStorage(b: *std.Build) std.Build.LazyPath { const stamped = std.mem.replaceOwned(u8, b.allocator, html, token, name) catch @panic("OOM"); return b.addWriteFiles().add("index.html", stamped); } - -fn rehome( - b: *std.Build, - web_target: std.Build.ResolvedTarget, - optimize: std.builtin.OptimizeMode, - src_mod: *std.Build.Module, - dvui_mod: *std.Build.Module, - core_module: *std.Build.Module, - sdk_mod: *std.Build.Module, - icons_mod: ?*std.Build.Module, -) *std.Build.Module { - const m = b.createModule(.{ - .target = web_target, - .optimize = optimize, - .root_source_file = src_mod.root_source_file, - .link_libc = false, - .single_threaded = true, - }); - var it = src_mod.import_table.iterator(); - while (it.next()) |kv| { - const name = kv.key_ptr.*; - if (std.mem.eql(u8, name, "dvui") or std.mem.eql(u8, name, "core") or std.mem.eql(u8, name, "fizzy_sdk") or std.mem.eql(u8, name, "icons")) continue; - m.addImport(name, kv.value_ptr.*); - } - m.addImport("dvui", dvui_mod); - m.addImport("core", core_module); - m.addImport("fizzy_sdk", sdk_mod); - if (icons_mod) |icons| m.addImport("icons", icons); - return m; -} diff --git a/src/Entry.zig b/src/Entry.zig index 77b578664..792624f1e 100644 --- a/src/Entry.zig +++ b/src/Entry.zig @@ -11,7 +11,6 @@ const icon = assets.files.@"icon.png"; const fizzy = @import("fizzy.zig"); const workbench = @import("workbench"); -const text = @import("text"); const auto_update = @import("app").update.auto_update; const file_assoc = @import("backend/file_assoc.zig"); const update_notify = @import("app").update.update_notify; diff --git a/src/editor/Editor.zig b/src/editor/Editor.zig index 3bc656b2f..21d552036 100644 --- a/src/editor/Editor.zig +++ b/src/editor/Editor.zig @@ -2114,9 +2114,11 @@ pub fn postInit(editor: *Editor) !void { // hardcoding panes. Web-safe — the draw fns reach the same inline code the // editor tick already runs on wasm. Order = sidebar order. // Every bundled plugin: its dylib beside the exe when there is one, else the copy linked - // in. None of the bundled four ship as dylibs today, so the load "fails" and the static - // copy registers on every run; not worth logging until that changes. The workbench's - // dylib entry takes the workbench state fizzy still holds as `arg_c`. + // in. The build puts the dylibs of fizzy's own (workbench, text, markdown, image) in + // `/plugins/`, so fizzy's own features load the way a third-party plugin does + // and that path is exercised every run; a plugin with no dylib (archive, devtools, an + // app's own, every one on the web) fails the load quietly and its static copy registers. + // The workbench's dylib entry takes the workbench state fizzy still holds as `arg_c`. // What this build bundles, for anything that needs to know a plugin is compiled in rather // than installed (the store, which must not offer to uninstall one). editor.app.bundled_plugin_ids = comptime blk: {