Skip to content

feat(sdk): static plugin registry + static dialog for no-dlopen (WASM) builds#132

Merged
facontidavide merged 4 commits into
mainfrom
wasm-static-registry
Jun 21, 2026
Merged

feat(sdk): static plugin registry + static dialog for no-dlopen (WASM) builds#132
facontidavide merged 4 commits into
mainfrom
wasm-static-registry

Conversation

@facontidavide

Copy link
Copy Markdown
Contributor

What

Adds the SDK infrastructure for statically-linked plugins — needed by builds with no dlopen, primarily Qt-for-WebAssembly. Three commits:

  • feat(sdk): static plugin registry for WASM / no-dlopen builds — host-side registration entry points so a DataSource / MessageParser / Toolbox plugin compiled into the executable can register with the runtime catalog without dlopen (plugin_runtime_catalog + the four *_library host classes + the SDK plugin-base hooks).
  • feat(sdk): static PJ_DIALOG_PLUGIN variant (no-collision, WASM) — a collision-free static variant of the dialog plugin macro so multiple statically-linked dialog plugins coexist in one binary.
  • chore(release): bump version to 0.11.0.

Why

On wasm there is no dynamic loader, so every plugin must be linked into the app and registered via a known symbol instead of being discovered on disk. These additions provide that path while leaving the existing dynamic (dlopen) flow untouched.

Version / compatibility

MINOR → 0.11.0. All changes are backward-compatible API additions — new entry points only; every already-built plugin keeps working with no recompile (abidiff should show additions only). Three version sources bumped in lockstep (conanfile.py, CMakeLists.txt, recipe.yaml).

This branch was rebased onto current main, so it already includes the AssetVideo removal (#131); the diff here is purely the static-plugin additions.

No tag / release in this PR — tagging v0.11.0 (which would fire the conda + GitHub release jobs) is a separate, explicitly-authorized step.

Downstream

Unblocks the PlotJuggler wasm build: PJ4's feat/wasm-p0-p1-refresh statically links the ROS + foxglove message parsers and scene2D, and re-points its submodule at this branch's tip.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

facontidavide and others added 3 commits June 21, 2026 19:40
Add a static-linking path alongside the dlopen one, for Qt-for-WebAssembly
(and any single-binary build) where many plugins are linked into the host:

- PJ_{DATA_SOURCE,TOOLBOX,MESSAGE_PARSER}_PLUGIN, under #ifdef PJ_STATIC_PLUGINS,
  emit a uniquely class-keyed `pj_static_get_*_vtable_<Class>()` instead of the
  fixed `extern "C" PJ_get_*_vtable` symbol (which would collide across plugins
  in one binary). The C-ABI vtable contract is unchanged.
- {DataSource,MessageParser,Toolbox}Library::loadStatic(vtable): wrap a
  statically-linked vtable with a sentinel shared_ptr owner (no DSO), so
  valid()/createHandle() work unchanged.
- PluginRuntimeCatalog::registerStatic{DataSource,MessageParser,Toolbox}(vtable):
  read the embedded manifest JSON and register without a disk scan.
- CMakeLists: append -Wno-error under EMSCRIPTEN (wasm32 size_t is 32-bit).

Pure additions (+243/-0); the dlopen path and desktop behavior are untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under PJ_STATIC_PLUGINS many plugins link into one binary; the fixed
`extern "C" PJ_get_dialog_vtable` symbol (+ the ABI-version export) PJ_DIALOG_PLUGIN
emits would collide across them at link. Emit a uniquely class-keyed
pj_static_get_dialog_vtable_<Class>() instead (keeping the dialogVtableFor<Class>
specialization), completing the static-export pattern the other three family
macros already follow. The static registry resolves dialogs by this getter, not
the dlsym entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MINOR: backward-compatible API additions for static (no-dlopen) plugin
linking — the static plugin registry + static dialog variant used by the
Qt-for-WebAssembly build. All already-built plugins keep working unchanged.

Also normalize clang-format (backslash-continuation alignment) on the
static-plugin macro headers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@facontidavide facontidavide force-pushed the wasm-static-registry branch from 9351d03 to e1f8cb8 Compare June 21, 2026 17:55
registerStaticDataSource/MessageParser/Toolbox were near-verbatim copies
differing only in library type, runtime struct, family label, and the one
family-specific field. Extract a `registerStaticPlugin<>` helper that does the
shared load-static + parse-manifest + fill-common-fields + push body; each
method now passes only the family-specific fill lambda. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@facontidavide facontidavide merged commit 6e91268 into main Jun 21, 2026
6 of 7 checks passed
@facontidavide facontidavide deleted the wasm-static-registry branch June 21, 2026 18:23
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