Merge pull request #85845 from YuriSizov/editor-export-hidden-errors

Ensure more export errors are reported to users
This commit is contained in:
Yuri Sizov 2023-12-08 16:59:04 +01:00
commit 26ba706831
9 changed files with 195 additions and 104 deletions

View File

@ -93,7 +93,7 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err)
}
p_log->add_newline();
if (msg_count) {
if (msg_count > 0) {
p_log->push_table(2);
p_log->set_table_column_expand(0, false);
p_log->set_table_column_expand(1, true);
@ -131,10 +131,39 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err)
p_log->pop();
p_log->pop();
}
p_log->pop();
p_log->add_newline();
} else if (p_err != OK) {
// We failed but don't show any user-facing messages. This is bad and should not
// be allowed, but just in case this happens, let's give the user something at least.
p_log->push_table(2);
p_log->set_table_column_expand(0, false);
p_log->set_table_column_expand(1, true);
{
Color color = p_log->get_theme_color(SNAME("error_color"), EditorStringName(Editor));
Ref<Texture> icon = p_log->get_editor_theme_icon(SNAME("Error"));
p_log->push_cell();
p_log->add_text("\t");
if (icon.is_valid()) {
p_log->add_image(icon);
}
p_log->pop();
p_log->push_cell();
p_log->push_color(color);
p_log->add_text(vformat("[%s]: %s", TTR("Unknown Error"), vformat(TTR("Export failed with error code %d."), p_err)));
p_log->pop();
p_log->pop();
}
p_log->pop();
p_log->add_newline();
}
p_log->add_newline();
return has_messages;
}

View File

@ -161,6 +161,7 @@ Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_
}
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
return err;
}
return err;

View File

@ -1109,37 +1109,40 @@ void ProjectExportDialog::_export_all_dialog_action(const String &p_str) {
}
void ProjectExportDialog::_export_all(bool p_debug) {
String export_target = p_debug ? TTR("Debug") : TTR("Release");
EditorProgress ep("exportall", TTR("Exporting All") + " " + export_target, EditorExport::get_singleton()->get_export_preset_count(), true);
exporting = true;
bool show_dialog = false;
result_dialog_log->clear();
for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(i);
if (preset.is_null()) {
exporting = false;
ERR_FAIL_MSG("Failed to start the export: one of the presets is invalid.");
}
Ref<EditorExportPlatform> platform = preset->get_platform();
if (platform.is_null()) {
exporting = false;
ERR_FAIL_MSG("Failed to start the export: one of the presets has no valid platform.");
}
{ // Scope for the editor progress, we must free it before showing the dialog at the end.
String export_target = p_debug ? TTR("Debug") : TTR("Release");
EditorProgress ep("exportall", TTR("Exporting All") + " " + export_target, EditorExport::get_singleton()->get_export_preset_count(), true);
ep.step(preset->get_name(), i);
result_dialog_log->clear();
for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(i);
if (preset.is_null()) {
exporting = false;
ERR_FAIL_MSG("Failed to start the export: one of the presets is invalid.");
}
platform->clear_messages();
Error err = platform->export_project(preset, p_debug, preset->get_export_path(), 0);
if (err == ERR_SKIP) {
exporting = false;
return;
Ref<EditorExportPlatform> platform = preset->get_platform();
if (platform.is_null()) {
exporting = false;
ERR_FAIL_MSG("Failed to start the export: one of the presets has no valid platform.");
}
ep.step(preset->get_name(), i);
platform->clear_messages();
Error err = platform->export_project(preset, p_debug, preset->get_export_path(), 0);
if (err == ERR_SKIP) {
exporting = false;
return;
}
bool has_messages = platform->fill_log_messages(result_dialog_log, err);
show_dialog = show_dialog || has_messages;
}
bool has_messages = platform->fill_log_messages(result_dialog_log, err);
show_dialog = show_dialog || has_messages;
}
if (show_dialog) {
result_dialog->popup_centered_ratio(0.5);
}
@ -1148,7 +1151,6 @@ void ProjectExportDialog::_export_all(bool p_debug) {
}
void ProjectExportDialog::_bind_methods() {
ClassDB::bind_method("_export_all", &ProjectExportDialog::_export_all);
ClassDB::bind_method("set_export_path", &ProjectExportDialog::set_export_path);
ClassDB::bind_method("get_export_path", &ProjectExportDialog::get_export_path);
ClassDB::bind_method("get_current_preset", &ProjectExportDialog::get_current_preset);

View File

@ -2782,6 +2782,12 @@ Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset>
Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String base_dir = p_path.get_base_dir();
if (!DirAccess::exists(base_dir)) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Target folder does not exist or is inaccessible: \"%s\""), base_dir));
return ERR_FILE_BAD_PATH;
}
String src_apk;
Error err;
@ -2856,7 +2862,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
const String assets_directory = get_assets_directory(p_preset, export_format);
String sdk_path = EDITOR_GET("export/android/android_sdk_path");
ERR_FAIL_COND_V_MSG(sdk_path.is_empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'.");
if (sdk_path.is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."));
return ERR_UNCONFIGURED;
}
print_verbose("Android sdk path: " + sdk_path);
// TODO: should we use "package/name" or "application/config/name"?
@ -3106,10 +3115,6 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
}
if (!DirAccess::exists(p_path.get_base_dir())) {
return ERR_FILE_BAD_PATH;
}
Ref<FileAccess> io_fa;
zlib_filefunc_def io = zipio_create_io(&io_fa);
@ -3302,10 +3307,6 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
zipClose(unaligned_apk, nullptr);
unzClose(pkg);
if (err != OK) {
CLEANUP_AND_RETURN(err);
}
// Let's zip-align (must be done before signing)
static const int ZIP_ALIGNMENT = 4;
@ -3392,6 +3393,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
// file will invalidate the signature.
err = sign_apk(p_preset, p_debug, p_path, ep);
if (err != OK) {
// Message is supplied by the subroutine method.
CLEANUP_AND_RETURN(err);
}
}

View File

@ -620,7 +620,10 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
String sizes;
Ref<DirAccess> da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
if (da.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat(TTR("Could not open a directory at path \"%s\"."), p_iconset_dir));
return ERR_CANT_OPEN;
}
Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color");
@ -692,12 +695,20 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
json_description += "]}";
Ref<FileAccess> json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
ERR_FAIL_COND_V(json_file.is_null(), ERR_CANT_CREATE);
if (json_file.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat(TTR("Could not write to a file at path \"%s\"."), p_iconset_dir + "Contents.json"));
return ERR_CANT_CREATE;
}
CharString json_utf8 = json_description.utf8();
json_file->store_buffer((const uint8_t *)json_utf8.get_data(), json_utf8.length());
Ref<FileAccess> sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
ERR_FAIL_COND_V(sizes_file.is_null(), ERR_CANT_CREATE);
if (sizes_file.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat(TTR("Could not write to a file at path \"%s\"."), p_iconset_dir + "sizes"));
return ERR_CANT_CREATE;
}
CharString sizes_utf8 = sizes.utf8();
sizes_file->store_buffer((const uint8_t *)sizes_utf8.get_data(), sizes_utf8.length());
@ -1219,10 +1230,10 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir
String asset = p_assets[f_idx];
if (asset.begins_with("res://")) {
Error err = _copy_asset(p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
} else if (ProjectSettings::get_singleton()->localize_path(asset).begins_with("res://")) {
Error err = _copy_asset(p_out_dir, ProjectSettings::get_singleton()->localize_path(asset), nullptr, p_is_framework, p_should_embed, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
} else {
// either SDK-builtin or already a part of the export template
IOSExportAsset exported_asset = { asset, p_is_framework, p_should_embed };
@ -1306,8 +1317,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
// We shouldn't embed .xcframework that contains static libraries.
// Static libraries are not embedded anyway.
err = _copy_asset(dest_dir, plugin_main_binary, &plugin_binary_result_file, true, false, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
// Adding dependencies.
// Use separate container for names to check for duplicates.
@ -1432,15 +1442,15 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
{
// Export linked plugin dependency
err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
// Export embedded plugin dependency
err = _export_additional_assets(dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
// Export plugin files
err = _export_additional_assets(dest_dir, plugin_files, false, false, r_exported_assets);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(err != OK, err);
}
// Update CPP
@ -1496,9 +1506,14 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_skip_ipa) {
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();
const String dest_dir = p_path.get_base_dir() + "/";
const String binary_name = p_path.get_file().get_basename();
const String binary_dir = dest_dir + binary_name;
if (!DirAccess::exists(dest_dir)) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Target folder does not exist or is inaccessible: \"%s\""), dest_dir));
return ERR_FILE_BAD_PATH;
}
bool export_project_only = p_preset->get("application/export_project_only");
@ -1507,6 +1522,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
String team_id = p_preset->get("application/app_store_team_id");
ERR_FAIL_COND_V_MSG(team_id.length() == 0, ERR_CANT_OPEN, "App Store Team ID not specified - cannot configure the project.");
String src_pkg_name;
if (p_debug) {
src_pkg_name = p_preset->get("custom_template/debug");
} else {
@ -1522,10 +1538,6 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
}
}
if (!DirAccess::exists(dest_dir)) {
return ERR_FILE_BAD_PATH;
}
{
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da.is_valid()) {
@ -1533,18 +1545,19 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
// 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) {
if (da->change_dir(binary_dir + ".xcodeproj") == OK) {
da->erase_contents_recursive();
}
if (da->change_dir(dest_dir + binary_name) == OK) {
if (da->change_dir(binary_dir) == OK) {
da->erase_contents_recursive();
}
da->change_dir(current_dir);
if (!da->dir_exists(dest_dir + binary_name)) {
Error err = da->make_dir(dest_dir + binary_name);
if (err) {
if (!da->dir_exists(binary_dir)) {
Error err = da->make_dir(binary_dir);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Failed to create the directory: \"%s\""), binary_dir));
return err;
}
}
@ -1554,10 +1567,11 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
if (ep.step("Making .pck", 0)) {
return ERR_SKIP;
}
String pack_path = dest_dir + binary_name + ".pck";
String pack_path = binary_dir + ".pck";
Vector<SharedObject> libraries;
Error err = save_pack(p_preset, p_debug, pack_path, &libraries);
if (err) {
// Message is supplied by the subroutine method.
return err;
}
@ -1606,7 +1620,10 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
Vector<IOSExportAsset> assets;
Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir);
ERR_FAIL_COND_V(tmp_app_path.is_null(), ERR_CANT_CREATE);
if (tmp_app_path.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Could not create and open the directory: \"%s\""), dest_dir));
return ERR_CANT_CREATE;
}
print_line("Unzipping...");
Ref<FileAccess> io_fa;
@ -1617,8 +1634,14 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
return ERR_CANT_OPEN;
}
err = _export_ios_plugins(p_preset, config_data, dest_dir + binary_name, assets, p_debug);
ERR_FAIL_COND_V(err, err);
err = _export_ios_plugins(p_preset, config_data, binary_dir, assets, p_debug);
if (err != OK) {
// TODO: Improve error reporting by using `add_message` throughout all methods called via `_export_ios_plugins`.
// For now a generic top level message would be fine, but we're ought to use proper reporting here instead of
// just fail macros and non-descriptive error return values.
add_message(EXPORT_MESSAGE_ERROR, TTR("iOS Plugins"), vformat(TTR("Failed to export iOS plugins with code %d. Please check the output log."), err));
return err;
}
//export rest of the files
int ret = unzGoToFirstFile(src_pkg_zip);
@ -1683,8 +1706,8 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
print_line("Creating " + dir_name);
Error dir_err = tmp_app_path->make_dir_recursive(dir_name);
if (dir_err) {
ERR_PRINT("Can't create '" + dir_name + "'.");
unzClose(src_pkg_zip);
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create a directory at path \"%s\"."), dir_name));
return ERR_CANT_CREATE;
}
}
@ -1693,8 +1716,8 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
{
Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
if (f.is_null()) {
ERR_PRINT("Can't write '" + file + "'.");
unzClose(src_pkg_zip);
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not write to a file at path \"%s\"."), file));
return ERR_CANT_CREATE;
};
f->store_buffer(data.ptr(), data.size());
@ -1715,7 +1738,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
unzClose(src_pkg_zip);
if (!found_library) {
ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Requested template library '%s' not found. It might be missing from your template archive."), library_to_use));
return ERR_FILE_NOT_FOUND;
}
@ -1727,7 +1750,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
Vector<String> translations = GLOBAL_GET("internationalization/locale/translations");
if (translations.size() > 0) {
{
String fname = dest_dir + binary_name + "/en.lproj";
String fname = binary_dir + "/en.lproj";
tmp_app_path->make_dir_recursive(fname);
Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
@ -1747,7 +1770,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
}
for (const String &lang : languages) {
String fname = dest_dir + binary_name + "/" + lang + ".lproj";
String fname = binary_dir + "/" + lang + ".lproj";
tmp_app_path->make_dir_recursive(fname);
Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
@ -1776,34 +1799,37 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
String dest_lib_file_path = dest_dir + static_lib_path.get_file();
Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path);
if (lib_copy_err != OK) {
ERR_PRINT("Can't copy '" + static_lib_path + "'.");
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not copy a file at path \"%s\" to \"%s\"."), static_lib_path, dest_lib_file_path));
return lib_copy_err;
}
}
}
String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/";
String iconset_dir = binary_dir + "/Images.xcassets/AppIcon.appiconset/";
err = OK;
if (!tmp_app_path->dir_exists(iconset_dir)) {
err = tmp_app_path->make_dir_recursive(iconset_dir);
}
if (err) {
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create a directory at path \"%s\"."), iconset_dir));
return err;
}
err = _export_icons(p_preset, iconset_dir);
if (err) {
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
{
bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
String launch_image_path = binary_dir + "/Images.xcassets/LaunchImage.launchimage/";
String splash_image_path = binary_dir + "/Images.xcassets/SplashImage.imageset/";
Ref<DirAccess> launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (launch_screen_da.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not access the filesystem."));
return ERR_CANT_CREATE;
}
@ -1816,10 +1842,11 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
}
err = _export_loading_screen_file(p_preset, splash_image_path);
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Failed to create a file at path \"%s\" with code %d."), splash_image_path, err));
} else {
print_line("Using Launch Images");
const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
const String launch_screen_path = binary_dir + "/Launch Screen.storyboard";
launch_screen_da->remove(launch_screen_path);
@ -1829,21 +1856,22 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
}
err = _export_loading_screen_images(p_preset, launch_image_path);
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Failed to create a file at path \"%s\" with code %d."), launch_image_path, err));
}
}
if (err) {
if (err != OK) {
return err;
}
print_line("Exporting additional assets");
_export_additional_assets(dest_dir + binary_name, libraries, assets);
_export_additional_assets(binary_dir, libraries, assets);
_add_assets_to_project(p_preset, project_file_data, assets);
String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
String project_file_name = binary_dir + ".xcodeproj/project.pbxproj";
{
Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE);
if (f.is_null()) {
ERR_PRINT("Can't write '" + project_file_name + "'.");
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not write to a file at path \"%s\"."), project_file_name));
return ERR_CANT_CREATE;
};
f->store_buffer(project_file_data.ptr(), project_file_data.size());
@ -1854,7 +1882,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
if (ep.step("Code-signing dylibs", 2)) {
return ERR_SKIP;
}
Ref<DirAccess> dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
Ref<DirAccess> dylibs_dir = DirAccess::open(binary_dir + "/dylibs");
ERR_FAIL_COND_V(dylibs_dir.is_null(), ERR_CANT_OPEN);
CodesignData codesign_data(p_preset, p_debug);
err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
@ -1871,10 +1899,11 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
if (ep.step("Making .xcarchive", 3)) {
return ERR_SKIP;
}
String archive_path = p_path.get_basename() + ".xcarchive";
List<String> archive_args;
archive_args.push_back("-project");
archive_args.push_back(dest_dir + binary_name + ".xcodeproj");
archive_args.push_back(binary_dir + ".xcodeproj");
archive_args.push_back("-scheme");
archive_args.push_back(binary_name);
archive_args.push_back("-sdk");
@ -1895,9 +1924,14 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
archive_args.push_back("-allowProvisioningUpdates");
archive_args.push_back("-archivePath");
archive_args.push_back(archive_path);
String archive_str;
err = OS::get_singleton()->execute("xcodebuild", archive_args, &archive_str, nullptr, true);
ERR_FAIL_COND_V(err, err);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), vformat(TTR("Failed to run xcodebuild with code %d"), err));
return err;
}
print_line("xcodebuild (.xcarchive):\n" + archive_str);
if (!archive_str.contains("** ARCHIVE SUCCEEDED **")) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), TTR("Xcode project build failed, see editor log for details."));
@ -1908,18 +1942,24 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
if (ep.step("Making .ipa", 4)) {
return ERR_SKIP;
}
List<String> export_args;
export_args.push_back("-exportArchive");
export_args.push_back("-archivePath");
export_args.push_back(archive_path);
export_args.push_back("-exportOptionsPlist");
export_args.push_back(dest_dir + binary_name + "/export_options.plist");
export_args.push_back(binary_dir + "/export_options.plist");
export_args.push_back("-allowProvisioningUpdates");
export_args.push_back("-exportPath");
export_args.push_back(dest_dir);
String export_str;
err = OS::get_singleton()->execute("xcodebuild", export_args, &export_str, nullptr, true);
ERR_FAIL_COND_V(err, err);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), vformat(TTR("Failed to run xcodebuild with code %d"), err));
return err;
}
print_line("xcodebuild (.ipa):\n" + export_str);
if (!export_str.contains("** EXPORT SUCCEEDED **")) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), TTR(".ipa export failed, see editor log for details."));

View File

@ -79,6 +79,7 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_dir_path);
if (export_as_zip) {
if (tmp_app_dir.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Could not create and open the directory: \"%s\""), tmp_dir_path));
return ERR_CANT_CREATE;
}
if (DirAccess::exists(tmp_dir_path)) {
@ -93,19 +94,18 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
// Export project.
Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, path, p_flags);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
// Save console wrapper.
if (err == OK) {
int con_scr = p_preset->get("debug/export_console_wrapper");
if ((con_scr == 1 && p_debug) || (con_scr == 2)) {
String scr_path = path.get_basename() + ".sh";
err = _export_debug_script(p_preset, pkg_name, path.get_file(), scr_path);
FileAccess::set_unix_permissions(scr_path, 0755);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Console Export"), TTR("Could not create console wrapper."));
}
int con_scr = p_preset->get("debug/export_console_wrapper");
if ((con_scr == 1 && p_debug) || (con_scr == 2)) {
String scr_path = path.get_basename() + ".sh";
err = _export_debug_script(p_preset, pkg_name, path.get_file(), scr_path);
FileAccess::set_unix_permissions(scr_path, 0755);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Console Export"), TTR("Could not create console wrapper."));
}
}

View File

@ -1266,10 +1266,16 @@ Error EditorExportPlatformMacOS::_export_debug_script(const Ref<EditorExportPres
Error EditorExportPlatformMacOS::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;
const String base_dir = p_path.get_base_dir();
if (!DirAccess::exists(base_dir)) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Target folder does not exist or is inaccessible: \"%s\""), base_dir));
return ERR_FILE_BAD_PATH;
}
EditorProgress ep("export", TTR("Exporting for macOS"), 3, true);
String src_pkg_name;
if (p_debug) {
src_pkg_name = p_preset->get("custom_template/debug");
} else {
@ -1280,16 +1286,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
String err;
src_pkg_name = find_export_template("macos.zip", &err);
if (src_pkg_name.is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found."));
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found.") + "\n" + err);
return ERR_FILE_NOT_FOUND;
}
}
if (!DirAccess::exists(p_path.get_base_dir())) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("The given export path doesn't exist."));
return ERR_FILE_BAD_PATH;
}
Ref<FileAccess> io_fa;
zlib_filefunc_def io = zipio_create_io(&io_fa);

View File

@ -259,6 +259,7 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese
_replace_strings(replaces, sw);
Error err = _write_or_error(sw.ptr(), sw.size(), dir.path_join(name + ".service.worker.js"));
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
@ -291,16 +292,19 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese
const String icon144_path = p_preset->get("progressive_web_app/icon_144x144");
err = _add_manifest_icon(p_path, icon144_path, 144, icons_arr);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
const String icon180_path = p_preset->get("progressive_web_app/icon_180x180");
err = _add_manifest_icon(p_path, icon180_path, 180, icons_arr);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
const String icon512_path = p_preset->get("progressive_web_app/icon_512x512");
err = _add_manifest_icon(p_path, icon512_path, 512, icons_arr);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
manifest["icons"] = icons_arr;
@ -308,6 +312,7 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese
CharString cs = Variant(manifest).to_json_string().utf8();
err = _write_or_error((const uint8_t *)cs.get_data(), cs.length(), dir.path_join(name + ".manifest.json"));
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
@ -439,6 +444,11 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p
const String base_path = p_path.get_basename();
const String base_name = p_path.get_file().get_basename();
if (!DirAccess::exists(base_dir)) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Target folder does not exist or is inaccessible: \"%s\""), base_dir));
return ERR_FILE_BAD_PATH;
}
// Find the correct template
String template_path = p_debug ? custom_debug : custom_release;
template_path = template_path.strip_edges();
@ -447,10 +457,6 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p
template_path = find_export_template(_get_template_name(extensions, p_debug));
}
if (!DirAccess::exists(base_dir)) {
return ERR_FILE_BAD_PATH;
}
if (!template_path.is_empty() && !FileAccess::exists(template_path)) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Template file not found: \"%s\"."), template_path));
return ERR_FILE_NOT_FOUND;
@ -480,6 +486,7 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p
// Extract templates.
error = _extract_template(template_path, base_dir, base_name, pwa);
if (error) {
// Message is supplied by the subroutine method.
return error;
}
@ -510,6 +517,7 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p
_fix_html(html, p_preset, base_name, p_debug, p_flags, shared_objects, file_sizes);
Error err = _write_or_error(html.ptr(), html.size(), p_path);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
html.resize(0);
@ -543,6 +551,7 @@ Error EditorExportPlatformWeb::export_project(const Ref<EditorExportPreset> &p_p
if (pwa) {
err = _build_pwa(p_preset, p_path, shared_objects);
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
}

View File

@ -226,6 +226,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_dir_path);
if (export_as_zip) {
if (tmp_app_dir.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Could not create and open the directory: \"%s\""), tmp_dir_path));
return ERR_CANT_CREATE;
}
if (DirAccess::exists(tmp_dir_path)) {
@ -242,8 +243,14 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
if (embedded) {
pck_path = pck_path.get_basename() + ".tmp";
}
Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, pck_path, p_flags);
if (p_preset->get("codesign/enable") && err == OK) {
if (err != OK) {
// Message is supplied by the subroutine method.
return err;
}
if (p_preset->get("codesign/enable")) {
_code_sign(p_preset, pck_path);
String wrapper_path = p_path.get_basename() + ".console.exe";
if (FileAccess::exists(wrapper_path)) {
@ -251,7 +258,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
}
}
if (embedded && err == OK) {
if (embedded) {
Ref<DirAccess> tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
err = tmp_dir->rename(pck_path, p_path);
if (err != OK) {