Merge pull request #104129 from dsnopek/gdextension-get-used-classes

GDExtension: Add mechanism to get which classes an extension is using
This commit is contained in:
Thaddeus Crews 2025-03-17 16:03:27 -05:00
commit 1b631edf67
No known key found for this signature in database
GPG Key ID: 62181B86FE9E5D84
3 changed files with 39 additions and 0 deletions

View File

@ -679,6 +679,13 @@ void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExte
memnew_placement(r_path, String(library_path));
}
void GDExtension::_register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback) {
#ifdef TOOLS_ENABLED
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
self->get_classes_used_callback = p_callback;
#endif
}
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
@ -799,6 +806,7 @@ void GDExtension::initialize_gdextensions() {
register_interface_function("classdb_register_extension_class_signal", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_signal);
register_interface_function("classdb_unregister_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_unregister_extension_class);
register_interface_function("get_library_path", (GDExtensionInterfaceFunctionPtr)&GDExtension::_get_library_path);
register_interface_function("editor_register_get_classes_used_callback", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_get_classes_used_callback);
}
void GDExtension::finalize_gdextensions() {
@ -1034,6 +1042,14 @@ void GDExtension::_untrack_instance(void *p_user_data, void *p_instance) {
extension->instances.erase(obj->get_instance_id());
}
PackedStringArray GDExtension::get_classes_used() const {
PackedStringArray ret;
if (get_classes_used_callback) {
get_classes_used_callback((GDExtensionTypePtr)&ret);
}
return ret;
}
Vector<StringName> GDExtensionEditorPlugins::extension_classes;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;

View File

@ -93,6 +93,7 @@ class GDExtension : public Resource {
static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
static void _register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
GDExtensionInitialization initialization;
int32_t level_initialized = -1;
@ -101,6 +102,7 @@ class GDExtension : public Resource {
bool is_reloading = false;
Vector<GDExtensionMethodBind *> invalid_methods;
Vector<ObjectID> instance_bindings;
GDExtensionEditorGetClassesUsedCallback get_classes_used_callback = nullptr;
static void _track_instance(void *p_user_data, void *p_instance);
static void _untrack_instance(void *p_user_data, void *p_instance);
@ -155,6 +157,8 @@ public:
void track_instance_binding(Object *p_object);
void untrack_instance_binding(Object *p_object);
PackedStringArray get_classes_used() const;
#endif
InitializationLevel get_minimum_library_initialization_level() const;

View File

@ -400,6 +400,9 @@ typedef struct {
typedef void *GDExtensionClassLibraryPtr;
/* Passed a pointer to a PackedStringArray that should be filled with the classes that may be used by the GDExtension. */
typedef void (*GDExtensionEditorGetClassesUsedCallback)(GDExtensionTypePtr p_packed_string_array);
/* Method */
typedef enum {
@ -3111,6 +3114,22 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
/**
* @name editor_register_get_classes_used_callback
* @since 4.5
*
* Registers a callback that Godot can call to get the list of all classes (from ClassDB) that may be used by the calling GDExtension.
*
* This is used by the editor to generate a build profile (in "Tools" > "Engine Compilation Configuration Editor..." > "Detect from project"),
* in order to recompile Godot with only the classes used.
* In the provided callback, the GDExtension should provide the list of classes that _may_ be used statically, thus the time of invocation shouldn't matter.
* If a GDExtension doesn't register a callback, Godot will assume that it could be using any classes.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_callback The callback to retrieve the list of classes used.
*/
typedef void (*GDExtensionInterfaceEditorRegisterGetClassesUsedCallback)(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
#ifdef __cplusplus
}
#endif