diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 35e4443f2a..6d4b46f4da 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -98,6 +98,7 @@ static Error _erase_recursive(DirAccess *da) { err = _erase_recursive(da); if (err) { print_line("err recurso " + E->get()); + da->change_dir(".."); return err; } err = da->change_dir(".."); @@ -340,6 +341,102 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) { return err; } +// Changes dir for the current scope, returning back to the original dir +// when scope exits +class DirChanger { + DirAccess *da; + String original_dir; + +public: + DirChanger(DirAccess *p_da, String p_dir) { + da = p_da; + original_dir = p_da->get_current_dir(); + p_da->change_dir(p_dir); + } + + ~DirChanger() { + da->change_dir(original_dir); + } +}; + +Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) { + List dirs; + + String curdir = get_current_dir(); + list_dir_begin(); + String n = get_next(); + while (n != String()) { + + if (n != "." && n != "..") { + + if (current_is_dir()) + dirs.push_back(n); + else { + String rel_path = n; + if (!n.is_rel_path()) { + list_dir_end(); + return ERR_BUG; + } + Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags); + if (err) { + list_dir_end(); + return err; + } + } + } + + n = get_next(); + } + + list_dir_end(); + + for (List::Element *E = dirs.front(); E; E = E->next()) { + String rel_path = E->get(); + String target_dir = p_to + rel_path; + if (!p_target_da->dir_exists(target_dir)) { + Error err = p_target_da->make_dir(target_dir); + ERR_FAIL_COND_V(err, err); + } + + Error err = change_dir(E->get()); + ERR_FAIL_COND_V(err, err); + err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags); + if (err) { + change_dir(".."); + ERR_PRINT("Failed to copy recursively"); + return err; + } + err = change_dir(".."); + if (err) { + ERR_PRINT("Failed to go back"); + return err; + } + } + + return OK; +} + +Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) { + ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND); + + DirAccess *target_da = DirAccess::create_for_path(p_to); + ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE); + + if (!target_da->dir_exists(p_to)) { + Error err = target_da->make_dir_recursive(p_to); + if (err) { + memdelete(target_da); + } + ERR_FAIL_COND_V(err, err); + } + + DirChanger dir_changer(this, p_from); + Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags); + memdelete(target_da); + + return err; +} + bool DirAccess::exists(String p_dir) { DirAccess *da = DirAccess::create_for_path(p_dir); diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 7fa3ce5cf1..f3d1320041 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -52,6 +52,9 @@ public: private: AccessType _access_type; static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object + + Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags); + protected: String _get_root_path() const; String _get_root_string() const; @@ -89,6 +92,7 @@ public: static bool exists(String p_dir); virtual size_t get_space_left() = 0; + Error copy_dir(String p_from, String p_to, int chmod_flags = -1); virtual Error copy(String p_from, String p_to, int chmod_flags = -1); virtual Error rename(String p_from, String p_to) = 0; virtual Error remove(String p_name) = 0; diff --git a/core/os/os.cpp b/core/os/os.cpp index 65d0b2e05d..dd71f8a9c6 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -548,6 +548,33 @@ bool OS::has_feature(const String &p_feature) { if (sizeof(void *) == 4 && p_feature == "32") { return true; } +#if defined(__x86_64) || defined(__x86_64__) + if (p_feature == "x86_64") { + return true; + } +#elif (defined(__i386) || defined(__i386__)) + if (p_feature == "x86") { + return true; + } +#elif defined(__aarch64__) + if (p_feature == "arm64") { + return true; + } +#elif defined(__arm__) +#if defined(__ARM_ARCH_7A__) + if (p_feature == "armv7a" || p_feature == "armv7") { + return true; + } +#endif +#if defined(__ARM_ARCH_7S__) + if (p_feature == "armv7s" || p_feature == "armv7") { + return true; + } +#endif + if (p_feature == "arm") { + return true; + } +#endif if (_check_internal_feature_support(p_feature)) return true; diff --git a/core/ustring.cpp b/core/ustring.cpp index 7c3a784c5b..8d40f56386 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -862,6 +862,17 @@ Vector String::split_ints_mk(const Vector &p_splitters, bool p_allo return ret; } +String String::join(Vector parts) { + String ret; + for (int i = 0; i < parts.size(); ++i) { + if (i > 0) { + ret += *this; + } + ret += parts[i]; + } + return ret; +} + CharType String::char_uppercase(CharType p_char) { return _find_upper(p_char); diff --git a/core/ustring.h b/core/ustring.h index 353c8e6c1d..9c24133b55 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -169,6 +169,8 @@ public: Vector split_ints(const String &p_splitter, bool p_allow_empty = true) const; Vector split_ints_mk(const Vector &p_splitters, bool p_allow_empty = true) const; + String join(Vector parts); + static CharType char_uppercase(CharType p_char); static CharType char_lowercase(CharType p_char); String to_upper() const; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 519bc33d42..8c8d9c4c79 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -470,9 +470,52 @@ void EditorExportPlugin::add_file(const String &p_path, const Vector &p extra_files.push_back(ef); } -void EditorExportPlugin::add_shared_object(const String &p_path) { +void EditorExportPlugin::add_shared_object(const String &p_path, const Vector &tags) { - shared_objects.push_back(p_path); + shared_objects.push_back(SharedObject(p_path, tags)); +} + +void EditorExportPlugin::add_ios_framework(const String &p_path) { + ios_frameworks.push_back(p_path); +} + +Vector EditorExportPlugin::get_ios_frameworks() const { + return ios_frameworks; +} + +void EditorExportPlugin::add_ios_plist_content(const String &p_plist_content) { + ios_plist_content += p_plist_content + "\n"; +} + +String EditorExportPlugin::get_ios_plist_content() const { + return ios_plist_content; +} + +void EditorExportPlugin::add_ios_linker_flags(const String &p_flags) { + if (ios_linker_flags.length() > 0) { + ios_linker_flags += ' '; + } + ios_linker_flags += p_flags; +} + +String EditorExportPlugin::get_ios_linker_flags() const { + return ios_linker_flags; +} + +void EditorExportPlugin::add_ios_bundle_file(const String &p_path) { + ios_bundle_files.push_back(p_path); +} + +Vector EditorExportPlugin::get_ios_bundle_files() const { + return ios_bundle_files; +} + +void EditorExportPlugin::add_ios_cpp_code(const String &p_code) { + ios_cpp_code += p_code; +} + +String EditorExportPlugin::get_ios_cpp_code() const { + return ios_cpp_code; } void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const PoolVector &p_features) { @@ -482,17 +525,17 @@ void EditorExportPlugin::_export_file_script(const String &p_path, const String } } -void EditorExportPlugin::_export_begin_script(const PoolVector &p_features) { +void EditorExportPlugin::_export_begin_script(const PoolVector &p_features, bool p_debug, const String &p_path, int p_flags) { if (get_script_instance()) { - get_script_instance()->call("_export_begin", p_features); + get_script_instance()->call("_export_begin", p_features, p_debug, p_path, p_flags); } } void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const Set &p_features) { } -void EditorExportPlugin::_export_begin(const Set &p_features) { +void EditorExportPlugin::_export_begin(const Set &p_features, bool p_debug, const String &p_path, int p_flags) { } void EditorExportPlugin::skip() { @@ -502,33 +545,58 @@ void EditorExportPlugin::skip() { void EditorExportPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_shared_object", "path"), &EditorExportPlugin::add_shared_object); + ClassDB::bind_method(D_METHOD("add_shared_object", "path", "tags"), &EditorExportPlugin::add_shared_object); ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); + ClassDB::bind_method(D_METHOD("add_ios_framework", "path"), &EditorExportPlugin::add_ios_framework); + ClassDB::bind_method(D_METHOD("add_ios_plist_content", "plist_content"), &EditorExportPlugin::add_ios_plist_content); + ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags); + ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file); + ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code); ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); BIND_VMETHOD(MethodInfo("_export_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "type"), PropertyInfo(Variant::POOL_STRING_ARRAY, "features"))); - BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"))); + BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"), PropertyInfo(Variant::BOOL, "is_debug"), PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "flags"))); } EditorExportPlugin::EditorExportPlugin() { skipped = false; } -Error EditorExportPlatform::export_project_files(const Ref &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { - +EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref &p_preset) { Ref platform = p_preset->get_platform(); List feature_list; + platform->get_platform_features(&feature_list); platform->get_preset_features(p_preset, &feature_list); - //figure out features - Set features; - PoolVector features_pv; + + FeatureContainers result; for (List::Element *E = feature_list.front(); E; E = E->next()) { - features.insert(E->get()); - features_pv.push_back(E->get()); + result.features.insert(E->get()); + result.features_pv.push_back(E->get()); } + return result; +} +EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_platform, const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + FeatureContainers features = p_platform.get_feature_containers(p_preset); Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + //initial export plugin callback + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->get_script_instance()) { //script based + export_plugins[i]->_export_begin_script(features.features_pv, p_debug, p_path, p_flags); + } else { + export_plugins[i]->_export_begin(features.features, p_debug, p_path, p_flags); + } + } +} +EditorExportPlatform::ExportNotifier::~ExportNotifier() { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + export_plugins[i]->_export_end(); + } +} + +Error EditorExportPlatform::export_project_files(const Ref &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { //figure out paths of files that will be exported Set paths; Vector path_remaps; @@ -551,13 +619,8 @@ Error EditorExportPlatform::export_project_files(const Ref & _edit_filter_list(paths, p_preset->get_include_filter(), false); _edit_filter_list(paths, p_preset->get_exclude_filter(), true); - //initial export plugin callback + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { - if (export_plugins[i]->get_script_instance()) { //script based - export_plugins[i]->_export_begin_script(features_pv); - } else { - export_plugins[i]->_export_begin(features); - } if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { p_so_func(p_udata, export_plugins[i]->shared_objects[j]); @@ -570,6 +633,10 @@ Error EditorExportPlatform::export_project_files(const Ref & export_plugins[i]->_clear(); } + FeatureContainers feature_containers = get_feature_containers(p_preset); + Set &features = feature_containers.features; + PoolVector &features_pv = feature_containers.features_pv; + //store everything in the export medium int idx = 0; int total = paths.size(); @@ -686,7 +753,16 @@ Error EditorExportPlatform::export_project_files(const Ref & return OK; } -Error EditorExportPlatform::save_pack(const Ref &p_preset, const String &p_path) { +Error EditorExportPlatform::_add_shared_object(void *p_userdata, const SharedObject &p_so) { + PackData *pack_data = (PackData *)p_userdata; + if (pack_data->so_files) { + pack_data->so_files->push_back(p_so); + } + + return OK; +} + +Error EditorExportPlatform::save_pack(const Ref &p_preset, const String &p_path, Vector *p_so_files) { EditorProgress ep("savepack", TTR("Packing"), 102); @@ -697,8 +773,9 @@ Error EditorExportPlatform::save_pack(const Ref &p_preset, c PackData pd; pd.ep = &ep; pd.f = ftmp; + pd.so_files = p_so_files; - Error err = export_project_files(p_preset, _save_pack_file, &pd); + Error err = export_project_files(p_preset, _save_pack_file, &pd, _add_shared_object); memdelete(ftmp); //close tmp file @@ -1203,6 +1280,7 @@ String EditorExportPlatformPC::get_binary_extension() const { } Error EditorExportPlatformPC::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); String custom_debug = p_preset->get("custom_template/debug"); String custom_release = p_preset->get("custom_template/release"); diff --git a/editor/editor_export.h b/editor/editor_export.h index 50379b9683..346c3b58e1 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -118,13 +118,24 @@ public: EditorExportPreset(); }; +struct SharedObject { + String path; + Vector tags; + + SharedObject(const String &p_path, const Vector &p_tags) + : path(p_path), tags(p_tags) { + } + + SharedObject() {} +}; + class EditorExportPlatform : public Reference { GDCLASS(EditorExportPlatform, Reference) public: typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const String &p_path); + typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so); private: struct SavedData { @@ -144,6 +155,7 @@ private: FileAccess *f; Vector file_ofs; EditorProgress *ep; + Vector *so_files; }; struct ZipData { @@ -152,6 +164,11 @@ private: EditorProgress *ep; }; + struct FeatureContainers { + Set features; + PoolVector features_pv; + }; + void _export_find_resources(EditorFileSystemDirectory *p_dir, Set &p_paths); void _export_find_dependencies(const String &p_path, Set &p_paths); @@ -162,7 +179,16 @@ private: void _edit_files_with_filter(DirAccess *da, const Vector &p_filters, Set &r_list, bool exclude); void _edit_filter_list(Set &r_list, const String &p_filter, bool exclude); + static Error _add_shared_object(void *p_userdata, const SharedObject &p_so); + protected: + struct ExportNotifier { + ExportNotifier(EditorExportPlatform &p_platform, const Ref &p_preset, bool p_debug, const String &p_path, int p_flags); + ~ExportNotifier(); + }; + + FeatureContainers get_feature_containers(const Ref &p_preset); + bool exists_export_template(String template_file_name, String *err) const; String find_export_template(String template_file_name, String *err = NULL) const; void gen_export_flags(Vector &r_flags, int p_flags); @@ -192,7 +218,7 @@ public: Error export_project_files(const Ref &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = NULL); - Error save_pack(const Ref &p_preset, const String &p_path); + Error save_pack(const Ref &p_preset, const String &p_path, Vector *p_so_files = NULL); Error save_zip(const Ref &p_preset, const String &p_path); virtual bool poll_devices() { return false; } @@ -225,7 +251,7 @@ class EditorExportPlugin : public Reference { friend class EditorExportPlatform; - Vector shared_objects; + Vector shared_objects; struct ExtraFile { String path; Vector data; @@ -234,26 +260,53 @@ class EditorExportPlugin : public Reference { Vector extra_files; bool skipped; + Vector ios_frameworks; + String ios_plist_content; + String ios_linker_flags; + Vector ios_bundle_files; + String ios_cpp_code; + _FORCE_INLINE_ void _clear() { shared_objects.clear(); extra_files.clear(); skipped = false; } + _FORCE_INLINE_ void _export_end() { + ios_frameworks.clear(); + ios_bundle_files.clear(); + ios_plist_content = ""; + ios_linker_flags = ""; + ios_cpp_code = ""; + } + void _export_file_script(const String &p_path, const String &p_type, const PoolVector &p_features); - void _export_begin_script(const PoolVector &p_features); + void _export_begin_script(const PoolVector &p_features, bool p_debug, const String &p_path, int p_flags); protected: void add_file(const String &p_path, const Vector &p_file, bool p_remap); - void add_shared_object(const String &p_path); + void add_shared_object(const String &p_path, const Vector &tags); + + void add_ios_framework(const String &p_path); + void add_ios_plist_content(const String &p_plist_content); + void add_ios_linker_flags(const String &p_flags); + void add_ios_bundle_file(const String &p_path); + void add_ios_cpp_code(const String &p_code); + void skip(); virtual void _export_file(const String &p_path, const String &p_type, const Set &p_features); - virtual void _export_begin(const Set &p_features); + virtual void _export_begin(const Set &p_features, bool p_debug, const String &p_path, int p_flags); static void _bind_methods(); public: + Vector get_ios_frameworks() const; + String get_ios_plist_content() const; + String get_ios_linker_flags() const; + Vector get_ios_bundle_files() const; + String get_ios_cpp_code() const; + EditorExportPlugin(); }; diff --git a/misc/dist/ios_xcode/godot.iphone.debug.fat b/misc/dist/ios_xcode/godot.iphone.debug.fat deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm b/misc/dist/ios_xcode/godot.iphone.release.arm deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm64 b/misc/dist/ios_xcode/godot.iphone.release.arm64 deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/misc/dist/ios_xcode/godot.iphone.release.fat b/misc/dist/ios_xcode/godot.iphone.release.fat deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 3f2db94193..ab15e35f63 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -8,8 +8,20 @@ /* Begin PBXBuildFile section */ 1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; }; + 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */; }; + 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926951FBBF7C400F53A6F /* Security.framework */; }; + 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */; }; + 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */; }; + 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926921FBBF7A000F53A6F /* GameController.framework */; }; + 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926911FBBF79500F53A6F /* CoreMotion.framework */; }; + 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */; }; + 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */; }; + 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; }; + DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; }; + 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; }; 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; }; 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; }; + 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1881F584E7600A41E41 /* StoreKit.framework */; }; D07CD43F1C5D573600B7FB28 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */; }; D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */; }; D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */; }; @@ -26,14 +38,25 @@ D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; }; D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; }; D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; }; - D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* $binary.iphone */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = dylibs; sourceTree = ""; }; + 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = ""; }; + 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + 1FE926911FBBF79500F53A6F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; + 1FE926921FBBF7A000F53A6F /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; + 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; + 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 1FE926951FBBF7C400F53A6F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = ""; }; 1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; 1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = $binary.entitlements; sourceTree = ""; }; + 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = ""; }; D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = ""; }; D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-736h@3x.png"; sourceTree = ""; }; @@ -51,24 +74,35 @@ D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = ""; }; D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "$binary-Prefix.pch"; sourceTree = ""; }; - D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = $binary.pck; sourceTree = ""; }; - D0BCFE7918AEC06A004A7AAE /* $binary.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = $binary.iphone; sourceTree = ""; }; /* End PBXFileReference section */ + $additional_pbx_files + /* Begin PBXFrameworksBuildPhase section */ D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */, + 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */, + 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */, + 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */, + 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */, + 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */, + 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */, + 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */, + 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */, + 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */, D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */, 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */, - D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */, + 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */, D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */, 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */, D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */, D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */, + DEADBEEF2F582BE20003B888 /* $binary.a */, + $additional_pbx_frameworks_build ); runOnlyForDeploymentPostprocessing = 0; }; @@ -79,11 +113,11 @@ isa = PBXGroup; children = ( 1F1575711F582BE20003B888 /* dylibs */, - D0BCFE7918AEC06A004A7AAE /* $binary.iphone */, D0BCFE7718AEBFEB004A7AAE /* $binary.pck */, D0BCFE4118AEBDA2004A7AAE /* $binary */, D0BCFE3618AEBDA2004A7AAE /* Frameworks */, D0BCFE3518AEBDA2004A7AAE /* Products */, + $additional_pbx_resources_refs ); sourceTree = ""; }; @@ -98,14 +132,25 @@ D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = { isa = PBXGroup; children = ( + 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */, + 1FE926951FBBF7C400F53A6F /* Security.framework */, + 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */, + 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */, + 1FE926921FBBF7A000F53A6F /* GameController.framework */, + 1FE926911FBBF79500F53A6F /* CoreMotion.framework */, + 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */, + 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */, + 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */, 1FF4C1861F584E5600A41E41 /* StoreKit.framework */, 1FF4C1841F584E3F00A41E41 /* GameKit.framework */, + 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */, D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */, D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */, D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */, D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */, D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */, - D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */, + DEADBEEF1F582BE20003B888 /* $binary.a */, + $additional_pbx_frameworks_refs ); name = Frameworks; sourceTree = ""; @@ -124,6 +169,7 @@ D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */, D07CD44D1C5D589C00B7FB28 /* Images.xcassets */, D0BCFE4218AEBDA2004A7AAE /* Supporting Files */, + 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */, ); path = $binary; sourceTree = ""; @@ -133,7 +179,6 @@ children = ( D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */, D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */, - D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; @@ -218,7 +263,7 @@ D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */, D07CD4481C5D573600B7FB28 /* Default-Portrait-1366h@2x.png in Resources */, D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */, - D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */, + $additional_pbx_resources_build ); runOnlyForDeploymentPostprocessing = 0; }; @@ -229,6 +274,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -250,7 +296,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + ARCHS = "$godot_archs"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -265,6 +311,8 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; COPY_PHASE_STRIP = NO; + ENABLE_BITCODE = NO; + "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -280,7 +328,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; - ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "$linker_flags"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -290,7 +338,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + ARCHS = "$godot_archs"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -306,6 +354,8 @@ CODE_SIGN_IDENTITY = "$code_sign_identity_release"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; COPY_PHASE_STRIP = YES; + ENABLE_BITCODE = NO; + "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -315,6 +365,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; + OTHER_LDFLAGS = "$linker_flags"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -324,26 +375,23 @@ D0BCFE7218AEBDA3004A7AAE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; + ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements; CODE_SIGN_IDENTITY = "$code_sign_identity_debug"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch"; INFOPLIST_FILE = "$binary/$binary-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/dylibs", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug"; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "armv7 armv7s"; + VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64"; WRAPPER_EXTENSION = app; }; name = Debug; @@ -351,26 +399,23 @@ D0BCFE7318AEBDA3004A7AAE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; + ARCHS = "$godot_archs"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements; CODE_SIGN_IDENTITY = "$code_sign_identity_release"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; DEVELOPMENT_TEAM = $team_id; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch"; INFOPLIST_FILE = "$binary/$binary-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/dylibs", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "$provisioning_profile_uuid_release"; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = "armv7 armv7s"; + VALID_ARCHS = "armv7 armv7s arm64 i386 x86_64"; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/misc/dist/ios_xcode/godot_ios/dummy.cpp b/misc/dist/ios_xcode/godot_ios/dummy.cpp new file mode 100644 index 0000000000..78ec87fc10 --- /dev/null +++ b/misc/dist/ios_xcode/godot_ios/dummy.cpp @@ -0,0 +1 @@ +$cpp_code \ No newline at end of file diff --git a/misc/dist/ios_xcode/godot_ios/dylibs/empty b/misc/dist/ios_xcode/godot_ios/dylibs/empty new file mode 100644 index 0000000000..4b5614362b --- /dev/null +++ b/misc/dist/ios_xcode/godot_ios/dylibs/empty @@ -0,0 +1 @@ +Dummy file to make dylibs folder exported \ No newline at end of file diff --git a/misc/dist/ios_xcode/export_options.plist b/misc/dist/ios_xcode/godot_ios/export_options.plist similarity index 61% rename from misc/dist/ios_xcode/export_options.plist rename to misc/dist/ios_xcode/godot_ios/export_options.plist index 86d89a6e42..3878a4dbe6 100644 --- a/misc/dist/ios_xcode/export_options.plist +++ b/misc/dist/ios_xcode/godot_ios/export_options.plist @@ -4,7 +4,17 @@ method $export_method + teamID $team_id + + provisioningProfiles + + $identifier + $provisioning_profile_uuid + + + compileBitcode + \ No newline at end of file diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist index 1531a41bd0..70932c1943 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist +++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist @@ -7,7 +7,7 @@ CFBundleDisplayName $name CFBundleExecutable - $binary.iphone + $binary CFBundleIcons CFBundleIcons~ipad @@ -47,5 +47,6 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + $additional_plist_content diff --git a/misc/dist/ios_xcode/godot_ios/main.m b/misc/dist/ios_xcode/godot_ios/main.m deleted file mode 100644 index bb63364d8f..0000000000 --- a/misc/dist/ios_xcode/godot_ios/main.m +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* main.m */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#import - -#import "AppDelegate.h" - -int main(int argc, char *argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm b/misc/dist/ios_xcode/libgodot.iphone.debug.fat.a old mode 100755 new mode 100644 similarity index 100% rename from misc/dist/ios_xcode/godot.iphone.debug.arm rename to misc/dist/ios_xcode/libgodot.iphone.debug.fat.a diff --git a/misc/dist/ios_xcode/godot.iphone.debug.arm64 b/misc/dist/ios_xcode/libgodot.iphone.release.fat.a old mode 100755 new mode 100644 similarity index 100% rename from misc/dist/ios_xcode/godot.iphone.debug.arm64 rename to misc/dist/ios_xcode/libgodot.iphone.release.fat.a diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index f98a16a5d7..de118043ca 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -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; } diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 052ce1fef1..bb260bdd1b 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -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 { diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 8af643df50..34099bf528 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -123,6 +123,11 @@ protected: virtual void _export_file(const String &p_path, const String &p_type, const Set &p_features); }; +struct LibrarySymbol { + char *name; + bool is_required; +}; + void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_type, const Set &p_features) { if (p_type != "GDNativeLibrary") { return; @@ -136,7 +141,6 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty Ref config = lib->get_config_file(); - String entry_lib_path; { List 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 dependency_paths; { - List 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 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 static_linking_keys; - config->get_section_keys("static_linking", &static_linking_keys); - - for (List::Element *E = static_linking_keys.front(); E; E = E->next()) { - String key = E->get(); - - Vector 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(); diff --git a/modules/webm/config.py b/modules/webm/config.py index 0374bb36f7..dcae4447d5 100644 --- a/modules/webm/config.py +++ b/modules/webm/config.py @@ -1,5 +1,5 @@ def can_build(platform): - return True + return platform != 'iphone' def configure(env): pass diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index d5ccf76631..b2c8799540 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -705,7 +705,24 @@ String OS_Android::get_joy_guid(int p_device) const { } bool OS_Android::_check_internal_feature_support(const String &p_feature) { - return p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2"; //TODO support etc2 only if GLES3 driver is selected + if (p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2") { + //TODO support etc2 only if GLES3 driver is selected + return true; + } +#if defined(__aarch64__) + if (p_feature == "arm64-v8a") { + return true; + } +#elif defined(__ARM_ARCH_7A__) + if (p_feature == "armeabi-v7a" || p_feature == "armeabi") { + return true; + } +#elif defined(__arm__) + if (p_feature == "armeabi") { + return true; + } +#endif + return false; } OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, bool p_use_apk_expansion) { diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 61798c5f87..550dfdd7d6 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -3,7 +3,7 @@ Import('env') iphone_lib = [ - + 'godot_iphone.cpp', 'os_iphone.cpp', 'sem_iphone.cpp', 'gl_view.mm', @@ -17,10 +17,10 @@ iphone_lib = [ ] env_ios = env.Clone() +ios_lib = env_ios.Library('iphone', iphone_lib) -obj = env_ios.Object('godot_iphone.cpp') +def combine_libs(target=None, source=None, env=None): + lib_path = target[0].srcnode().abspath + env.Execute('$IPHONEPATH/usr/bin/libtool -static -o "' + lib_path + '" ' + ' '.join([('"' + lib.srcnode().abspath + '"') for lib in source])) -prog = None -prog = env_ios.Program('#bin/godot', [obj] + iphone_lib) -action = "$IPHONEPATH/usr/bin/dsymutil " + File(prog)[0].path + " -o " + File(prog)[0].path + ".dSYM" -env.AddPostAction(prog, action) +combine_command = env_ios.Command('#bin/libgodot' + env_ios['LIBSUFFIX'], [ios_lib] + env_ios['LIBS'], combine_libs) diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 4ea358f871..25674c2b47 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -61,10 +61,13 @@ def configure(env): env.Append(LINKFLAGS=['-flto']) ## Architecture + if env["ios_sim"] and not ("arch" in env): + env["arch"] = "x86" - if env["ios_sim"] or env["arch"] == "x86": # i386, simulator - env["arch"] = "x86" + if env["arch"] == "x86": # i386, simulator env["bits"] = "32" + elif env["arch"] == "x86_64": + env["bits"] = "64" elif (env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32"): # arm env["arch"] = "arm" env["bits"] = "32" @@ -95,10 +98,11 @@ def configure(env): ## Compile flags - if (env["arch"] == "x86"): + if (env["arch"] == "x86" or env["arch"] == "x86_64"): env['IPHONEPLATFORM'] = 'iPhoneSimulator' - env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.6' - env.Append(CCFLAGS='-arch i386 -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -D__IPHONE_OS_VERSION_MIN_REQUIRED=40100 -isysroot $IPHONESDK -mios-simulator-version-min=4.3 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"'.split()) + env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9' + arch_flag = "i386" if env["arch"] == "x86" else env["arch"] + env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split()) elif (env["arch"] == "arm"): env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split()) elif (env["arch"] == "arm64"): @@ -113,8 +117,9 @@ def configure(env): ## Link flags - if (env["arch"] == "x86"): - env.Append(LINKFLAGS=['-arch', 'i386', '-mios-simulator-version-min=4.3', + if (env["arch"] == "x86" or env["arch"] == "x86_64"): + arch_flag = "i386" if env["arch"] == "x86" else env["arch"] + env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=9.0', '-isysroot', '$IPHONESDK', '-Xlinker', '-objc_abi_version', diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 0507ef19d6..6aa1ed9f8d 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -56,11 +56,48 @@ class EditorExportPlatformIOS : public EditorExportPlatform { static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata); static Error _codesign(String p_file, void *p_userdata); - void _fix_config_file(const Ref &p_preset, Vector &pfile, const String &p_name, const String &p_binary, bool p_debug); - static Error _export_dylibs(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); + struct IOSConfigData { + String pkg_name; + String binary_name; + String plist_content; + String architectures; + String linker_flags; + String cpp_code; + }; + + struct ExportArchitecture { + String name; + bool is_default; + + ExportArchitecture() + : name(""), is_default(false) { + } + + ExportArchitecture(String p_name, bool p_is_default) { + name = p_name; + is_default = p_is_default; + } + }; + + struct IOSExportAsset { + String exported_path; + bool is_framework; // framework is anything linked to the binary, otherwise it's a resource + }; + + String _get_additional_plist_content(); + String _get_linker_flags(); + String _get_cpp_code(); + void _fix_config_file(const Ref &p_preset, Vector &pfile, const IOSConfigData &p_config, bool p_debug); Error _export_loading_screens(const Ref &p_preset, const String &p_dest_dir); Error _export_icons(const Ref &p_preset, const String &p_iconset_dir); + Vector _get_supported_architectures(); + Vector _get_preset_architectures(const Ref &p_preset); + + void _add_assets_to_project(Vector &p_project_data, const Vector &p_additional_assets); + Error _export_additional_assets(const String &p_out_dir, const Vector &p_assets, bool p_is_framework, Vector &r_exported_assets); + Error _export_additional_assets(const String &p_out_dir, const Vector &p_libraries, Vector &r_exported_assets); + protected: virtual void get_preset_features(const Ref &p_preset, List *r_features); virtual void get_export_options(List *r_options); @@ -96,6 +133,17 @@ void EditorExportPlatformIOS::get_preset_features(const Ref if (p_preset->get("texture_format/etc2")) { r_features->push_back("etc2"); } + Vector architectures = _get_preset_architectures(p_preset); + for (int i = 0; i < architectures.size(); ++i) { + r_features->push_back(architectures[i]); + } +} + +Vector EditorExportPlatformIOS::_get_supported_architectures() { + Vector archs; + archs.push_back(ExportArchitecture("armv7", true)); + archs.push_back(ExportArchitecture("arm64", true)); + return archs; } void EditorExportPlatformIOS::get_export_options(List *r_options) { @@ -120,7 +168,6 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPhone/iPod Touch with retina display r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad @@ -145,10 +192,13 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true)); - /* probably need some more info */ + Vector architectures = _get_supported_architectures(); + for (int i = 0; i < architectures.size(); ++i) { + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + architectures[i].name), architectures[i].is_default)); + } } -void EditorExportPlatformIOS::_fix_config_file(const Ref &p_preset, Vector &pfile, const String &p_name, const String &p_binary, bool p_debug) { +void EditorExportPlatformIOS::_fix_config_file(const Ref &p_preset, Vector &pfile, const IOSConfigData &p_config, bool p_debug) { static const String export_method_string[] = { "app-store", "development", @@ -158,13 +208,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); - print_line(str); Vector lines = str.split("\n"); for (int i = 0; i < lines.size(); i++) { if (lines[i].find("$binary") != -1) { - strnew += lines[i].replace("$binary", p_binary) + "\n"; + strnew += lines[i].replace("$binary", p_config.binary_name) + "\n"; } else if (lines[i].find("$name") != -1) { - strnew += lines[i].replace("$name", p_name) + "\n"; + strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; } else if (lines[i].find("$info") != -1) { strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; } else if (lines[i].find("$identifier") != -1) { @@ -186,10 +235,21 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n"; } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) { strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n"; + } else if (lines[i].find("$provisioning_profile_uuid") != -1) { + String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release"); + strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; } else if (lines[i].find("$code_sign_identity_debug") != -1) { strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n"; } else if (lines[i].find("$code_sign_identity_release") != -1) { strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n"; + } else if (lines[i].find("$additional_plist_content") != -1) { + strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n"; + } else if (lines[i].find("$godot_archs") != -1) { + strnew += lines[i].replace("$godot_archs", p_config.architectures) + "\n"; + } else if (lines[i].find("$linker_flags") != -1) { + strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; + } else if (lines[i].find("$cpp_code") != -1) { + strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; } else { strnew += lines[i] + "\n"; } @@ -204,27 +264,37 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ } } -Error EditorExportPlatformIOS::_export_dylibs(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - if (!p_path.ends_with(".dylib")) return OK; - const String &dest_dir = *(String *)p_userdata; - String rel_path = p_path.replace_first("res://", "dylibs/"); - DirAccess *dest_dir_access = DirAccess::open(dest_dir); - ERR_FAIL_COND_V(!dest_dir_access, ERR_CANT_OPEN); - - String base_dir = rel_path.get_base_dir(); - Error make_dir_err = OK; - if (!dest_dir_access->dir_exists(base_dir)) { - make_dir_err = dest_dir_access->make_dir_recursive(base_dir); +String EditorExportPlatformIOS::_get_additional_plist_content() { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + String result; + for (int i = 0; i < export_plugins.size(); ++i) { + result += export_plugins[i]->get_ios_plist_content(); } - if (make_dir_err != OK) { - memdelete(dest_dir_access); - return make_dir_err; + return result; +} + +String EditorExportPlatformIOS::_get_linker_flags() { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + String result; + for (int i = 0; i < export_plugins.size(); ++i) { + String flags = export_plugins[i]->get_ios_linker_flags(); + if (flags.length() == 0) continue; + if (result.length() > 0) { + result += ' '; + } + result += flags; } + // the flags will be enclosed in quotes, so need to escape them + return result.replace("\"", "\\\""); +} - Error copy_err = dest_dir_access->copy(p_path, dest_dir + rel_path); - memdelete(dest_dir_access); - - return copy_err; +String EditorExportPlatformIOS::_get_cpp_code() { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + String result; + for (int i = 0; i < export_plugins.size(); ++i) { + result += export_plugins[i]->get_ios_cpp_code(); + } + return result; } struct IconInfo { @@ -402,7 +472,207 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { return OK; } +struct PbxId { +private: + static char _hex_char(uint8_t four_bits) { + if (four_bits < 10) { + return ('0' + four_bits); + } + return 'A' + (four_bits - 10); + } + + static String _hex_pad(uint32_t num) { + Vector ret; + ret.resize(sizeof(num) * 2); + for (int i = 0; i < sizeof(num) * 2; ++i) { + uint8_t four_bits = (num >> (sizeof(num) * 8 - (i + 1) * 4)) & 0xF; + ret[i] = _hex_char(four_bits); + } + return String::utf8(ret.ptr(), ret.size()); + } + +public: + uint32_t high_bits; + uint32_t mid_bits; + uint32_t low_bits; + + String str() const { + return _hex_pad(high_bits) + _hex_pad(mid_bits) + _hex_pad(low_bits); + } + + PbxId &operator++() { + low_bits++; + if (!low_bits) { + mid_bits++; + if (!mid_bits) { + high_bits++; + } + } + + return *this; + } +}; + +struct ExportLibsData { + Vector lib_paths; + String dest_dir; +}; + +void EditorExportPlatformIOS::_add_assets_to_project(Vector &p_project_data, const Vector &p_additional_assets) { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + Vector frameworks; + for (int i = 0; i < export_plugins.size(); ++i) { + Vector plugin_frameworks = export_plugins[i]->get_ios_frameworks(); + for (int j = 0; j < plugin_frameworks.size(); ++j) { + frameworks.push_back(plugin_frameworks[j]); + } + } + + // that is just a random number, we just need Godot IDs not to clash with + // existing IDs in the project. + PbxId current_id = { 0x58938401, 0, 0 }; + String pbx_files; + String pbx_frameworks_build; + String pbx_frameworks_refs; + String pbx_resources_build; + String pbx_resources_refs; + + const String file_info_format = String("$build_id = {isa = PBXBuildFile; fileRef = $ref_id; };\n") + + "$ref_id = {isa = PBXFileReference; lastKnownFileType = $file_type; name = $name; path = \"$file_path\"; sourceTree = \"\"; };\n"; + for (int i = 0; i < p_additional_assets.size(); ++i) { + String build_id = (++current_id).str(); + String ref_id = (++current_id).str(); + const IOSExportAsset &asset = p_additional_assets[i]; + + String type; + if (asset.exported_path.ends_with(".framework")) { + type = "wrapper.framework"; + } else if (asset.exported_path.ends_with(".dylib")) { + type = "compiled.mach-o.dylib"; + } else if (asset.exported_path.ends_with(".a")) { + type = "archive.ar"; + } else { + type = "file"; + } + + String &pbx_build = asset.is_framework ? pbx_frameworks_build : pbx_resources_build; + String &pbx_refs = asset.is_framework ? pbx_frameworks_refs : pbx_resources_refs; + + if (pbx_build.length() > 0) { + pbx_build += ",\n"; + pbx_refs += ",\n"; + } + pbx_build += build_id; + pbx_refs += ref_id; + + Dictionary format_dict; + format_dict["build_id"] = build_id; + format_dict["ref_id"] = ref_id; + format_dict["name"] = asset.exported_path.get_file(); + format_dict["file_path"] = asset.exported_path; + format_dict["file_type"] = type; + pbx_files += file_info_format.format(format_dict, "$_"); + } + + String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size()); + str = str.replace("$additional_pbx_files", pbx_files); + str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build); + str = str.replace("$additional_pbx_frameworks_refs", pbx_frameworks_refs); + str = str.replace("$additional_pbx_resources_build", pbx_resources_build); + str = str.replace("$additional_pbx_resources_refs", pbx_resources_refs); + + CharString cs = str.utf8(); + p_project_data.resize(cs.size() - 1); + for (int i = 0; i < cs.size() - 1; i++) { + p_project_data[i] = cs[i]; + } +} + +Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector &p_assets, bool p_is_framework, Vector &r_exported_assets) { + DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V(!filesystem_da, ERR_CANT_CREATE); + for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) { + String asset = p_assets[f_idx]; + if (!asset.begins_with("res://")) { + // either SDK-builtin or already a part of the export template + IOSExportAsset exported_asset = { asset, p_is_framework }; + r_exported_assets.push_back(exported_asset); + } else { + DirAccess *da = DirAccess::create_for_path(asset); + if (!da) { + memdelete(filesystem_da); + ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); + } + bool file_exists = da->file_exists(asset); + bool dir_exists = da->dir_exists(asset); + if (!file_exists && !dir_exists) { + memdelete(da); + memdelete(filesystem_da); + return ERR_FILE_NOT_FOUND; + } + String additional_dir = p_is_framework && asset.ends_with(".dylib") ? "/dylibs/" : "/"; + String destination_dir = p_out_dir + additional_dir + asset.get_base_dir().replace("res://", ""); + if (!filesystem_da->dir_exists(destination_dir)) { + Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); + if (make_dir_err) { + memdelete(da); + memdelete(filesystem_da); + return make_dir_err; + } + } + + String destination = destination_dir + "/" + asset.get_file(); + Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination); + memdelete(da); + if (err) { + memdelete(filesystem_da); + return err; + } + IOSExportAsset exported_asset = { destination, p_is_framework }; + r_exported_assets.push_back(exported_asset); + } + } + memdelete(filesystem_da); + + return OK; +} + +Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector &p_libraries, Vector &r_exported_assets) { + Vector > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + Vector frameworks = export_plugins[i]->get_ios_frameworks(); + Error err = _export_additional_assets(p_out_dir, frameworks, true, r_exported_assets); + ERR_FAIL_COND_V(err, err); + Vector ios_bundle_files = export_plugins[i]->get_ios_bundle_files(); + err = _export_additional_assets(p_out_dir, ios_bundle_files, false, r_exported_assets); + ERR_FAIL_COND_V(err, err); + } + + Vector library_paths; + for (int i = 0; i < p_libraries.size(); ++i) { + library_paths.push_back(p_libraries[i].path); + } + Error err = _export_additional_assets(p_out_dir, library_paths, true, r_exported_assets); + ERR_FAIL_COND_V(err, err); + + return OK; +} + +Vector EditorExportPlatformIOS::_get_preset_architectures(const Ref &p_preset) { + Vector all_archs = _get_supported_architectures(); + Vector enabled_archs; + for (int i = 0; i < all_archs.size(); ++i) { + bool is_enabled = p_preset->get("architectures/" + all_archs[i].name); + if (is_enabled) { + enabled_archs.push_back(all_archs[i].name); + } + } + return enabled_archs; +} + Error EditorExportPlatformIOS::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + String src_pkg_name; String dest_dir = p_path.get_base_dir() + "/"; String binary_name = p_path.get_file().get_basename(); @@ -427,26 +697,43 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p } } - FileAccess *src_f = NULL; - zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (da) { + String current_dir = da->get_current_dir(); - ep.step("Creating app", 0); + // remove leftovers from last export so they don't interfere + // in case some files are no longer needed + if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) { + da->erase_contents_recursive(); + } + if (da->change_dir(dest_dir + binary_name) == OK) { + da->erase_contents_recursive(); + } - unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io); - if (!src_pkg_zip) { + da->change_dir(current_dir); - EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name); - return ERR_FILE_NOT_FOUND; + if (!da->dir_exists(dest_dir + binary_name)) { + Error err = da->make_dir(dest_dir + binary_name); + if (err) { + memdelete(da); + return err; + } + } + memdelete(da); } - ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN); - int ret = unzGoToFirstFile(src_pkg_zip); + ep.step("Making .pck", 0); + String pack_path = dest_dir + binary_name + ".pck"; + Vector libraries; + Error err = save_pack(p_preset, pack_path, &libraries); + if (err) + return err; - String binary_to_use = "godot.iphone." + String(p_debug ? "debug" : "release") + "."; - int bits_mode = p_preset->get("application/bits_mode"); - binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "arm64" : "armv7"); + ep.step("Extracting and configuring Xcode project", 1); - print_line("binary: " + binary_to_use); + String library_to_use = "libgodot.iphone." + String(p_debug ? "debug" : "release") + ".fat.a"; + + print_line("static library: " + library_to_use); String pkg_name; if (p_preset->get("application/name") != "") pkg_name = p_preset->get("application/name"); // app_name @@ -455,22 +742,41 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p else pkg_name = "Unnamed"; - DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); - ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE) - - /* Now process our template */ - bool found_binary = false; + bool found_library = false; int total_size = 0; + const String project_file = "godot_ios.xcodeproj/project.pbxproj"; Set files_to_parse; files_to_parse.insert("godot_ios/godot_ios-Info.plist"); - files_to_parse.insert("godot_ios.xcodeproj/project.pbxproj"); - files_to_parse.insert("export_options.plist"); + files_to_parse.insert(project_file); + files_to_parse.insert("godot_ios/export_options.plist"); + files_to_parse.insert("godot_ios/dummy.cpp"); files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata"); files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme"); - print_line("Unzipping..."); + IOSConfigData config_data = { + pkg_name, + binary_name, + _get_additional_plist_content(), + String(" ").join(_get_preset_architectures(p_preset)), + _get_linker_flags(), + _get_cpp_code() + }; + DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); + ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE) + + print_line("Unzipping..."); + FileAccess *src_f = NULL; + zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io); + if (!src_pkg_zip) { + EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name); + return ERR_CANT_OPEN; + } + ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN); + int ret = unzGoToFirstFile(src_pkg_zip); + Vector project_file_data; while (ret == UNZ_OK) { bool is_execute = false; @@ -496,15 +802,18 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p if (files_to_parse.has(file)) { print_line(String("parse ") + file); - _fix_config_file(p_preset, data, pkg_name, binary_name, p_debug); - } else if (file.begins_with("godot.iphone")) { - if (file != binary_to_use) { + _fix_config_file(p_preset, data, config_data, p_debug); + } else if (file.begins_with("libgodot.iphone")) { + if (file != library_to_use) { ret = unzGoToNextFile(src_pkg_zip); continue; //ignore! } - found_binary = true; + found_library = true; is_execute = true; - file = "godot_ios.iphone"; + file = "godot_ios.a"; + } + if (file == project_file) { + project_file_data = data; } ///@TODO need to parse logo files @@ -557,16 +866,16 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p /* we're done with our source zip */ unzClose(src_pkg_zip); - if (!found_binary) { - ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive."); + if (!found_library) { + ERR_PRINTS("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive."); memdelete(tmp_app_path); return ERR_FILE_NOT_FOUND; } String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/"; - Error err = OK; + err = OK; if (!tmp_app_path->dir_exists(iconset_dir)) { - Error err = tmp_app_path->make_dir_recursive(iconset_dir); + err = tmp_app_path->make_dir_recursive(iconset_dir); } memdelete(tmp_app_path); if (err) @@ -580,20 +889,23 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p if (err) return err; - ep.step("Making .pck", 1); - - String pack_path = dest_dir + binary_name + ".pck"; - err = save_pack(p_preset, pack_path); - if (err) - return err; - - err = export_project_files(p_preset, _export_dylibs, &dest_dir); - if (err) - return err; + print_line("Exporting additional assets"); + Vector assets; + _export_additional_assets(dest_dir + binary_name, libraries, assets); + _add_assets_to_project(project_file_data, assets); + String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj"; + FileAccess *f = FileAccess::open(project_file_name, FileAccess::WRITE); + if (!f) { + ERR_PRINTS("Can't write '" + project_file_name + "'."); + return ERR_CANT_CREATE; + }; + f->store_buffer(project_file_data.ptr(), project_file_data.size()); + f->close(); + memdelete(f); #ifdef OSX_ENABLED ep.step("Code-signing dylibs", 2); - DirAccess *dylibs_dir = DirAccess::open(dest_dir + "dylibs"); + DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs"); ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN); CodesignData codesign_data(p_preset, p_debug); err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data); @@ -625,13 +937,14 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p export_args.push_back("-archivePath"); export_args.push_back(archive_path); export_args.push_back("-exportOptionsPlist"); - export_args.push_back(dest_dir + "export_options.plist"); + export_args.push_back(dest_dir + binary_name + "/export_options.plist"); + export_args.push_back("-allowProvisioningUpdates"); export_args.push_back("-exportPath"); export_args.push_back(dest_dir); err = OS::get_singleton()->execute("xcodebuild", export_args, true); ERR_FAIL_COND_V(err, err); #else - print_line(".ipa can only be built on macOS. Leaving XCode project without building the package."); + print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package."); #endif return OK; diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index 531b80eee3..d2104ae765 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -109,7 +109,7 @@ void GameCenter::connect() { GameCenter::get_singleton()->authenticated = true; } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; ret["error_description"] = [error.localizedDescription UTF8String]; GameCenter::get_singleton()->authenticated = false; }; @@ -145,7 +145,7 @@ Error GameCenter::post_score(Variant p_score) { ret["result"] = "ok"; } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; ret["error_description"] = [error.localizedDescription UTF8String]; }; @@ -183,7 +183,7 @@ Error GameCenter::award_achievement(Variant p_params) { ret["result"] = "ok"; } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; }; pending_events.push_back(ret); @@ -241,7 +241,7 @@ void GameCenter::request_achievement_descriptions() { } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; }; pending_events.push_back(ret); @@ -273,7 +273,7 @@ void GameCenter::request_achievements() { } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; }; pending_events.push_back(ret); @@ -289,7 +289,7 @@ void GameCenter::reset_achievements() { ret["result"] = "ok"; } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; }; pending_events.push_back(ret); @@ -358,7 +358,7 @@ Error GameCenter::request_identity_verification_signature() { ret["player_id"] = [player.playerID UTF8String]; } else { ret["result"] = "error"; - ret["error_code"] = error.code; + ret["error_code"] = (int64_t)error.code; ret["error_description"] = [error.localizedDescription UTF8String]; }; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 95d7710c76..90cb09b458 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -46,6 +46,7 @@ #include "sem_iphone.h" #include "ios.h" +#include int OSIPhone::get_video_driver_count() const { @@ -99,9 +100,11 @@ void OSIPhone::initialize_core() { void OSIPhone::initialize_logger() { Vector loggers; loggers.push_back(memnew(SyslogLogger)); - // FIXME: Reenable once we figure out how to get this properly in user:// - // instead of littering the user's working dirs (res:// + pwd) with log files (GH-12277) - //loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt"))); +#ifdef DEBUG_ENABLED + // it seems iOS app's stdout/stderr is only obtainable if you launch it from Xcode + loggers.push_back(memnew(StdLogger)); +#endif + loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt"))); _set_logger(memnew(CompositeLogger(loggers))); } @@ -402,6 +405,37 @@ void OSIPhone::alert(const String &p_alert, const String &p_title) { iOS::alert(utf8_alert.get_data(), utf8_title.get_data()); } +Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle) { + if (p_path.length() == 0) { + p_library_handle = RTLD_SELF; + return OK; + } + return OS_Unix::open_dynamic_library(p_path, p_library_handle); +} + +Error OSIPhone::close_dynamic_library(void *p_library_handle) { + if (p_library_handle == RTLD_SELF) { + return OK; + } + return OS_Unix::close_dynamic_library(p_library_handle); +} + +HashMap OSIPhone::dynamic_symbol_lookup_table; +void register_dynamic_symbol(char *name, void *address) { + OSIPhone::dynamic_symbol_lookup_table[String(name)] = address; +} + +Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { + if (p_library_handle == RTLD_SELF) { + void **ptr = OSIPhone::dynamic_symbol_lookup_table.getptr(p_name); + if (ptr) { + p_symbol_handle = *ptr; + return OK; + } + } + return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional); +} + void OSIPhone::set_video_mode(const VideoMode &p_video_mode, int p_screen) { video_mode = p_video_mode; @@ -558,7 +592,36 @@ bool OSIPhone::_check_internal_feature_support(const String &p_feature) { return p_feature == "mobile" || p_feature == "etc" || p_feature == "pvrtc" || p_feature == "etc2"; } +// Initialization order between compilation units is not guaranteed, +// so we use this as a hack to ensure certain code is called before +// everything else, but after all units are initialized. +typedef void (*init_callback)(); +static init_callback *ios_init_callbacks = NULL; +static int ios_init_callbacks_count = 0; +static int ios_init_callbacks_capacity = 0; + +void add_ios_init_callback(init_callback cb) { + if (ios_init_callbacks_count == ios_init_callbacks_capacity) { + void *new_ptr = realloc(ios_init_callbacks, sizeof(cb) * 32); + if (new_ptr) { + ios_init_callbacks = (init_callback *)(new_ptr); + ios_init_callbacks_capacity += 32; + } + } + if (ios_init_callbacks_capacity > ios_init_callbacks_count) { + ios_init_callbacks[ios_init_callbacks_count] = cb; + ++ios_init_callbacks_count; + } +} + OSIPhone::OSIPhone(int width, int height, String p_data_dir) { + for (int i = 0; i < ios_init_callbacks_count; ++i) { + ios_init_callbacks[i](); + } + free(ios_init_callbacks); + ios_init_callbacks = NULL; + ios_init_callbacks_count = 0; + ios_init_callbacks_capacity = 0; main_loop = NULL; visual_server = NULL; diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 433228b599..0790a2a9ea 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -60,6 +60,9 @@ private: MAX_EVENTS = 64, }; + static HashMap dynamic_symbol_lookup_table; + friend void register_dynamic_symbol(char *name, void *address); + uint8_t supported_orientations; VisualServer *visual_server; @@ -153,6 +156,10 @@ public: 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); + virtual Error close_dynamic_library(void *p_library_handle); + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false); + virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); virtual VideoMode get_video_mode(int p_screen = 0) const; virtual void get_fullscreen_mode_list(List *p_list, int p_screen = 0) const; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 943f6d8f35..05b0fb3fbc 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -155,6 +155,7 @@ String EditorExportPlatformJavaScript::get_binary_extension() const { } Error EditorExportPlatformJavaScript::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); String custom_debug = p_preset->get("custom_template/debug"); String custom_release = p_preset->get("custom_template/release"); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index f6922377e3..689b79b826 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -288,6 +288,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin } Error EditorExportPlatformOSX::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); String src_pkg_name;