Skip to content

app: a link-only build, which loads no plugin at runtime - #445

Merged
foxnne merged 1 commit into
mainfrom
app/link-only
Oct 16, 2026
Merged

foxnne merged 1 commit into
mainfrom
app/link-only

Conversation

@foxnne

@foxnne foxnne commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Part of fizzyedit/plans#13 (step 2). Builds on #441.

What changes

An app built on fizzy can run with linked plugins only:

const fizzy_dep = b.dependency("fizzy", .{ …, .@"defer-app" = true, .@"dynamic-plugins" = false });

(or zig build -Ddynamic-plugins=false). In that build:

  • No plugin dylib is built or installed. fizzy's four bundled ones are skipped, as are the packaged copies.
  • Nothing loads at runtime. One comptime constant, App.loads_plugins, turns off:
    • the bundled-dylib probe in postInit
    • the user plugins directory scan (loadUserPlugins)
    • loading a plugin by id (the store's and settings' enable path)
    • a web page's ?plugin= request
  • No store. PluginStore.register still sets the PluginManager (settings name plugins through it), then returns before the catalog fetch and the store's view. tick returns at once.

Every gate is comptime, as wasm's are, so a dynamic build checks nothing at runtime. Most other dynamic paths go quiet on their own when nothing is dlopened: the rebuilt-plugin watcher walks only the loaded libraries.

CI compiles the link-only build on Linux (-Ddynamic-plugins=false -Dno-emit, about 10 s locally), because its gates are comptime and the default build never compiles that branch.

SDK impact

  • None

Verified

  • macOS:
    • Build: zig build -Ddynamic-plugins=false installs only the executable, with no plugins/ directory.
    • Runtime: a text.dylib planted beside the executable and in the profile's user plugins directory is not mapped into the link-only process (vmmap). The default build, run with the same profile, maps all four of fizzy's dylibs.
    • Screenshots: the link-only window has no store icon in the rail, and the default build has it above the settings cog.
    • Gates on the default build: zig build, test (91/91 steps), test-integration (53/53 steps), check-tests-reached, test-sdk-version, check-fmt.
    • Web: check-web with and without the flag.
  • Windows:
  • Linux: CI (including the new link-only compile)
  • Web: compiles link-only; not run in a browser

Not exercised: opening Settings in the link-only build. Its plugin rows read through the PluginManager, which is set as before.

Follow-ups

  • Removing the buildApp fallback (a list naming none of fizzy's plugins gets all of them) waits until build: fizzy's plugins are listed; the minimal shape links two example-app#6 is on example-app's main, because fizzy's CI builds that main. It's a small PR after the repin.
  • example-app: a link-only build in its CI and in check-examples.sh, after this merges, for the same ordering reason.

🤖 Generated with Claude Code

-Ddynamic-plugins=false (a buildApp dependency option too) makes an app run exactly the
plugins it links. No plugin dylib is built, and App.loads_plugins (comptime) turns off the
bundled-dylib probe, the user plugins directory scan, loading a plugin by id, a web page's
?plugin= request, and the store (PluginStore.register keeps the manager, which settings read,
then returns; tick returns). CI compiles it on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@foxnne
foxnne marked this pull request as ready for review October 16, 2026 15:42
@foxnne
foxnne merged commit 07d8b03 into main Oct 16, 2026
12 checks passed
@foxnne
foxnne deleted the app/link-only branch October 16, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant