From f7ca84f2c674bf135931334e135fd1acf5d733ec Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Tue, 3 Dec 2024 23:04:51 +0100 Subject: [PATCH] Add docs for #[gdextension(entry_symbol)] key (now renamed from `entry_point`) --- godot-core/src/deprecated.rs | 11 ++++++++--- godot-core/src/init/mod.rs | 25 +++++++++++++++++++++---- godot-macros/src/gdextension.rs | 20 +++++++++++++++++++- itest/rust/src/lib.rs | 2 +- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/godot-core/src/deprecated.rs b/godot-core/src/deprecated.rs index ab4559bf8..5d3313116 100644 --- a/godot-core/src/deprecated.rs +++ b/godot-core/src/deprecated.rs @@ -38,17 +38,22 @@ pub use crate::emit_deprecated_warning; // Library-side deprecations #[deprecated = "\nThe attribute key #[init(val = ...)] replaces #[init(default = ...)].\n\ - More information on https://github.com/godot-rust/gdext/pull/844."] + More information on https://github.com/godot-rust/gdext/pull/844"] pub const fn init_default() {} #[deprecated = "\nThe attribute key #[class(editor_plugin)] is now implied by #[class(base = EditorPlugin)]. It is ignored.\n\ - More information on https://github.com/godot-rust/gdext/pull/884."] + More information on https://github.com/godot-rust/gdext/pull/884"] pub const fn class_editor_plugin() {} #[deprecated = "\nThe attribute key #[class(hidden)] has been renamed to #[class(internal)], following Godot terminology.\n\ - More information on https://github.com/godot-rust/gdext/pull/884."] + More information on https://github.com/godot-rust/gdext/pull/884"] pub const fn class_hidden() {} +#[deprecated = "\nThe attribute key #[gdextension(entry_point)] has been renamed to #[gdextension(entry_symbol)], for consistency \ + with the configuration key in the .gdextension file.\n\ + More information on https://github.com/godot-rust/gdext/pull/959"] +pub const fn gdextension_entry_point() {} + // ---------------------------------------------------------------------------------------------------------------------------------------------- // Godot-side deprecations diff --git a/godot-core/src/init/mod.rs b/godot-core/src/init/mod.rs index 5a287b0a5..a9f299830 100644 --- a/godot-core/src/init/mod.rs +++ b/godot-core/src/init/mod.rs @@ -184,12 +184,14 @@ fn gdext_on_level_deinit(level: InitLevel) { /// Every library should have exactly one implementation of this trait. It is always used in combination with the /// [`#[gdextension]`][gdextension] proc-macro attribute. /// +/// # Example /// The simplest usage is as follows. This will automatically perform the necessary init and cleanup routines, and register /// all classes marked with `#[derive(GodotClass)]`, without needing to mention them in a central list. The order in which /// classes are registered is not specified. /// /// ``` -/// # use godot::init::*; +/// use godot::init::*; +/// /// // This is just a type tag without any functionality. /// // Its name is irrelevant. /// struct MyExtension; @@ -198,10 +200,25 @@ fn gdext_on_level_deinit(level: InitLevel) { /// unsafe impl ExtensionLibrary for MyExtension {} /// ``` /// -/// # Safety -/// By using godot-rust, you accept the safety considerations [as outlined in the book][safety]. -/// Please make sure you fully understand the implications. +/// # Custom entry symbol +/// There is usually no reason to, but you can use a different entry point (C function in the dynamic library). This must match the key +/// that you specify in the `.gdextension` file. Let's say your `.gdextension` file has such a section: +/// ```toml +/// [configuration] +/// entry_symbol = "custom_name" +/// ``` +/// then you can implement the trait like this: +/// ```no_run +/// # use godot::init::*; +/// struct MyExtension; /// +/// #[gdextension(entry_symbol = custom_name)] +/// unsafe impl ExtensionLibrary for MyExtension {} +/// ``` +/// Note that this only changes the name. You cannot provide your own function -- use the [`on_level_init()`][ExtensionLibrary::on_level_init] +/// hook for custom startup logic. +/// +/// # Safety /// The library cannot enforce any safety guarantees outside Rust code, which means that **you as a user** are /// responsible to uphold them: namely in GDScript code or other GDExtension bindings loaded by the engine. /// Violating this may cause undefined behavior, even when invoking _safe_ functions. diff --git a/godot-macros/src/gdextension.rs b/godot-macros/src/gdextension.rs index 987896d90..68dc4bff1 100644 --- a/godot-macros/src/gdextension.rs +++ b/godot-macros/src/gdextension.rs @@ -28,12 +28,30 @@ pub fn attribute_gdextension(item: venial::Item) -> ParseResult { let drained_attributes = std::mem::take(&mut impl_decl.attributes); let mut parser = KvParser::parse_required(&drained_attributes, "gdextension", &impl_decl)?; let entry_point = parser.handle_ident("entry_point")?; + let entry_symbol = parser.handle_ident("entry_symbol")?; parser.finish()?; - let entry_point = entry_point.unwrap_or_else(|| ident("gdext_rust_init")); + if entry_point.is_some() && entry_symbol.is_some() { + return bail!( + impl_decl.tk_impl, + "Cannot specify both `entry_point` and `entry_symbol` in #[gdextension] attribute", + ); + } + + let deprecation = if entry_point.is_some() { + quote! { ::godot::__deprecated::emit_deprecated_warning!(gdextension_entry_point); } + } else { + TokenStream::new() + }; + + let entry_point = entry_symbol + .or(entry_point) + .unwrap_or_else(|| ident("gdext_rust_init")); + let impl_ty = &impl_decl.self_ty; Ok(quote! { + #deprecation #impl_decl // This cfg cannot be checked from the outer proc-macro since its 'target' is the build diff --git a/itest/rust/src/lib.rs b/itest/rust/src/lib.rs index 332ca0ad8..5a4bad9ac 100644 --- a/itest/rust/src/lib.rs +++ b/itest/rust/src/lib.rs @@ -18,7 +18,7 @@ mod register_tests; // ---------------------------------------------------------------------------------------------------------------------------------------------- // Entry point -#[gdextension(entry_point=itest_init)] +#[gdextension(entry_symbol = itest_init)] unsafe impl ExtensionLibrary for framework::IntegrationTests { fn on_level_init(level: InitLevel) { // Testing that we can initialize and use `Object`-derived classes during `Servers` init level. See `object_tests::init_level_test`.