Merge pull request #11783 from endragor/ios-export-frameworks
Allow exporting third-party iOS Frameworks
This commit is contained in:
commit
71a3e71b61
32 changed files with 935 additions and 230 deletions
|
|
@ -123,7 +123,7 @@ bool GDNative::initialize() {
|
|||
return false;
|
||||
}
|
||||
#ifdef IPHONE_ENABLED
|
||||
String path = lib_path.replace("res://", "dylibs/");
|
||||
String path = "";
|
||||
#else
|
||||
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
|
||||
#endif
|
||||
|
|
@ -148,7 +148,7 @@ bool GDNative::initialize() {
|
|||
// we cheat here a little bit. you saw nothing
|
||||
initialized = true;
|
||||
|
||||
err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init);
|
||||
err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init, false);
|
||||
|
||||
initialized = false;
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced
|
|||
return *(Variant *)&result;
|
||||
}
|
||||
|
||||
Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) {
|
||||
Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) {
|
||||
|
||||
if (!initialized) {
|
||||
ERR_PRINT("No valid library handle, can't get symbol from GDNative object");
|
||||
|
|
@ -291,7 +291,7 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) {
|
|||
native_handle,
|
||||
p_procedure_name,
|
||||
r_handle,
|
||||
true);
|
||||
p_optional);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ public:
|
|||
|
||||
Variant call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments = Array());
|
||||
|
||||
Error get_symbol(StringName p_procedure_name, void *&r_handle);
|
||||
Error get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional = true);
|
||||
};
|
||||
|
||||
class GDNativeLibraryResourceLoader : public ResourceFormatLoader {
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ protected:
|
|||
virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
|
||||
};
|
||||
|
||||
struct LibrarySymbol {
|
||||
char *name;
|
||||
bool is_required;
|
||||
};
|
||||
|
||||
void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
|
||||
if (p_type != "GDNativeLibrary") {
|
||||
return;
|
||||
|
|
@ -136,7 +141,6 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
|
|||
|
||||
Ref<ConfigFile> config = lib->get_config_file();
|
||||
|
||||
String entry_lib_path;
|
||||
{
|
||||
|
||||
List<String> entry_keys;
|
||||
|
|
@ -161,14 +165,12 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
|
|||
continue;
|
||||
}
|
||||
|
||||
entry_lib_path = config->get_value("entry", key);
|
||||
break;
|
||||
String entry_lib_path = config->get_value("entry", key);
|
||||
add_shared_object(entry_lib_path, tags);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<String> dependency_paths;
|
||||
{
|
||||
|
||||
List<String> dependency_keys;
|
||||
config->get_section_keys("dependencies", &dependency_keys);
|
||||
|
||||
|
|
@ -191,47 +193,54 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
|
|||
continue;
|
||||
}
|
||||
|
||||
dependency_paths = config->get_value("dependencies", key);
|
||||
break;
|
||||
Vector<String> dependency_paths = config->get_value("dependencies", key);
|
||||
for (int i = 0; i < dependency_paths.size(); i++) {
|
||||
add_shared_object(dependency_paths[i], tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_statically_linked = false;
|
||||
{
|
||||
if (p_features.has("iOS")) {
|
||||
// Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS.
|
||||
LibrarySymbol expected_symbols[] = {
|
||||
{ "gdnative_init", true },
|
||||
{ "gdnative_terminate", false },
|
||||
{ "nativescript_init", false },
|
||||
{ "nativescript_frame", false },
|
||||
{ "nativescript_thread_enter", false },
|
||||
{ "nativescript_thread_exit", false },
|
||||
{ "gdnative_singleton", false }
|
||||
};
|
||||
String declare_pattern = "extern \"C\" void $name(void)$weak;\n";
|
||||
String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"
|
||||
"extern void add_ios_init_callback(void (*cb)());\n";
|
||||
String linker_flags = "";
|
||||
for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
|
||||
String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
|
||||
String code = declare_pattern.replace("$name", full_name);
|
||||
code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))");
|
||||
additional_code += code;
|
||||
|
||||
List<String> static_linking_keys;
|
||||
config->get_section_keys("static_linking", &static_linking_keys);
|
||||
|
||||
for (List<String>::Element *E = static_linking_keys.front(); E; E = E->next()) {
|
||||
String key = E->get();
|
||||
|
||||
Vector<String> tags = key.split(".");
|
||||
|
||||
bool skip = false;
|
||||
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
bool has_feature = p_features.has(tags[i]);
|
||||
|
||||
if (!has_feature) {
|
||||
skip = true;
|
||||
break;
|
||||
if (!expected_symbols[i].is_required) {
|
||||
if (linker_flags.length() > 0) {
|
||||
linker_flags += " ";
|
||||
}
|
||||
linker_flags += "-Wl,-U,_" + full_name;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
is_statically_linked = config->get_value("static_linking", key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_statically_linked)
|
||||
add_shared_object(entry_lib_path);
|
||||
additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix());
|
||||
String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n";
|
||||
for (int i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) {
|
||||
String full_name = lib->get_symbol_prefix() + expected_symbols[i].name;
|
||||
additional_code += register_pattern.replace("$name", full_name);
|
||||
}
|
||||
additional_code += "}\n";
|
||||
additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix());
|
||||
additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix());
|
||||
|
||||
for (int i = 0; i < dependency_paths.size(); i++) {
|
||||
add_shared_object(dependency_paths[i]);
|
||||
add_ios_cpp_code(additional_code);
|
||||
add_ios_linker_flags(linker_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,9 +280,7 @@ void register_gdnative_types() {
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
EditorNode::add_init_callback(editor_init_callback);
|
||||
}
|
||||
EditorNode::add_init_callback(editor_init_callback);
|
||||
#endif
|
||||
|
||||
ClassDB::register_class<GDNativeLibrary>();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
def can_build(platform):
|
||||
return True
|
||||
return platform != 'iphone'
|
||||
|
||||
def configure(env):
|
||||
pass
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue