diff --git a/.ci/macos/build.sh b/.ci/macos/build.sh new file mode 100755 index 0000000000..0405194a6f --- /dev/null +++ b/.ci/macos/build.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +export LIBVULKAN_PATH="/opt/homebrew/lib/libvulkan.1.dylib" + +if [ -z "$BUILD_TYPE" ]; then + export BUILD_TYPE="Release" +fi + +if [ "$DEVEL" != "true" ]; then + export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DENABLE_QT_UPDATE_CHECKER=ON) +fi + +mkdir -p build +cd build + +cmake .. -GNinja \ + -DYUZU_TESTS=OFF \ + -DYUZU_USE_BUNDLED_QT=OFF \ + -DENABLE_QT_TRANSLATION=ON \ + -DYUZU_ENABLE_LTO=ON \ + -DUSE_DISCORD_PRESENCE=ON \ + -DYUZU_CMD=OFF \ + -DYUZU_ROOM_STANDALONE=OFF \ + -DCMAKE_CXX_FLAGS="-w" \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DYUZU_USE_PRECOMPILED_HEADERS=OFF \ + "${EXTRA_CMAKE_FLAGS[@]}" + +ninja diff --git a/.ci/macos/package.sh b/.ci/macos/package.sh new file mode 100755 index 0000000000..11e8b626ed --- /dev/null +++ b/.ci/macos/package.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# credit: escary and hauntek + +cd build +APP=./bin/eden.app + +macdeployqt "$APP" +macdeployqt "$APP" -always-overwrite + +# FixMachOLibraryPaths +find "$APP/Contents/Frameworks" ""$APP/Contents/MacOS"" -type f \( -name "*.dylib" -o -perm +111 \) | while read file; do + if file "$file" | grep -q "Mach-O"; then + otool -L "$file" | awk '/@rpath\// {print $1}' | while read lib; do + lib_name="${lib##*/}" + new_path="@executable_path/../Frameworks/$lib_name" + install_name_tool -change "$lib" "$new_path" "$file" + done + + if [[ "$file" == *.dylib ]]; then + lib_name="${file##*/}" + new_id="@executable_path/../Frameworks/$lib_name" + install_name_tool -id "$new_id" "$file" + fi + fi +done +codesign --deep --force --verify --verbose --sign - "$APP" + +ZIP_NAME="eden-macos.zip" +mkdir -p artifacts + +mv $APP . +7z a -tzip "$ZIP_NAME" eden.app +mv "$ZIP_NAME" artifacts/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b9d19b3c1b..3ec1d5d825 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,7 +495,11 @@ add_subdirectory(externals) if (ENABLE_QT) if (YUZU_USE_BUNDLED_QT) - download_qt(6.8.3) + if (APPLE) + download_qt(6.7.3) + else() + download_qt(6.8.3) + endif() else() message(STATUS "Using system Qt") if (NOT Qt6_DIR) diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 3e9bc26d69..61f9a2cf64 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -221,7 +221,7 @@ set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") if (NOT EXISTS ${MOLTENVK_DIR}) if (NOT EXISTS ${MOLTENVK_TAR}) - file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.10-rc2/MoltenVK-all.tar + file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.11-artifacts/MoltenVK-all.tar ${MOLTENVK_TAR} SHOW_PROGRESS) endif() diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 9259639107..f30dfaf096 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1373,8 +1373,8 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, // these images that aren't size-compatible if (BytesPerBlock(src.info.format) != BytesPerBlock(dst.info.format)) { auto oneCopy = VideoCommon::ImageCopy{ - .src_offset = VideoCommon::Offset3D(0, 0, 0), - .dst_offset = VideoCommon::Offset3D(0, 0, 0), + .src_offset = VideoCommon::Offset3D{0, 0, 0}, + .dst_offset = VideoCommon::Offset3D{0, 0, 0}, .extent = dst.info.size }; return ReinterpretImage(dst, src, std::span{&oneCopy, 1}); diff --git a/src/video_core/vulkan_common/vulkan.h b/src/video_core/vulkan_common/vulkan.h index 62aa132915..4b5df1e8f1 100644 --- a/src/video_core/vulkan_common/vulkan.h +++ b/src/video_core/vulkan_common/vulkan.h @@ -15,7 +15,12 @@ #define VK_USE_PLATFORM_WAYLAND_KHR #endif +#ifdef __APPLE__ +//#include #include +#else +#include +#endif // Sanitize macros #undef CreateEvent diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 34f2ba455a..ba4cce1620 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -374,7 +374,7 @@ if (APPLE) if (NOT USE_SYSTEM_MOLTENVK) set(MOLTENVK_PLATFORM "macOS") - set(MOLTENVK_VERSION "v1.3.0") + set(MOLTENVK_VERSION "v1.2.11-artifacts") download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) endif() find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp index 1c1342ff18..6b131c88f3 100644 --- a/src/yuzu/debugger/console.cpp +++ b/src/yuzu/debugger/console.cpp @@ -2,9 +2,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later #ifdef _WIN32 -#include - #include +#include +#endif + +#ifdef __APPLE__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/fs/path_util.h" + +extern char** environ; #endif #include "common/logging/backend.h" @@ -12,18 +26,76 @@ #include "yuzu/uisettings.h" namespace Debugger { +#ifdef __APPLE__ +namespace { + +pid_t g_terminal_pid = -1; +int g_saved_out = -1; +int g_saved_err = -1; + +std::string GetLogFilePath() { + std::string dir = Common::FS::GetEdenPathString(Common::FS::EdenPath::LogDir); + if (!dir.empty() && dir.back() != '/') + dir.push_back('/'); + return dir + "eden_log.txt"; +} + +void ShowMacConsole() { + const std::string logfile = GetLogFilePath(); + if (logfile.empty()) + return; + + g_saved_out = dup(STDOUT_FILENO); + g_saved_err = dup(STDERR_FILENO); + + int fd = ::open(logfile.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd == -1) + return; + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + +const std::string shell_cmd = + "osascript -e 'tell application \"Terminal\" " + "to do script \"printf \\\\e]1;Eden logs\\\\a\\\\e]2;Eden logs\\\\a; " + "tail -n +1 -F " + logfile + "\"'"; + + posix_spawnp(&g_terminal_pid, "/bin/sh", nullptr, nullptr, + (char* const[]){const_cast("/bin/sh"), const_cast("-c"), + const_cast(shell_cmd.c_str()), nullptr}, + environ); +} + +void HideMacConsole() { + if (g_terminal_pid > 0) { + kill(g_terminal_pid, SIGTERM); + g_terminal_pid = -1; + } + if (g_saved_out != -1) { + dup2(g_saved_out, STDOUT_FILENO); + close(g_saved_out); + g_saved_out = -1; + } + if (g_saved_err != -1) { + dup2(g_saved_err, STDERR_FILENO); + close(g_saved_err); + g_saved_err = -1; + } +} +} // namespace +#endif // __APPLE__ + void ToggleConsole() { static bool console_shown = false; - if (console_shown == UISettings::values.show_console.GetValue()) { + const bool want_console = UISettings::values.show_console.GetValue(); + if (console_shown == want_console) return; - } else { - console_shown = UISettings::values.show_console.GetValue(); - } + console_shown = want_console; using namespace Common::Log; #if defined(_WIN32) && !defined(_DEBUG) FILE* temp; - if (UISettings::values.show_console) { + if (want_console) { if (AllocConsole()) { // The first parameter for freopen_s is a out parameter, so we can just ignore it freopen_s(&temp, "CONIN$", "r", stdin); @@ -43,6 +115,12 @@ void ToggleConsole() { } } #else +#if defined(__APPLE__) + if (want_console) + ShowMacConsole(); + else + HideMacConsole(); +#endif SetColorConsoleBackendEnabled(UISettings::values.show_console.GetValue()); #endif }