diff --git a/drivers/apple/os_log_logger.cpp b/drivers/apple/os_log_logger.cpp new file mode 100644 index 00000000000..23b0fe2ae65 --- /dev/null +++ b/drivers/apple/os_log_logger.cpp @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* os_log_logger.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/**************************************************************************/ + +#include "os_log_logger.h" + +#include "core/string/print_string.h" + +#include // For malloc/free + +OsLogLogger::OsLogLogger(const char *p_subsystem) { + const char *subsystem = p_subsystem; + if (!subsystem) { + subsystem = "org.godotengine.godot"; + os_log_info(OS_LOG_DEFAULT, "Missing subsystem for os_log logging; using %{public}s", subsystem); + } + + log = os_log_create(subsystem, "engine"); + error_log = os_log_create(subsystem, error_type_string(ErrorType::ERR_ERROR)); + warning_log = os_log_create(subsystem, error_type_string(ErrorType::ERR_WARNING)); + script_log = os_log_create(subsystem, error_type_string(ErrorType::ERR_SCRIPT)); + shader_log = os_log_create(subsystem, error_type_string(ErrorType::ERR_SHADER)); +} + +void OsLogLogger::logv(const char *p_format, va_list p_list, bool p_err) { + constexpr int static_buf_size = 1024; + char static_buf[static_buf_size] = { '\0' }; + char *buf = static_buf; + va_list list_copy; + va_copy(list_copy, p_list); + int len = vsnprintf(buf, static_buf_size, p_format, p_list); + if (len >= static_buf_size) { + buf = (char *)Memory::alloc_static(len + 1); + vsnprintf(buf, len + 1, p_format, list_copy); + } + va_end(list_copy); + + // Choose appropriate log type based on error flag. + os_log_type_t log_type = p_err ? OS_LOG_TYPE_ERROR : OS_LOG_TYPE_INFO; + os_log_with_type(log, log_type, "%{public}s", buf); + + if (len >= static_buf_size) { + Memory::free_static(buf); + } +} + +void OsLogLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector> &p_script_backtraces) { + os_log_t selected_log; + switch (p_type) { + case ERR_WARNING: + selected_log = warning_log; + break; + case ERR_SCRIPT: + selected_log = script_log; + break; + case ERR_SHADER: + selected_log = shader_log; + break; + case ERR_ERROR: + default: + selected_log = error_log; + break; + } + const char *err_details; + if (p_rationale && *p_rationale) { + err_details = p_rationale; + } else { + err_details = p_code; + } + + // Choose log level based on error type. + os_log_type_t log_type; + switch (p_type) { + case ERR_WARNING: + log_type = OS_LOG_TYPE_DEFAULT; + break; + case ERR_ERROR: + case ERR_SCRIPT: + case ERR_SHADER: + default: + log_type = OS_LOG_TYPE_ERROR; + break; + } + + // Append script backtraces, if any. + String back_trace; + for (const Ref &backtrace : p_script_backtraces) { + if (backtrace.is_valid() && !backtrace->is_empty()) { + back_trace += "\n"; + back_trace += backtrace->format(strlen(error_type_indent(p_type))); + } + } + + if (back_trace.is_empty()) { + os_log_with_type(selected_log, log_type, "%{public}s:%d:%{public}s(): %{public}s %{public}s", p_file, p_line, p_function, err_details, p_code); + } else { + os_log_with_type(selected_log, log_type, "%{public}s:%d:%{public}s(): %{public}s %{public}s%{public}s", p_file, p_line, p_function, err_details, p_code, back_trace.utf8().ptr()); + } +} diff --git a/drivers/apple_embedded/terminal_logger_apple_embedded.h b/drivers/apple/os_log_logger.h similarity index 73% rename from drivers/apple_embedded/terminal_logger_apple_embedded.h rename to drivers/apple/os_log_logger.h index 046d3001758..932540cabcd 100644 --- a/drivers/apple_embedded/terminal_logger_apple_embedded.h +++ b/drivers/apple/os_log_logger.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* terminal_logger_apple_embedded.h */ +/* os_log_logger.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,13 +30,26 @@ #pragma once -#ifdef APPLE_EMBEDDED_ENABLED - #include "core/io/logger.h" -class TerminalLoggerAppleEmbedded : public StdLogger { -public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector> &p_script_backtraces = {}) override; -}; +#include -#endif // APPLE_EMBEDDED_ENABLED +/** + * @brief Apple unified logging system integration for Godot Engine. + */ +class OsLogLogger : public Logger { + os_log_t log; + os_log_t error_log; + os_log_t warning_log; + os_log_t script_log; + os_log_t shader_log; + +public: + void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0; + void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector> &p_script_backtraces = {}) override; + + /** + * @brief Constructs an OsLogLogger with the specified subsystem identifier, which is normally the bundle identifier. + */ + OsLogLogger(const char *p_subsystem); +}; diff --git a/drivers/apple_embedded/os_apple_embedded.h b/drivers/apple_embedded/os_apple_embedded.h index 6bbf3185231..148fada9a08 100644 --- a/drivers/apple_embedded/os_apple_embedded.h +++ b/drivers/apple_embedded/os_apple_embedded.h @@ -83,6 +83,8 @@ private: void deinitialize_modules(); + mutable String remote_fs_dir; + public: static OS_AppleEmbedded *get_singleton(); @@ -115,6 +117,7 @@ public: virtual String get_cache_path() const override; virtual String get_temp_path() const override; + virtual String get_resource_dir() const override; virtual String get_locale() const override; @@ -125,6 +128,8 @@ public: virtual bool _check_internal_feature_support(const String &p_feature) override; + virtual Error setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path) override; + void on_focus_out(); void on_focus_in(); diff --git a/drivers/apple_embedded/os_apple_embedded.mm b/drivers/apple_embedded/os_apple_embedded.mm index fa71c96e100..6468c688aca 100644 --- a/drivers/apple_embedded/os_apple_embedded.mm +++ b/drivers/apple_embedded/os_apple_embedded.mm @@ -35,14 +35,12 @@ #import "app_delegate_service.h" #import "display_server_apple_embedded.h" #import "godot_view_apple_embedded.h" -#import "terminal_logger_apple_embedded.h" #import "view_controller.h" #include "core/config/project_settings.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" -#include "core/io/file_access_pack.h" -#include "drivers/unix/syslog_logger.h" +#import "drivers/apple/os_log_logger.h" #include "main/main.h" #import @@ -142,7 +140,7 @@ OS_AppleEmbedded::OS_AppleEmbedded() { main_loop = nullptr; Vector loggers; - loggers.push_back(memnew(TerminalLoggerAppleEmbedded)); + loggers.push_back(memnew(OsLogLogger(NSBundle.mainBundle.bundleIdentifier.UTF8String))); _set_logger(memnew(CompositeLogger(loggers))); AudioDriverManager::add_driver(&audio_driver); @@ -383,6 +381,18 @@ String OS_AppleEmbedded::get_temp_path() const { return ret; } +String OS_AppleEmbedded::get_resource_dir() const { +#ifdef TOOLS_ENABLED + return OS_Unix::get_resource_dir(); +#else + if (remote_fs_dir.is_empty()) { + return OS_Unix::get_resource_dir(); + } else { + return remote_fs_dir; + } +#endif +} + String OS_AppleEmbedded::get_locale() const { NSString *preferredLanguage = [NSLocale preferredLanguages].firstObject; @@ -641,6 +651,15 @@ bool OS_AppleEmbedded::_check_internal_feature_support(const String &p_feature) return false; } +Error OS_AppleEmbedded::setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path) { + r_project_path = OS::get_user_data_dir(); + Error err = OS_Unix::setup_remote_filesystem(p_server_host, p_port, p_password, r_project_path); + if (err == OK) { + remote_fs_dir = r_project_path; + } + return err; +} + void OS_AppleEmbedded::on_focus_out() { if (is_focused) { is_focused = false; diff --git a/drivers/apple_embedded/terminal_logger_apple_embedded.mm b/drivers/apple_embedded/terminal_logger_apple_embedded.mm deleted file mode 100644 index 4889b244f25..00000000000 --- a/drivers/apple_embedded/terminal_logger_apple_embedded.mm +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************/ -/* terminal_logger_apple_embedded.mm */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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 "terminal_logger_apple_embedded.h" - -#ifdef APPLE_EMBEDDED_ENABLED - -#import - -void TerminalLoggerAppleEmbedded::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector> &p_script_backtraces) { - if (!should_log(true)) { - return; - } - - const char *err_details; - if (p_rationale && p_rationale[0]) { - err_details = p_rationale; - } else { - err_details = p_code; - } - - os_log_error(OS_LOG_DEFAULT, - "%{public}s: %{public}s\nat: %{public}s (%{public}s:%i)", - error_type_string(p_type), err_details, p_function, p_file, p_line); - - for (const Ref &backtrace : p_script_backtraces) { - if (!backtrace->is_empty()) { - os_log_error(OS_LOG_DEFAULT, "%{public}s", backtrace->format().utf8().get_data()); - } - } -} - -#endif // APPLE_EMBEDDED_ENABLED diff --git a/editor/export/editor_export_platform_apple_embedded.cpp b/editor/export/editor_export_platform_apple_embedded.cpp index 3cef0355be4..9565fc6630f 100644 --- a/editor/export/editor_export_platform_apple_embedded.cpp +++ b/editor/export/editor_export_platform_apple_embedded.cpp @@ -42,6 +42,7 @@ #include "editor/import/resource_importer_texture_settings.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/themes/editor_scale.h" +#include "main/main.h" #include "modules/modules_enabled.gen.h" // For mono. #include "modules/svg/image_loader_svg.h" @@ -2161,15 +2162,21 @@ Error EditorExportPlatformAppleEmbedded::_export_project_helper(const Refexecute("xcodebuild", archive_args, &archive_str, nullptr, true); - if (err != OK) { + bool archive_succeeded = false; + int result = _execute("xcodebuild", archive_args, [&archive_succeeded](const String &p_data) { + print_line(p_data); + DisplayServer::get_singleton()->process_events(); + Main::iteration(); + if (!archive_succeeded && p_data.contains("** ARCHIVE SUCCEEDED **")) { + archive_succeeded = true; + } + }); + if (result != 0) { add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), vformat(TTR("Failed to run xcodebuild with code %d"), err)); - return err; + return ERR_CANT_CREATE; } - print_line("xcodebuild (.xcarchive):\n" + archive_str); - if (!archive_str.contains("** ARCHIVE SUCCEEDED **")) { + if (!archive_succeeded) { add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), TTR("Xcode project build failed, see editor log for details.")); return FAILED; } @@ -2189,15 +2196,21 @@ Error EditorExportPlatformAppleEmbedded::_export_project_helper(const Refexecute("xcodebuild", export_args, &export_str, nullptr, true); - if (err != OK) { + bool export_succeeded = false; + result = _execute("xcodebuild", export_args, [&export_succeeded](const String &p_data) { + print_line(p_data); + DisplayServer::get_singleton()->process_events(); + Main::iteration(); + if (!export_succeeded && p_data.contains("** EXPORT SUCCEEDED **")) { + export_succeeded = true; + } + }); + if (result != 0) { 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 **")) { + if (!export_succeeded) { add_message(EXPORT_MESSAGE_ERROR, TTR("Xcode Build"), TTR(".ipa export failed, see editor log for details.")); return FAILED; } @@ -2390,6 +2403,17 @@ bool EditorExportPlatformAppleEmbedded::_check_xcode_install() { void EditorExportPlatformAppleEmbedded::_check_for_changes_poll_thread(void *ud) { EditorExportPlatformAppleEmbedded *ea = static_cast(ud); + String device_types; + bool first = true; + for (const String &d : ea->get_device_types()) { + if (first) { + first = false; + } else { + device_types += "|"; + } + device_types += d; + } + while (!ea->quit_request.is_set()) { // Nothing to do if we already know the plugins have changed. if (!ea->plugins_changed.is_set()) { @@ -2417,7 +2441,7 @@ void EditorExportPlatformAppleEmbedded::_check_for_changes_poll_thread(void *ud) if (EditorSettings::get_singleton()->has_setting(ios_deploy_setting)) { String idepl = EDITOR_GET(ios_deploy_setting); if (ea->has_runnable_preset.is_set() && !idepl.is_empty()) { - String devices; + String devices_json; List args; args.push_back("-c"); args.push_back("-timeout"); @@ -2427,12 +2451,12 @@ void EditorExportPlatformAppleEmbedded::_check_for_changes_poll_thread(void *ud) args.push_back("-I"); int ec = 0; - Error err = OS::get_singleton()->execute(idepl, args, &devices, &ec, true); + Error err = OS::get_singleton()->execute(idepl, args, &devices_json, &ec, true); if (err == OK && ec == 0) { Ref json; json.instantiate(); - devices = "{ \"devices\":[" + devices.replace("}{", "},{") + "]}"; - err = json->parse(devices); + devices_json = "{ \"devices\":[" + devices_json.replace("}{", "},{") + "]}"; + err = json->parse(devices_json); if (err == OK) { Dictionary data = json->get_data(); Array devices = data["devices"]; @@ -2454,7 +2478,7 @@ void EditorExportPlatformAppleEmbedded::_check_for_changes_poll_thread(void *ud) } // Enum devices (via Xcode). if (ea->has_runnable_preset.is_set() && _check_xcode_install() && (FileAccess::exists("/usr/bin/xcrun") || FileAccess::exists("/bin/xcrun"))) { - String devices; + String devices_json; List args; args.push_back("devicectl"); args.push_back("list"); @@ -2462,12 +2486,18 @@ void EditorExportPlatformAppleEmbedded::_check_for_changes_poll_thread(void *ud) args.push_back("-j"); args.push_back("-"); args.push_back("-q"); + // Add a timeout, so the process doesn't hang indefinitely, which can prevent Godot shutting down. + args.push_back("--timeout"); + args.push_back("5"); + args.push_back("--filter"); + args.push_back(vformat("hardwareProperties.deviceType MATCHES '%s'", device_types)); + int ec = 0; - Error err = OS::get_singleton()->execute("xcrun", args, &devices, &ec, true); + Error err = OS::get_singleton()->execute("xcrun", args, &devices_json, &ec, true); if (err == OK && ec == 0) { Ref json; json.instantiate(); - err = json->parse(devices); + err = json->parse(devices_json); if (err == OK) { const Dictionary &data = json->get_data(); const Dictionary &result = data["result"]; @@ -2542,6 +2572,115 @@ void EditorExportPlatformAppleEmbedded::_update_preset_status() { } devices_changed.set(); } + +class FileReader { + Ref f; + LocalVector buf; + + void append_span(Span p_span, String &p_data) { + uint32_t old_size = p_data.size(); + if (p_data.append_utf8(p_span) != OK) { + p_data.resize_uninitialized(old_size); // Back up to original size. + if (old_size > 0) { + p_data[old_size - 1] = '\0'; + } + p_data.append_latin1(p_span); + } + } + +public: + uint32_t get_lines(String &p_data) { + uint64_t available = f->get_length() - f->get_position(); + if (available == 0) { + return 0; + } + + uint32_t start = buf.size(); + buf.resize_uninitialized(buf.size() + available); + f->get_buffer((uint8_t *)buf.ptr() + start, available); + const char *end = &buf[buf.size() - 1]; + const char *p = end; + uint32_t n = available; + bool found = false; + // Scan for a newline starting from the end of the appended bytes. + while (n--) { + if (*p == '\n') { + found = true; + break; + } + p--; + } + if (found) { + size_t len = static_cast(p - buf.ptr()) + 1; + Span new_data(buf.ptr(), len); + append_span(new_data, p_data); + size_t remain = static_cast(end - p); + // If there is unprocessed data in the buffer, move it to the front. + if (remain > 0) { + // Move to next char after '\n'. + p++; + memmove(buf.ptr(), p, remain); + } + buf.resize_uninitialized(remain); + } + return available; + } + + // Flush any remaining data. + uint32_t flush(String &p_data) { + Span new_data = buf.span(); + if (new_data.size() > 0) { + append_span(new_data, p_data); + } + return new_data.size(); + } + + FileReader(Ref p_f) : + f(p_f) { + } +}; + +int EditorExportPlatformAppleEmbedded::_execute(const String &p_path, const List &p_arguments, std::function p_on_data) { + Dictionary pipe_info = OS::get_singleton()->execute_with_pipe(p_path, p_arguments, false); + ERR_FAIL_COND_V_MSG(pipe_info.is_empty(), 1, "execute_with_pipe failed"); + + Ref fa_stdout = pipe_info["stdio"]; + Ref fa_stderr = pipe_info["stderr"]; + OS::ProcessID pid = pipe_info["pid"]; + + FileReader stdout_r(fa_stdout); + FileReader stderr_r(fa_stderr); + + while (true) { + String output; + stdout_r.get_lines(output); + stderr_r.get_lines(output); + if (!output.is_empty()) { + p_on_data(output); + } + + // If the process is no longer running and no new data arrived, we're done. + if (output.is_empty() && !OS::get_singleton()->is_process_running(pid)) { + break; + } + + OS::get_singleton()->delay_usec(1000); + } + + // Flush any remaining content + String output; + stdout_r.flush(output); + stderr_r.flush(output); + if (!output.is_empty()) { + p_on_data(output); + } + + fa_stdout->close(); + fa_stderr->close(); + + return OS::get_singleton()->get_process_exit_code(pid); +} + #endif Error EditorExportPlatformAppleEmbedded::run(const Ref &p_preset, int p_device, BitField p_debug_flags) { @@ -2689,12 +2828,9 @@ Error EditorExportPlatformAppleEmbedded::run(const Ref &p_pr args.push_back(EditorPaths::get_singleton()->get_temp_dir().path_join(id).path_join("export.xcarchive/Products/Applications/export.app")); String log; - int ec; - err = OS::get_singleton()->execute("xcrun", args, &log, &ec, true); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Run"), TTR("Could not start device executable.")); - CLEANUP_AND_RETURN(err); - } + int ec = _execute("xcrun", args, [&log](const String &p_data) { + log.append_utf32(p_data.span()); + }); if (ec != 0) { print_line("device install:\n" + log); add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Installation failed, see editor log for details.")); @@ -2719,12 +2855,9 @@ Error EditorExportPlatformAppleEmbedded::run(const Ref &p_pr } String log; - int ec; - err = OS::get_singleton()->execute("xcrun", args, &log, &ec, true); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Run"), TTR("Could not start devicectl executable.")); - CLEANUP_AND_RETURN(err); - } + int ec = _execute("xcrun", args, [&log](const String &p_data) { + log.append_utf32(p_data.span()); + }); if (ec != 0) { print_line("devicectl launch:\n" + log); add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Running failed, see editor log for details.")); @@ -2755,7 +2888,6 @@ EditorExportPlatformAppleEmbedded::EditorExportPlatformAppleEmbedded(const char devices_changed.set(); #ifdef MACOS_ENABLED _update_preset_status(); - check_for_changes_thread.start(_check_for_changes_poll_thread, this); #endif } } diff --git a/editor/export/editor_export_platform_apple_embedded.h b/editor/export/editor_export_platform_apple_embedded.h index 1bc5575adc4..c79c10ac4a4 100644 --- a/editor/export/editor_export_platform_apple_embedded.h +++ b/editor/export/editor_export_platform_apple_embedded.h @@ -46,6 +46,7 @@ #include "scene/resources/image_texture.h" #include +#include // Optional environment variables for defining confidential information. If any // of these is set, they will override the values set in the credentials file. @@ -91,6 +92,15 @@ class EditorExportPlatformAppleEmbedded : public EditorExportPlatform { static bool _check_xcode_install(); static void _check_for_changes_poll_thread(void *ud); void _update_preset_status(); + +protected: + void _start_remote_device_poller_thread() { + check_for_changes_thread.start(_check_for_changes_poll_thread, this); + } + + int _execute(const String &p_path, const List &p_arguments, std::function p_on_data); + +private: #endif typedef Error (*FileHandler)(String p_file, void *p_userdata); @@ -169,6 +179,7 @@ protected: virtual String get_platform_name() const = 0; virtual String get_sdk_name() const = 0; + virtual const Vector get_device_types() const = 0; virtual String get_minimum_deployment_target() const = 0; virtual void get_preset_features(const Ref &p_preset, List *r_features) const override; diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 2ba36c56f56..1f40fe27dd7 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -33,8 +33,13 @@ #include "logo_svg.gen.h" #include "run_icon_svg.gen.h" +Vector EditorExportPlatformIOS::device_types({ "iPhone", "iPad" }); + EditorExportPlatformIOS::EditorExportPlatformIOS() : EditorExportPlatformAppleEmbedded(_ios_logo_svg, _ios_run_icon_svg) { +#ifdef MACOS_ENABLED + _start_remote_device_poller_thread(); +#endif } EditorExportPlatformIOS::~EditorExportPlatformIOS() { diff --git a/platform/ios/export/export_plugin.h b/platform/ios/export/export_plugin.h index 1dd210d2607..f7892df3ec5 100644 --- a/platform/ios/export/export_plugin.h +++ b/platform/ios/export/export_plugin.h @@ -35,9 +35,11 @@ class EditorExportPlatformIOS : public EditorExportPlatformAppleEmbedded { GDCLASS(EditorExportPlatformIOS, EditorExportPlatformAppleEmbedded); - virtual String get_platform_name() const override { return "ios"; } + static Vector device_types; + virtual String get_platform_name() const override { return "ios"; } virtual String get_sdk_name() const override { return "iphoneos"; } + virtual const Vector get_device_types() const override { return device_types; } virtual String get_minimum_deployment_target() const override { return "14.0"; } diff --git a/platform/macos/SCsub b/platform/macos/SCsub index f1ee9c7d814..19b0acb74f3 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -10,7 +10,6 @@ files = [ "godot_application.mm", "godot_application_delegate.mm", "crash_handler_macos.mm", - "macos_terminal_logger.mm", "display_server_macos_base.mm", "display_server_embedded.mm", "display_server_macos.mm", diff --git a/platform/macos/macos_terminal_logger.h b/platform/macos/macos_terminal_logger.h deleted file mode 100644 index ed45563b7d3..00000000000 --- a/platform/macos/macos_terminal_logger.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************/ -/* macos_terminal_logger.h */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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. */ -/**************************************************************************/ - -#pragma once - -#ifdef MACOS_ENABLED - -#include "core/io/logger.h" - -class MacOSTerminalLogger : public StdLogger { -public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector> &p_script_backtraces = {}) override; -}; - -#endif // MACOS_ENABLED diff --git a/platform/macos/macos_terminal_logger.mm b/platform/macos/macos_terminal_logger.mm deleted file mode 100644 index d93aed1b288..00000000000 --- a/platform/macos/macos_terminal_logger.mm +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************/ -/* macos_terminal_logger.mm */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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 "macos_terminal_logger.h" - -#ifdef MACOS_ENABLED - -#include - -void MacOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector> &p_script_backtraces) { - if (!should_log(true)) { - return; - } - - const char *err_details; - if (p_rationale && p_rationale[0]) { - err_details = p_rationale; - } else { - err_details = p_code; - } - - const char *bold_color; - const char *normal_color; - switch (p_type) { - case ERR_WARNING: - bold_color = "\E[1;33m"; - normal_color = "\E[0;93m"; - break; - case ERR_SCRIPT: - bold_color = "\E[1;35m"; - normal_color = "\E[0;95m"; - break; - case ERR_SHADER: - bold_color = "\E[1;36m"; - normal_color = "\E[0;96m"; - break; - case ERR_ERROR: - default: - bold_color = "\E[1;31m"; - normal_color = "\E[0;91m"; - break; - } - - os_log_error(OS_LOG_DEFAULT, - "%{public}s: %{public}s\nat: %{public}s (%{public}s:%i)", - error_type_string(p_type), err_details, p_function, p_file, p_line); - logf_error("%s%s:%s %s\n", bold_color, error_type_string(p_type), normal_color, err_details); - logf_error("\E[0;90m%sat: %s (%s:%i)\E[0m\n", error_type_indent(p_type), p_function, p_file, p_line); - - for (const Ref &backtrace : p_script_backtraces) { - if (!backtrace->is_empty()) { - os_log_error(OS_LOG_DEFAULT, "%{public}s", backtrace->format().utf8().get_data()); - logf_error("\E[0;90m%s\E[0m\n", backtrace->format(strlen(error_type_indent(p_type))).utf8().get_data()); - } - } -} - -#endif // MACOS_ENABLED diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index 2bbd3c2c186..09a538bfa0d 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -37,10 +37,10 @@ #import "display_server_macos.h" #import "godot_application.h" #import "godot_application_delegate.h" -#import "macos_terminal_logger.h" #include "core/crypto/crypto_core.h" #include "core/version_generated.gen.h" +#include "drivers/apple/os_log_logger.h" #include "main/main.h" #include @@ -1023,9 +1023,9 @@ OS_MacOS::OS_MacOS(const char *p_execpath, int p_argc, char **p_argv) { } [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"]; } - Vector loggers; - loggers.push_back(memnew(MacOSTerminalLogger)); + loggers.push_back(memnew(OsLogLogger(NSBundle.mainBundle.bundleIdentifier.UTF8String))); + loggers.push_back(memnew(UnixTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); #ifdef COREAUDIO_ENABLED diff --git a/platform/visionos/export/export_plugin.cpp b/platform/visionos/export/export_plugin.cpp index 8c67a011854..5f188a3fdb7 100644 --- a/platform/visionos/export/export_plugin.cpp +++ b/platform/visionos/export/export_plugin.cpp @@ -33,8 +33,13 @@ #include "logo_svg.gen.h" #include "run_icon_svg.gen.h" +Vector EditorExportPlatformVisionOS::device_types({ "realityDevice" }); + EditorExportPlatformVisionOS::EditorExportPlatformVisionOS() : EditorExportPlatformAppleEmbedded(_visionos_logo_svg, _visionos_run_icon_svg) { +#ifdef MACOS_ENABLED + _start_remote_device_poller_thread(); +#endif } EditorExportPlatformVisionOS::~EditorExportPlatformVisionOS() { diff --git a/platform/visionos/export/export_plugin.h b/platform/visionos/export/export_plugin.h index 1deb7361af2..39e95af4e49 100644 --- a/platform/visionos/export/export_plugin.h +++ b/platform/visionos/export/export_plugin.h @@ -35,9 +35,11 @@ class EditorExportPlatformVisionOS : public EditorExportPlatformAppleEmbedded { GDCLASS(EditorExportPlatformVisionOS, EditorExportPlatformAppleEmbedded); - virtual String get_platform_name() const override { return "visionos"; } + static Vector device_types; + virtual String get_platform_name() const override { return "visionos"; } virtual String get_sdk_name() const override { return "xros"; } + virtual const Vector get_device_types() const override { return device_types; } virtual String get_minimum_deployment_target() const override { return "2.0"; }