Genja Plugin Manager
A plugin management library for Rust applications that need to load Genja-compatible plugins from shared libraries at runtime.
What Changed
The recommended integration flow is now:
- build your plugin crates as
cdylib - declare the built plugin library paths in the end-user app's
Cargo.toml - call
genja_plugin_manager::build_support::copy_plugins_from_manifest()from the end-user app'sbuild.rs - load plugins at runtime from a
pluginsdirectory beside the executable
Runtime loading no longer needs to read the end-user app manifest directly.
Features
- Dynamic loading of plugins from shared library files
- Linux:
.so - macOS:
.dylib - Windows:
.dll
- Linux:
- Support for individual and grouped plugin metadata entries
- Runtime scanning of a plugin directory
- Type-safe plugin lookup by plugin kind
- Build-script helper for copying plugin artifacts into the runtime plugin directory
Installation
Runtime dependency:
[]
= "0.1.0"
If your application uses manifest-driven plugin copying in build.rs, add it as a build dependency too:
[]
= "0.1.0"
Creating a Plugin
Implement Plugin plus one of the typed plugin traits and export create_plugins.
use async_trait;
use Hosts;
use RunnerConfig;
use ;
use ;
;
For inventory plugins there are now two Rust trait paths:
PluginInventoryfor synchronous loadersAsyncPluginInventoryfor async loaders used withGenja::from_settings_file_async(...)
The async constructor is the superset path: it prefers AsyncPluginInventory
when registered for the selected plugin name and otherwise falls back to
PluginInventory.
Plugin crate setup:
[]
= "my_plugin"
= "0.1.0"
= "2024"
[]
= "0.1.0"
= "0.1.0"
[]
= "my_plugin"
= ["lib", "cdylib"]
Build the plugin:
End-User Application Setup
The end-user application is the source of truth for plugin artifacts.
Example Cargo.toml:
[]
= "use_genja"
= "0.1.0"
= "2024"
[]
= "0.1.0"
= "0.1.0"
[]
= "0.1.0"
[]
= "target/{PROFILE}/libhostname_ip_transform.so"
[]
= "target/{PROFILE}/libhost_loader.so"
Notes:
- metadata paths are resolved relative to the consuming app's
Cargo.toml {PROFILE}is replaced bydebugorreleaseby the build helper- grouped entries are supported and flattened into the runtime plugin directory
Example build.rs:
What this does:
- reads
[package.metadata.plugins]from the end-user app manifest - copies the referenced plugin libraries into
target/{PROFILE}/plugins - leaves runtime loading to the normal plugin directory scan
Runtime Loading
At runtime, load plugins from a directory instead of reading Cargo.toml.
use PluginManager;
In a real application, prefer resolving the plugin directory relative to the executable location, for example current_exe().parent().join("plugins").
Metadata Format
Both individual and grouped entries are supported.
[]
= "target/{PROFILE}/libplugin_a.so"
[]
= "target/{PROFILE}/libinventory_a.so"
[]
= "target/{PROFILE}/libthreaded_ext.so"
Workspace Notes
If the end-user app is part of a Cargo workspace, paths in [package.metadata.plugins] are still resolved relative to that crate's own Cargo.toml, not the workspace root.
That usually means plugin artifact paths look like:
[]
= "../target/{PROFILE}/libplugin_a.so"
instead of:
[]
= "target/{PROFILE}/libplugin_a.so"
depending on your workspace layout.
API Summary
Common entry points:
PluginManager::load_plugin(...)PluginManager::load_plugins_from_directory(...)PluginManager::get_runner_plugin(...)PluginManager::get_inventory_plugin(...)PluginManager::get_processor_plugin(...)genja_plugin_manager::build_support::copy_plugins_from_manifest()
License
This project is licensed under AGPL-3.0-only. See LICENSE.
Contributing
Contributions are welcome. Submit a pull request with tests for behavior changes.