Skip to main content

Module build_support

Module build_support 

Source
Expand description

Build-time support for copying plugin libraries into the Cargo output directory.

This module provides utilities for integrating plugin libraries into Rust applications at build time. It is designed to be used from build.rs scripts to automatically copy plugin dynamic libraries from their build locations into the application’s output directory, making them available for runtime loading.

§Overview

The plugin system requires dynamic libraries to be available at runtime in a known location. This module solves that problem by:

  1. Reading plugin declarations from [package.metadata.plugins] in Cargo.toml
  2. Resolving plugin library paths (supporting both absolute and relative paths)
  3. Copying plugin libraries to target/{PROFILE}/plugins/
  4. Emitting cargo:rerun-if-changed directives for proper incremental builds

§Plugin Declaration Format

Plugins are declared in the consuming application’s Cargo.toml under [package.metadata.plugins]. The format supports both individual plugins and grouped plugins:

[package.metadata.plugins]
# Individual plugin
ssh_plugin = "target/{PROFILE}/libssh_plugin.so"

# Grouped plugins
[package.metadata.plugins.connection]
ssh = "../plugins/ssh/target/{PROFILE}/libssh.so"
telnet = "../plugins/telnet/target/{PROFILE}/libtelnet.so"

# Absolute paths are also supported
[package.metadata.plugins.system]
audit = "/opt/genja/plugins/libaudit.so"

§Path Resolution

Plugin paths can be specified in three ways:

  1. Relative paths: Resolved relative to the manifest directory (where Cargo.toml lives)
  2. Absolute paths: Used as-is without modification
  3. Profile placeholders: The {PROFILE} placeholder is replaced with the current build profile (“debug” or “release”)

§Build Integration

To use this module in your application, add a build.rs file to your project root:

// build.rs
fn main() {
    genja_plugin_manager::build_support::copy_plugins_from_manifest()
        .expect("Failed to copy plugins");
}

Then declare your plugins in Cargo.toml:

[package.metadata.plugins]
my_plugin = "target/{PROFILE}/libmy_plugin.so"

§Runtime Loading

After build-time copying, plugins can be loaded at runtime using the plugin manager:

use genja_plugin_manager::PluginManager;

let mut manager = PluginManager::new();
manager.load_plugins_from_directory("target/debug/plugins")?;

§Cross-Platform Considerations

The helper reads only [package.metadata.plugins], so the plugin path you declare there must use the correct filename for the OS building the application:

Linux:

[package.metadata.plugins]
my_plugin = "target/{PROFILE}/libmy_plugin.so"

macOS:

[package.metadata.plugins]
my_plugin = "target/{PROFILE}/libmy_plugin.dylib"

Windows:

[package.metadata.plugins]
my_plugin = "target/{PROFILE}/my_plugin.dll"

§Error Handling

All functions in this module return io::Result<()>. Common error scenarios include:

  • Missing environment variables (CARGO_MANIFEST_DIR, OUT_DIR, PROFILE)
  • Invalid Cargo.toml syntax or structure
  • Missing plugin source files
  • Permission errors when creating directories or copying files
  • Invalid plugin path configurations (e.g., paths with no filename)

§Examples

§Basic Usage

// build.rs
fn main() {
    genja_plugin_manager::build_support::copy_plugins_from_manifest()
        .expect("Failed to copy plugins");
}

§With Error Handling

// build.rs
fn main() {
    if let Err(e) = genja_plugin_manager::build_support::copy_plugins_from_manifest() {
        eprintln!("Warning: Failed to copy plugins: {}", e);
        eprintln!("Plugins may not be available at runtime");
    }
}

§Multiple Plugin Groups

[package.metadata.plugins.connection]
ssh = "target/{PROFILE}/libssh.so"
telnet = "target/{PROFILE}/libtelnet.so"

[package.metadata.plugins.inventory]
file = "target/{PROFILE}/libfile_inventory.so"
database = "target/{PROFILE}/libdb_inventory.so"

[package.metadata.plugins.runner]
threaded = "target/{PROFILE}/libthreaded_runner.so"
serial = "target/{PROFILE}/libserial_runner.so"

§Implementation Notes

  • The module uses cargo:rerun-if-changed directives to ensure plugins are recopied when source files change
  • Plugin directory structure is created automatically if it doesn’t exist
  • Existing plugin files in the destination are overwritten without warning
  • The module processes nested plugin groups recursively
  • Profile resolution happens before path resolution, allowing profile-specific paths

Functions§

copy_plugins_from_manifest
Copy plugin libraries declared in [package.metadata.plugins] from the calling application’s Cargo.toml into target/{PROFILE}/plugins.