mirror of
https://github.com/bevyengine/bevy
synced 2024-11-14 00:47:32 +00:00
Deprecate dynamic plugins (#13080)
# Objective - The current implementation for dynamic plugins is unsound. Please see #11969 for background and justification. - Closes #11969 and closes #13073. ## Solution - Deprecate all dynamic plugin items for Bevy 0.14, with plans to remove them for Bevy 0.15. ## Discussion One thing I want to make clear is that I'm not opposed to dynamic plugins _in general_. I think they can be handy, especially for DLC and modding, but I think the current system is the wrong approach. It's too much of a footgun for the meager benefit is provides. --- ## Changelog - Deprecated the current dynamic plugin system. - Dynamic plugins will be removed in Bevy 0.15. For now you can continue using them by marking your code with `#[allow(deprecated)]`. ## Migration Guide If possible, remove all usage of dynamic plugins. ```rust // Old #[derive(DynamicPlugin)] pub struct MyPlugin; App::new() .load_plugin("path/to/plugin") .run(); // New pub struct MyPlugin; App::new() .add_plugins(MyPlugin) .run(); ``` If you are unable to do that, you may temporarily silence the deprecation warnings. ```rust #[allow(deprecated)] ``` Please note that the current dynamic plugin system will be removed by the next major Bevy release, so you will have to migrate eventually. You may be interested in these safer alternatives: - [Bevy Assets - Scripting]: Scripting and modding libraries for Bevy - [Bevy Assets - Development tools]: Hot reloading and other development functionality - [`stabby`]: Stable Rust ABI [Bevy Assets - Scripting]: https://bevyengine.org/assets/#scripting [Bevy Assets - Development tools]: https://bevyengine.org/assets/#development-tools [`stabby`]: https://github.com/ZettaScaleLabs/stabby
This commit is contained in:
parent
612e77ef78
commit
2940636e0a
5 changed files with 39 additions and 0 deletions
|
@ -124,6 +124,10 @@ impl Plugin for PlaceholderPlugin {
|
||||||
/// It is used for dynamically loading plugins.
|
/// It is used for dynamically loading plugins.
|
||||||
///
|
///
|
||||||
/// See `bevy_dynamic_plugin/src/loader.rs#dynamically_load_plugin`.
|
/// See `bevy_dynamic_plugin/src/loader.rs#dynamically_load_plugin`.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;
|
pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;
|
||||||
|
|
||||||
/// Types that represent a set of [`Plugin`]s.
|
/// Types that represent a set of [`Plugin`]s.
|
||||||
|
|
|
@ -2,6 +2,10 @@ use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_macro_input, DeriveInput};
|
use syn::{parse_macro_input, DeriveInput};
|
||||||
|
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
|
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
let struct_name = &ast.ident;
|
let struct_name = &ast.ident;
|
||||||
|
|
|
@ -19,8 +19,15 @@ use proc_macro::TokenStream;
|
||||||
use quote::format_ident;
|
use quote::format_ident;
|
||||||
|
|
||||||
/// Generates a dynamic plugin entry point function for the given `Plugin` type.
|
/// Generates a dynamic plugin entry point function for the given `Plugin` type.
|
||||||
|
///
|
||||||
|
/// This is deprecated since 0.14. The current dynamic plugin system is unsound and will be removed in 0.15.
|
||||||
#[proc_macro_derive(DynamicPlugin)]
|
#[proc_macro_derive(DynamicPlugin)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
|
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
|
||||||
|
#[allow(deprecated)]
|
||||||
app_plugin::derive_dynamic_plugin(input)
|
app_plugin::derive_dynamic_plugin(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,23 @@
|
||||||
//! This crate allows loading dynamic libraries (`.dylib`, `.so`) that export a single
|
//! This crate allows loading dynamic libraries (`.dylib`, `.so`) that export a single
|
||||||
//! [`Plugin`](bevy_app::Plugin). For usage, see [`dynamically_load_plugin`].
|
//! [`Plugin`](bevy_app::Plugin). For usage, see [`dynamically_load_plugin`].
|
||||||
//!
|
//!
|
||||||
|
//! # Deprecation
|
||||||
|
//!
|
||||||
|
//! The current dynamic plugin system is unsound and will be removed in 0.15. You may be interested
|
||||||
|
//! in the [Alternatives](#alternatives) listed below. If your use-case is not supported, please
|
||||||
|
//! consider commenting on [#13080](https://github.com/bevyengine/bevy/pull/13080) describing how
|
||||||
|
//! you use dynamic plugins in your project.
|
||||||
|
//!
|
||||||
|
//! # Warning
|
||||||
|
//!
|
||||||
//! Note that dynamic linking and loading is inherently unsafe because it allows executing foreign
|
//! Note that dynamic linking and loading is inherently unsafe because it allows executing foreign
|
||||||
//! code. Additionally, Rust does not have a stable ABI and may produce
|
//! code. Additionally, Rust does not have a stable ABI and may produce
|
||||||
//! incompatible libraries across Rust versions, or even subsequent compilations. This will not work
|
//! incompatible libraries across Rust versions, or even subsequent compilations. This will not work
|
||||||
//! well in scenarios such as modding, but can work if the dynamic plugins and the main app are
|
//! well in scenarios such as modding, but can work if the dynamic plugins and the main app are
|
||||||
//! built at the same time, such as with Downloadable Content (DLC) packs.
|
//! built at the same time, such as with Downloadable Content (DLC) packs.
|
||||||
//!
|
//!
|
||||||
|
//! # Alternatives
|
||||||
|
//!
|
||||||
//! You may be interested in these safer alternatives:
|
//! You may be interested in these safer alternatives:
|
||||||
//!
|
//!
|
||||||
//! - [Bevy Assets - Scripting]: Scripting and modding libraries for Bevy
|
//! - [Bevy Assets - Scripting]: Scripting and modding libraries for Bevy
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
use libloading::{Library, Symbol};
|
use libloading::{Library, Symbol};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
@ -8,6 +9,10 @@ use bevy_app::{App, CreatePlugin, Plugin};
|
||||||
|
|
||||||
/// Errors that can occur when loading a dynamic plugin
|
/// Errors that can occur when loading a dynamic plugin
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub enum DynamicPluginLoadError {
|
pub enum DynamicPluginLoadError {
|
||||||
/// An error occurred when loading a dynamic library.
|
/// An error occurred when loading a dynamic library.
|
||||||
#[error("cannot load library for dynamic plugin: {0}")]
|
#[error("cannot load library for dynamic plugin: {0}")]
|
||||||
|
@ -30,6 +35,10 @@ pub enum DynamicPluginLoadError {
|
||||||
/// foreign code, initialization routines may be run (as well as termination routines when the
|
/// foreign code, initialization routines may be run (as well as termination routines when the
|
||||||
/// program exits). The caller of this function is responsible for ensuring these routines are
|
/// program exits). The caller of this function is responsible for ensuring these routines are
|
||||||
/// sound. For more information, please see the safety section of [`libloading::Library::new`].
|
/// sound. For more information, please see the safety section of [`libloading::Library::new`].
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub unsafe fn dynamically_load_plugin<P: AsRef<OsStr>>(
|
pub unsafe fn dynamically_load_plugin<P: AsRef<OsStr>>(
|
||||||
path: P,
|
path: P,
|
||||||
) -> Result<(Library, Box<dyn Plugin>), DynamicPluginLoadError> {
|
) -> Result<(Library, Box<dyn Plugin>), DynamicPluginLoadError> {
|
||||||
|
@ -51,6 +60,10 @@ pub unsafe fn dynamically_load_plugin<P: AsRef<OsStr>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An extension trait for [`App`] that allows loading dynamic plugins.
|
/// An extension trait for [`App`] that allows loading dynamic plugins.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.14.0",
|
||||||
|
note = "The current dynamic plugin system is unsound and will be removed in 0.15."
|
||||||
|
)]
|
||||||
pub trait DynamicPluginExt {
|
pub trait DynamicPluginExt {
|
||||||
/// Dynamically links a plugin at the given path, registering the plugin.
|
/// Dynamically links a plugin at the given path, registering the plugin.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue