Merge pull request #88381 from m4gr3d/fix_gdextension_dependencies_load_on_android
Fix loading GDExtension dependencies on Android
This commit is contained in:
commit
0156bc2039
20 changed files with 163 additions and 82 deletions
|
@ -46,6 +46,41 @@ String GDExtension::get_extension_list_config_file() {
|
||||||
return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg");
|
return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<SharedObject> GDExtension::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
|
||||||
|
Vector<SharedObject> dependencies_shared_objects;
|
||||||
|
if (p_config->has_section("dependencies")) {
|
||||||
|
List<String> config_dependencies;
|
||||||
|
p_config->get_section_keys("dependencies", &config_dependencies);
|
||||||
|
|
||||||
|
for (const String &dependency : config_dependencies) {
|
||||||
|
Vector<String> dependency_tags = dependency.split(".");
|
||||||
|
bool all_tags_met = true;
|
||||||
|
for (int i = 0; i < dependency_tags.size(); i++) {
|
||||||
|
String tag = dependency_tags[i].strip_edges();
|
||||||
|
if (!p_has_feature(tag)) {
|
||||||
|
all_tags_met = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_tags_met) {
|
||||||
|
Dictionary dependency_value = p_config->get_value("dependencies", dependency);
|
||||||
|
for (const Variant *key = dependency_value.next(nullptr); key; key = dependency_value.next(key)) {
|
||||||
|
String dependency_path = *key;
|
||||||
|
String target_path = dependency_value[*key];
|
||||||
|
if (dependency_path.is_relative_path()) {
|
||||||
|
dependency_path = p_path.get_base_dir().path_join(dependency_path);
|
||||||
|
}
|
||||||
|
dependencies_shared_objects.push_back(SharedObject(dependency_path, dependency_tags, target_path));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencies_shared_objects;
|
||||||
|
}
|
||||||
|
|
||||||
String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
|
String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
|
||||||
// First, check the explicit libraries.
|
// First, check the explicit libraries.
|
||||||
if (p_config->has_section("libraries")) {
|
if (p_config->has_section("libraries")) {
|
||||||
|
@ -727,10 +762,24 @@ GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const String
|
||||||
return *function;
|
return *function;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) {
|
Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies) {
|
||||||
String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path);
|
String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path);
|
||||||
|
|
||||||
|
Vector<String> abs_dependencies_paths;
|
||||||
|
if (p_dependencies != nullptr && !p_dependencies->is_empty()) {
|
||||||
|
for (const SharedObject &dependency : *p_dependencies) {
|
||||||
|
abs_dependencies_paths.push_back(ProjectSettings::get_singleton()->globalize_path(dependency.path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String actual_lib_path;
|
String actual_lib_path;
|
||||||
Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true, &actual_lib_path, Engine::get_singleton()->is_editor_hint());
|
OS::GDExtensionData data = {
|
||||||
|
true, // also_set_library_path
|
||||||
|
&actual_lib_path, // r_resolved_path
|
||||||
|
Engine::get_singleton()->is_editor_hint(), // generate_temp_files
|
||||||
|
&abs_dependencies_paths, // library_dependencies
|
||||||
|
};
|
||||||
|
Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, &data);
|
||||||
|
|
||||||
if (actual_lib_path.get_file() != abs_path.get_file()) {
|
if (actual_lib_path.get_file() != abs_path.get_file()) {
|
||||||
// If temporary files are generated, let's change the library path to point at the original,
|
// If temporary files are generated, let's change the library path to point at the original,
|
||||||
|
@ -970,7 +1019,8 @@ Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path,
|
||||||
FileAccess::get_modified_time(library_path));
|
FileAccess::get_modified_time(library_path));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = p_extension->open_library(is_static_library ? String() : library_path, entry_symbol);
|
Vector<SharedObject> library_dependencies = GDExtension::find_extension_dependencies(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
|
||||||
|
err = p_extension->open_library(is_static_library ? String() : library_path, entry_symbol, &library_dependencies);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
// Unreference the extension so that this loading can be considered a failure.
|
// Unreference the extension so that this loading can be considered a failure.
|
||||||
p_extension.unref();
|
p_extension.unref();
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "core/io/config_file.h"
|
#include "core/io/config_file.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
|
#include "core/os/shared_object.h"
|
||||||
|
|
||||||
class GDExtensionMethodBind;
|
class GDExtensionMethodBind;
|
||||||
|
|
||||||
|
@ -123,8 +124,9 @@ public:
|
||||||
|
|
||||||
static String get_extension_list_config_file();
|
static String get_extension_list_config_file();
|
||||||
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
|
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
|
||||||
|
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);
|
||||||
|
|
||||||
Error open_library(const String &p_path, const String &p_entry_symbol);
|
Error open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies = nullptr);
|
||||||
void close_library();
|
void close_library();
|
||||||
|
|
||||||
enum InitializationLevel {
|
enum InitializationLevel {
|
||||||
|
|
|
@ -153,7 +153,14 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) { return ERR_UNAVAILABLE; }
|
struct GDExtensionData {
|
||||||
|
bool also_set_library_path = false;
|
||||||
|
String *r_resolved_path = nullptr;
|
||||||
|
bool generate_temp_files = false;
|
||||||
|
PackedStringArray *library_dependencies = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) { return ERR_UNAVAILABLE; }
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
|
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* editor_export_shared_object.h */
|
/* shared_object.h */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* This file is part of: */
|
/* This file is part of: */
|
||||||
/* GODOT ENGINE */
|
/* GODOT ENGINE */
|
||||||
|
@ -28,8 +28,8 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
#ifndef EDITOR_EXPORT_SHARED_OBJECT_H
|
#ifndef SHARED_OBJECT_H
|
||||||
#define EDITOR_EXPORT_SHARED_OBJECT_H
|
#define SHARED_OBJECT_H
|
||||||
|
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
@ -48,4 +48,4 @@ struct SharedObject {
|
||||||
SharedObject() {}
|
SharedObject() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EDITOR_EXPORT_SHARED_OBJECT_H
|
#endif // SHARED_OBJECT_H
|
|
@ -784,7 +784,7 @@ String OS_Unix::get_locale() const {
|
||||||
return locale;
|
return locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Unix::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
Error OS_Unix::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
String path = p_path;
|
String path = p_path;
|
||||||
|
|
||||||
if (FileAccess::exists(path) && path.is_relative_path()) {
|
if (FileAccess::exists(path) && path.is_relative_path()) {
|
||||||
|
@ -808,8 +808,8 @@ Error OS_Unix::open_dynamic_library(const String &p_path, void *&p_library_handl
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE);
|
p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE);
|
||||||
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ struct EditorProgress;
|
||||||
|
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
#include "core/io/zip_io.h"
|
#include "core/io/zip_io.h"
|
||||||
|
#include "core/os/shared_object.h"
|
||||||
#include "editor_export_preset.h"
|
#include "editor_export_preset.h"
|
||||||
#include "editor_export_shared_object.h"
|
|
||||||
#include "scene/gui/rich_text_label.h"
|
#include "scene/gui/rich_text_label.h"
|
||||||
#include "scene/main/node.h"
|
#include "scene/main/node.h"
|
||||||
#include "scene/resources/image_texture.h"
|
#include "scene/resources/image_texture.h"
|
||||||
|
|
|
@ -60,6 +60,10 @@ void EditorExportPlugin::add_shared_object(const String &p_path, const Vector<St
|
||||||
shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
|
shared_objects.push_back(SharedObject(p_path, p_tags, p_target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorExportPlugin::_add_shared_object(const SharedObject &p_shared_object) {
|
||||||
|
shared_objects.push_back(p_shared_object);
|
||||||
|
}
|
||||||
|
|
||||||
void EditorExportPlugin::add_ios_framework(const String &p_path) {
|
void EditorExportPlugin::add_ios_framework(const String &p_path) {
|
||||||
ios_frameworks.push_back(p_path);
|
ios_frameworks.push_back(p_path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@
|
||||||
#define EDITOR_EXPORT_PLUGIN_H
|
#define EDITOR_EXPORT_PLUGIN_H
|
||||||
|
|
||||||
#include "core/extension/gdextension.h"
|
#include "core/extension/gdextension.h"
|
||||||
|
#include "core/os/shared_object.h"
|
||||||
#include "editor_export_platform.h"
|
#include "editor_export_platform.h"
|
||||||
#include "editor_export_preset.h"
|
#include "editor_export_preset.h"
|
||||||
#include "editor_export_shared_object.h"
|
|
||||||
#include "scene/main/node.h"
|
#include "scene/main/node.h"
|
||||||
|
|
||||||
class EditorExportPlugin : public RefCounted {
|
class EditorExportPlugin : public RefCounted {
|
||||||
|
@ -94,6 +94,7 @@ protected:
|
||||||
|
|
||||||
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
|
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
|
||||||
void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
|
void add_shared_object(const String &p_path, const Vector<String> &tags, const String &p_target = String());
|
||||||
|
void _add_shared_object(const SharedObject &p_shared_object);
|
||||||
|
|
||||||
void add_ios_framework(const String &p_path);
|
void add_ios_framework(const String &p_path);
|
||||||
void add_ios_embedded_framework(const String &p_path);
|
void add_ios_embedded_framework(const String &p_path);
|
||||||
|
|
|
@ -129,34 +129,9 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
|
||||||
ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector)));
|
ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector)));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> dependencies;
|
Vector<SharedObject> dependencies_shared_objects = GDExtension::find_extension_dependencies(p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); });
|
||||||
if (config->has_section("dependencies")) {
|
for (const SharedObject &shared_object : dependencies_shared_objects) {
|
||||||
config->get_section_keys("dependencies", &dependencies);
|
_add_shared_object(shared_object);
|
||||||
}
|
|
||||||
|
|
||||||
for (const String &E : dependencies) {
|
|
||||||
Vector<String> dependency_tags = E.split(".");
|
|
||||||
bool all_tags_met = true;
|
|
||||||
for (int i = 0; i < dependency_tags.size(); i++) {
|
|
||||||
String tag = dependency_tags[i].strip_edges();
|
|
||||||
if (!p_features.has(tag)) {
|
|
||||||
all_tags_met = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_tags_met) {
|
|
||||||
Dictionary dependency = config->get_value("dependencies", E);
|
|
||||||
for (const Variant *key = dependency.next(nullptr); key; key = dependency.next(key)) {
|
|
||||||
String dependency_path = *key;
|
|
||||||
String target_path = dependency[*key];
|
|
||||||
if (dependency_path.is_relative_path()) {
|
|
||||||
dependency_path = p_path.get_base_dir().path_join(dependency_path);
|
|
||||||
}
|
|
||||||
add_shared_object(dependency_path, dependency_tags, target_path);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,39 @@ Vector<String> OS_Android::get_granted_permissions() const {
|
||||||
return godot_java->get_granted_permissions();
|
return godot_java->get_granted_permissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Android::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
bool OS_Android::copy_dynamic_library(const String &p_library_path, const String &p_target_dir, String *r_copy_path) {
|
||||||
|
if (!FileAccess::exists(p_library_path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<DirAccess> da_ref = DirAccess::create_for_path(p_library_path);
|
||||||
|
if (!da_ref.is_valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String copy_path = p_target_dir.path_join(p_library_path.get_file());
|
||||||
|
bool copy_exists = FileAccess::exists(copy_path);
|
||||||
|
if (copy_exists) {
|
||||||
|
print_verbose("Deleting existing library copy " + copy_path);
|
||||||
|
if (da_ref->remove(copy_path) != OK) {
|
||||||
|
print_verbose("Unable to delete " + copy_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_verbose("Copying " + p_library_path + " to " + p_target_dir);
|
||||||
|
Error create_dir_result = da_ref->make_dir_recursive(p_target_dir);
|
||||||
|
if (create_dir_result == OK || create_dir_result == ERR_ALREADY_EXISTS) {
|
||||||
|
copy_exists = da_ref->copy(p_library_path, copy_path) == OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_exists && r_copy_path != nullptr) {
|
||||||
|
*r_copy_path = copy_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy_exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error OS_Android::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
String path = p_path;
|
String path = p_path;
|
||||||
bool so_file_exists = true;
|
bool so_file_exists = true;
|
||||||
if (!FileAccess::exists(path)) {
|
if (!FileAccess::exists(path)) {
|
||||||
|
@ -172,24 +204,32 @@ Error OS_Android::open_dynamic_library(const String &p_path, void *&p_library_ha
|
||||||
|
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
if (!p_library_handle && so_file_exists) {
|
if (!p_library_handle && so_file_exists) {
|
||||||
// The library may be on the sdcard and thus inaccessible. Try to copy it to the internal
|
// The library (and its dependencies) may be on the sdcard and thus inaccessible.
|
||||||
// directory.
|
// Try to copy to the internal directory for access.
|
||||||
uint64_t so_modified_time = FileAccess::get_modified_time(p_path);
|
const String dynamic_library_path = get_dynamic_libraries_path();
|
||||||
String dynamic_library_path = get_dynamic_libraries_path().path_join(String::num_uint64(so_modified_time));
|
|
||||||
String internal_path = dynamic_library_path.path_join(p_path.get_file());
|
|
||||||
|
|
||||||
bool internal_so_file_exists = FileAccess::exists(internal_path);
|
if (p_data != nullptr && p_data->library_dependencies != nullptr && !p_data->library_dependencies->is_empty()) {
|
||||||
if (!internal_so_file_exists) {
|
// Copy the library dependencies
|
||||||
Ref<DirAccess> da_ref = DirAccess::create_for_path(p_path);
|
print_verbose("Copying library dependencies..");
|
||||||
if (da_ref.is_valid()) {
|
for (const String &library_dependency_path : *p_data->library_dependencies) {
|
||||||
Error create_dir_result = da_ref->make_dir_recursive(dynamic_library_path);
|
String internal_library_dependency_path;
|
||||||
if (create_dir_result == OK || create_dir_result == ERR_ALREADY_EXISTS) {
|
if (!copy_dynamic_library(library_dependency_path, dynamic_library_path.path_join(library_dependency_path.get_base_dir()), &internal_library_dependency_path)) {
|
||||||
internal_so_file_exists = da_ref->copy(path, internal_path) == OK;
|
ERR_PRINT(vformat("Unable to copy library dependency %s", library_dependency_path));
|
||||||
|
} else {
|
||||||
|
void *lib_dependency_handle = dlopen(internal_library_dependency_path.utf8().get_data(), RTLD_NOW);
|
||||||
|
if (!lib_dependency_handle) {
|
||||||
|
ERR_PRINT(vformat("Can't open dynamic library dependency: %s. Error: %s.", internal_library_dependency_path, dlerror()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String internal_path;
|
||||||
|
print_verbose("Copying library " + p_path);
|
||||||
|
const bool internal_so_file_exists = copy_dynamic_library(p_path, dynamic_library_path.path_join(p_path.get_base_dir()), &internal_path);
|
||||||
|
|
||||||
if (internal_so_file_exists) {
|
if (internal_so_file_exists) {
|
||||||
|
print_verbose("Opening library " + internal_path);
|
||||||
p_library_handle = dlopen(internal_path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(internal_path.utf8().get_data(), RTLD_NOW);
|
||||||
if (p_library_handle) {
|
if (p_library_handle) {
|
||||||
path = internal_path;
|
path = internal_path;
|
||||||
|
@ -199,8 +239,8 @@ Error OS_Android::open_dynamic_library(const String &p_path, void *&p_library_ha
|
||||||
|
|
||||||
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title) override;
|
virtual void alert(const String &p_alert, const String &p_title) override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
|
|
||||||
virtual String get_name() const override;
|
virtual String get_name() const override;
|
||||||
virtual String get_distribution_name() const override;
|
virtual String get_distribution_name() const override;
|
||||||
|
@ -178,6 +178,8 @@ public:
|
||||||
private:
|
private:
|
||||||
// Location where we relocate external dynamic libraries to make them accessible.
|
// Location where we relocate external dynamic libraries to make them accessible.
|
||||||
String get_dynamic_libraries_path() const;
|
String get_dynamic_libraries_path() const;
|
||||||
|
// Copy a dynamic library to the given location to make it accessible for loading.
|
||||||
|
bool copy_dynamic_library(const String &p_library_path, const String &p_target_dir, String *r_copy_path = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OS_ANDROID_H
|
#endif // OS_ANDROID_H
|
||||||
|
|
|
@ -103,7 +103,7 @@ public:
|
||||||
virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
|
virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
|
||||||
virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
|
virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
|
@ -217,13 +217,13 @@ _FORCE_INLINE_ String OS_IOS::get_framework_executable(const String &p_path) {
|
||||||
return p_path;
|
return p_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_IOS::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
Error OS_IOS::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
if (p_path.length() == 0) {
|
if (p_path.length() == 0) {
|
||||||
// Static xcframework.
|
// Static xcframework.
|
||||||
p_library_handle = RTLD_SELF;
|
p_library_handle = RTLD_SELF;
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = p_path;
|
*p_data->r_resolved_path = p_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -256,8 +256,8 @@ Error OS_IOS::open_dynamic_library(const String &p_path, void *&p_library_handle
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -85,7 +85,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
|
|
||||||
virtual MainLoop *get_main_loop() const override;
|
virtual MainLoop *get_main_loop() const override;
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ _FORCE_INLINE_ String OS_MacOS::get_framework_executable(const String &p_path) {
|
||||||
return p_path;
|
return p_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_MacOS::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
Error OS_MacOS::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
String path = get_framework_executable(p_path);
|
String path = get_framework_executable(p_path);
|
||||||
|
|
||||||
if (!FileAccess::exists(path)) {
|
if (!FileAccess::exists(path)) {
|
||||||
|
@ -235,8 +235,8 @@ Error OS_MacOS::open_dynamic_library(const String &p_path, void *&p_library_hand
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -247,13 +247,13 @@ bool OS_Web::is_userfs_persistent() const {
|
||||||
return idb_available;
|
return idb_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Web::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
Error OS_Web::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
String path = p_path.get_file();
|
String path = p_path.get_file();
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
@ -109,7 +109,7 @@ public:
|
||||||
|
|
||||||
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
|
|
||||||
void resume_audio();
|
void resume_audio();
|
||||||
|
|
||||||
|
|
|
@ -359,7 +359,7 @@ void debug_dynamic_library_check_dependencies(const String &p_root_path, const S
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path, bool p_generate_temp_files) {
|
Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data) {
|
||||||
String path = p_path.replace("/", "\\");
|
String path = p_path.replace("/", "\\");
|
||||||
|
|
||||||
if (!FileAccess::exists(path)) {
|
if (!FileAccess::exists(path)) {
|
||||||
|
@ -371,7 +371,7 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
|
||||||
|
|
||||||
// Here we want a copy to be loaded.
|
// Here we want a copy to be loaded.
|
||||||
// This is so the original file isn't locked and can be updated by a compiler.
|
// This is so the original file isn't locked and can be updated by a compiler.
|
||||||
if (p_generate_temp_files) {
|
if (p_data != nullptr && p_data->generate_temp_files) {
|
||||||
// Copy the file to the same directory as the original with a prefix in the name.
|
// Copy the file to the same directory as the original with a prefix in the name.
|
||||||
// This is so relative path to dependencies are satisfied.
|
// This is so relative path to dependencies are satisfied.
|
||||||
String copy_path = path.get_base_dir().path_join("~" + path.get_file());
|
String copy_path = path.get_base_dir().path_join("~" + path.get_file());
|
||||||
|
@ -407,13 +407,13 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
|
||||||
bool has_dll_directory_api = ((add_dll_directory != nullptr) && (remove_dll_directory != nullptr));
|
bool has_dll_directory_api = ((add_dll_directory != nullptr) && (remove_dll_directory != nullptr));
|
||||||
DLL_DIRECTORY_COOKIE cookie = nullptr;
|
DLL_DIRECTORY_COOKIE cookie = nullptr;
|
||||||
|
|
||||||
if (p_also_set_library_path && has_dll_directory_api) {
|
if (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) {
|
||||||
cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data()));
|
cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
|
p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
|
||||||
if (!p_library_handle) {
|
if (!p_library_handle) {
|
||||||
if (p_generate_temp_files) {
|
if (p_data != nullptr && p_data->generate_temp_files) {
|
||||||
DirAccess::remove_absolute(path);
|
DirAccess::remove_absolute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,11 +446,11 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
|
||||||
remove_dll_directory(cookie);
|
remove_dll_directory(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_resolved_path != nullptr) {
|
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {
|
||||||
*r_resolved_path = path;
|
*p_data->r_resolved_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_generate_temp_files) {
|
if (p_data != nullptr && p_data->generate_temp_files) {
|
||||||
temp_libraries[p_library_handle] = path;
|
temp_libraries[p_library_handle] = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,7 @@ public:
|
||||||
|
|
||||||
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr, bool p_generate_temp_files = false) override;
|
virtual Error open_dynamic_library(const String &p_path, void *&p_library_handle, GDExtensionData *p_data = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String &p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue