Allow configuring iOS export
- EditorExportPlugin's _export_begin accepts all the arguments related to the current export (is_debug, path, flags). - EditorExportPlugin API is extended with methods allowing to configure iOS export: add_ios_framework, add_ios_plist_content, add_ios_linker_flags, add_ios_bundle_file. - iOS export template now contains Godot as a static library so that it can be linked with third-party Frameworks and GDNative static libraries. - Adds method to DirAccess for recursive copying of a directory. - Fixes iOS export to work with Xcode 9 (released recently).
This commit is contained in:
parent
82ad05a20e
commit
8f0f327f02
|
@ -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<String> 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<String>::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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -862,6 +862,17 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo
|
|||
return ret;
|
||||
}
|
||||
|
||||
String String::join(Vector<String> 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);
|
||||
|
|
|
@ -169,6 +169,8 @@ public:
|
|||
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
|
||||
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
|
||||
|
||||
String join(Vector<String> parts);
|
||||
|
||||
static CharType char_uppercase(CharType p_char);
|
||||
static CharType char_lowercase(CharType p_char);
|
||||
String to_upper() const;
|
||||
|
|
|
@ -470,9 +470,52 @@ void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &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<String> &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<String> 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<String> 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<String> &p_features) {
|
||||
|
@ -482,17 +525,17 @@ void EditorExportPlugin::_export_file_script(const String &p_path, const String
|
|||
}
|
||||
}
|
||||
|
||||
void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features) {
|
||||
void EditorExportPlugin::_export_begin_script(const PoolVector<String> &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<String> &p_features) {
|
||||
}
|
||||
|
||||
void EditorExportPlugin::_export_begin(const Set<String> &p_features) {
|
||||
void EditorExportPlugin::_export_begin(const Set<String> &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<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
|
||||
|
||||
EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset) {
|
||||
Ref<EditorExportPlatform> platform = p_preset->get_platform();
|
||||
List<String> feature_list;
|
||||
platform->get_platform_features(&feature_list);
|
||||
platform->get_preset_features(p_preset, &feature_list);
|
||||
//figure out features
|
||||
Set<String> features;
|
||||
PoolVector<String> features_pv;
|
||||
|
||||
FeatureContainers result;
|
||||
for (List<String>::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<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
||||
FeatureContainers features = p_platform.get_feature_containers(p_preset);
|
||||
Vector<Ref<EditorExportPlugin> > 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<Ref<EditorExportPlugin> > 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<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) {
|
||||
//figure out paths of files that will be exported
|
||||
Set<String> paths;
|
||||
Vector<String> path_remaps;
|
||||
|
@ -551,13 +619,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
|
|||
_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<Ref<EditorExportPlugin> > 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<EditorExportPreset> &
|
|||
export_plugins[i]->_clear();
|
||||
}
|
||||
|
||||
FeatureContainers feature_containers = get_feature_containers(p_preset);
|
||||
Set<String> &features = feature_containers.features;
|
||||
PoolVector<String> &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<EditorExportPreset> &
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &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<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files) {
|
||||
|
||||
EditorProgress ep("savepack", TTR("Packing"), 102);
|
||||
|
||||
|
@ -697,8 +773,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &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<EditorExportPreset> &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");
|
||||
|
|
|
@ -118,13 +118,24 @@ public:
|
|||
EditorExportPreset();
|
||||
};
|
||||
|
||||
struct SharedObject {
|
||||
String path;
|
||||
Vector<String> tags;
|
||||
|
||||
SharedObject(const String &p_path, const Vector<String> &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<uint8_t> &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<SavedData> file_ofs;
|
||||
EditorProgress *ep;
|
||||
Vector<SharedObject> *so_files;
|
||||
};
|
||||
|
||||
struct ZipData {
|
||||
|
@ -152,6 +164,11 @@ private:
|
|||
EditorProgress *ep;
|
||||
};
|
||||
|
||||
struct FeatureContainers {
|
||||
Set<String> features;
|
||||
PoolVector<String> features_pv;
|
||||
};
|
||||
|
||||
void _export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths);
|
||||
void _export_find_dependencies(const String &p_path, Set<String> &p_paths);
|
||||
|
||||
|
@ -162,7 +179,16 @@ private:
|
|||
void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
|
||||
void _edit_filter_list(Set<String> &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<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
|
||||
~ExportNotifier();
|
||||
};
|
||||
|
||||
FeatureContainers get_feature_containers(const Ref<EditorExportPreset> &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<String> &r_flags, int p_flags);
|
||||
|
@ -192,7 +218,7 @@ public:
|
|||
|
||||
Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = NULL);
|
||||
|
||||
Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
||||
Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files = NULL);
|
||||
Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
||||
|
||||
virtual bool poll_devices() { return false; }
|
||||
|
@ -225,7 +251,7 @@ class EditorExportPlugin : public Reference {
|
|||
|
||||
friend class EditorExportPlatform;
|
||||
|
||||
Vector<String> shared_objects;
|
||||
Vector<SharedObject> shared_objects;
|
||||
struct ExtraFile {
|
||||
String path;
|
||||
Vector<uint8_t> data;
|
||||
|
@ -234,26 +260,53 @@ class EditorExportPlugin : public Reference {
|
|||
Vector<ExtraFile> extra_files;
|
||||
bool skipped;
|
||||
|
||||
Vector<String> ios_frameworks;
|
||||
String ios_plist_content;
|
||||
String ios_linker_flags;
|
||||
Vector<String> 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<String> &p_features);
|
||||
void _export_begin_script(const PoolVector<String> &p_features);
|
||||
void _export_begin_script(const PoolVector<String> &p_features, bool p_debug, const String &p_path, int p_flags);
|
||||
|
||||
protected:
|
||||
void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap);
|
||||
void add_shared_object(const String &p_path);
|
||||
void add_shared_object(const String &p_path, const Vector<String> &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<String> &p_features);
|
||||
virtual void _export_begin(const Set<String> &p_features);
|
||||
virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Vector<String> get_ios_frameworks() const;
|
||||
String get_ios_plist_content() const;
|
||||
String get_ios_linker_flags() const;
|
||||
Vector<String> get_ios_bundle_files() const;
|
||||
String get_ios_cpp_code() const;
|
||||
|
||||
EditorExportPlugin();
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = "<group>"; };
|
||||
1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; };
|
||||
D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||
D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
|
||||
D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-736h@3x.png"; sourceTree = "<group>"; };
|
||||
|
@ -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 = "<group>"; };
|
||||
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "$binary-Prefix.pch"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
D0BCFE7918AEC06A004A7AAE /* $binary.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = $binary.iphone; sourceTree = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
|
@ -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 = "<group>";
|
||||
|
@ -124,6 +169,7 @@
|
|||
D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */,
|
||||
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
|
||||
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
|
||||
1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */,
|
||||
);
|
||||
path = $binary;
|
||||
sourceTree = "<group>";
|
||||
|
@ -133,7 +179,6 @@
|
|||
children = (
|
||||
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */,
|
||||
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
|
||||
D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
|
@ -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;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
$cpp_code
|
|
@ -0,0 +1 @@
|
|||
Dummy file to make dylibs folder exported
|
|
@ -4,7 +4,17 @@
|
|||
<dict>
|
||||
<key>method</key>
|
||||
<string>$export_method</string>
|
||||
|
||||
<key>teamID</key>
|
||||
<string>$team_id</string>
|
||||
|
||||
<key>provisioningProfiles</key>
|
||||
<dict>
|
||||
<key>$identifier</key>
|
||||
<string>$provisioning_profile_uuid</string>
|
||||
</dict>
|
||||
|
||||
<key>compileBitcode</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -7,7 +7,7 @@
|
|||
<key>CFBundleDisplayName</key>
|
||||
<string>$name</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$binary.iphone</string>
|
||||
<string>$binary</string>
|
||||
<key>CFBundleIcons</key>
|
||||
<dict/>
|
||||
<key>CFBundleIcons~ipad</key>
|
||||
|
@ -47,5 +47,6 @@
|
|||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
$additional_plist_content
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -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 <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
0
misc/dist/ios_xcode/godot.iphone.debug.arm → misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
vendored
Executable file → Normal file
0
misc/dist/ios_xcode/godot.iphone.debug.arm → misc/dist/ios_xcode/libgodot.iphone.debug.fat.a
vendored
Executable file → Normal file
0
misc/dist/ios_xcode/godot.iphone.debug.arm64 → misc/dist/ios_xcode/libgodot.iphone.release.fat.a
vendored
Executable file → Normal file
0
misc/dist/ios_xcode/godot.iphone.debug.arm64 → misc/dist/ios_xcode/libgodot.iphone.release.fat.a
vendored
Executable file → Normal 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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<EditorExportPreset> &p_preset, Vector<uint8_t> &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<uint8_t> &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<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const IOSConfigData &p_config, bool p_debug);
|
||||
Error _export_loading_screens(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir);
|
||||
Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir);
|
||||
|
||||
Vector<ExportArchitecture> _get_supported_architectures();
|
||||
Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset);
|
||||
|
||||
void _add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
|
||||
Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets);
|
||||
Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
|
||||
|
||||
protected:
|
||||
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
|
||||
virtual void get_export_options(List<ExportOption> *r_options);
|
||||
|
@ -96,6 +133,17 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset>
|
|||
if (p_preset->get("texture_format/etc2")) {
|
||||
r_features->push_back("etc2");
|
||||
}
|
||||
Vector<String> architectures = _get_preset_architectures(p_preset);
|
||||
for (int i = 0; i < architectures.size(); ++i) {
|
||||
r_features->push_back(architectures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() {
|
||||
Vector<ExportArchitecture> archs;
|
||||
archs.push_back(ExportArchitecture("armv7", true));
|
||||
archs.push_back(ExportArchitecture("arm64", true));
|
||||
return archs;
|
||||
}
|
||||
|
||||
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
|
||||
|
@ -120,7 +168,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *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<ExportOption> *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<ExportArchitecture> 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<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug) {
|
||||
void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &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<EditorExportPreset> &p_
|
|||
String str;
|
||||
String strnew;
|
||||
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
|
||||
print_line(str);
|
||||
Vector<String> 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<EditorExportPreset> &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<EditorExportPreset> &p_
|
|||
}
|
||||
}
|
||||
|
||||
Error EditorExportPlatformIOS::_export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &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<Ref<EditorExportPlugin> > 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<Ref<EditorExportPlugin> > 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<Ref<EditorExportPlugin> > 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<char> 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<String> lib_paths;
|
||||
String dest_dir;
|
||||
};
|
||||
|
||||
void EditorExportPlatformIOS::_add_assets_to_project(Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets) {
|
||||
Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
|
||||
Vector<String> frameworks;
|
||||
for (int i = 0; i < export_plugins.size(); ++i) {
|
||||
Vector<String> 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 = \"<group>\"; };\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<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &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<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) {
|
||||
Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins();
|
||||
for (int i = 0; i < export_plugins.size(); i++) {
|
||||
Vector<String> 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<String> 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<String> 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<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<EditorExportPreset> &p_preset) {
|
||||
Vector<ExportArchitecture> all_archs = _get_supported_architectures();
|
||||
Vector<String> 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<EditorExportPreset> &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<EditorExportPreset> &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<SharedObject> 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<EditorExportPreset> &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<String> 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<uint8_t> project_file_data;
|
||||
while (ret == UNZ_OK) {
|
||||
bool is_execute = false;
|
||||
|
||||
|
@ -496,15 +802,18 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &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<EditorExportPreset> &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<EditorExportPreset> &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<IOSExportAsset> 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<EditorExportPreset> &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;
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "sem_iphone.h"
|
||||
|
||||
#include "ios.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
int OSIPhone::get_video_driver_count() const {
|
||||
|
||||
|
@ -99,9 +100,11 @@ void OSIPhone::initialize_core() {
|
|||
void OSIPhone::initialize_logger() {
|
||||
Vector<Logger *> 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<String, void *> 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;
|
||||
|
|
|
@ -60,6 +60,9 @@ private:
|
|||
MAX_EVENTS = 64,
|
||||
};
|
||||
|
||||
static HashMap<String, void *> 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<VideoMode> *p_list, int p_screen = 0) const;
|
||||
|
|
|
@ -155,6 +155,7 @@ String EditorExportPlatformJavaScript::get_binary_extension() const {
|
|||
}
|
||||
|
||||
Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPreset> &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");
|
||||
|
|
|
@ -288,6 +288,7 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
|
|||
}
|
||||
|
||||
Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue