Merge pull request #11783 from endragor/ios-export-frameworks

Allow exporting third-party iOS Frameworks
This commit is contained in:
Rémi Verschelde 2017-11-20 22:56:15 +01:00 committed by GitHub
commit 71a3e71b61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 935 additions and 230 deletions

View file

@ -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;
}

View file

@ -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 {

View file

@ -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>();

View file

@ -1,5 +1,5 @@
def can_build(platform):
return True
return platform != 'iphone'
def configure(env):
pass