diff --git a/.github/linux/appimage.sh b/.github/linux/appimage.sh index bde546e..9b0d2d7 100755 --- a/.github/linux/appimage.sh +++ b/.github/linux/appimage.sh @@ -13,9 +13,8 @@ else fi curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage" -curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/raw/master/linuxdeploy-plugin-gtk.sh" -chmod a+x linuxdeploy* +chmod a+x "linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage" mkdir -p AppDir/usr/bin cp BM64Recompiled AppDir/usr/bin/ @@ -26,20 +25,22 @@ cp .github/linux/BM64Recompiled.desktop AppDir/ "./linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage" --appimage-extract mv squashfs-root/ deploy -./deploy/AppRun --appdir=AppDir/ -d AppDir/BM64Recompiled.desktop -i AppDir/BM64Recompiled.png -e AppDir/usr/bin/BM64Recompiled --plugin gtk -sed -i 's/exec/#exec/g' AppDir/AppRun -echo 'if [ -f "portable.txt" ]; then' >> AppDir/AppRun -echo ' APP_FOLDER_PATH=$PWD' >> AppDir/AppRun -echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun -echo ' APP_FOLDER_PATH=$APP_FOLDER_PATH ./BM64Recompiled' >> AppDir/AppRun -echo 'else' >> AppDir/AppRun -echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun -echo ' ./BM64Recompiled' >> AppDir/AppRun -echo 'fi' >> AppDir/AppRun +./deploy/AppRun --appdir=AppDir/ -d AppDir/BM64Recompiled.desktop -i AppDir/BM64Recompiled.png -e AppDir/usr/bin/BM64Recompiled -# Remove conflicting libraries -rm -rf AppDir/usr/lib/libgmodule* -rm -rf AppDir/usr/lib/gio/modules/*.so -rm -rf AppDir/usr/lib/libwayland* +# linuxdeploy may create AppRun as a symlink to the binary; remove it first +# so we don't overwrite the actual executable through the symlink. +rm -f AppDir/AppRun +cat > AppDir/AppRun << 'APPRUN' +#!/bin/bash +this_dir="$(dirname "$(readlink -f "$0")")" +export LD_LIBRARY_PATH="$this_dir/usr/lib:$LD_LIBRARY_PATH" +if [ -f "portable.txt" ]; then + APP_FOLDER_PATH="$PWD" exec "$this_dir/usr/bin/BM64Recompiled" "$@" +else + cd "$this_dir/usr/bin/" + exec ./BM64Recompiled "$@" +fi +APPRUN +chmod +x AppDir/AppRun ./deploy/usr/bin/linuxdeploy-plugin-appimage --appdir=AppDir diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 1cb3086..6e165c1 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -37,7 +37,7 @@ jobs: - name: Install Linux Dependencies run: | sudo apt-get update - sudo apt-get install -y ninja-build libsdl2-dev libgtk-3-dev lld llvm clang-15 libfuse2 + sudo apt-get install -y ninja-build libsdl2-dev libdbus-1-dev lld llvm clang-15 libfuse2 # Install SDL2 echo ::group::install SDL2 @@ -185,7 +185,7 @@ jobs: - name: Install Linux Dependencies run: | sudo apt-get update - sudo apt-get install -y ninja-build libsdl2-dev libgtk-3-dev lld llvm clang-15 libfuse2 + sudo apt-get install -y ninja-build libsdl2-dev libdbus-1-dev lld llvm clang-15 libfuse2 # Install SDL2 echo ::group::install SDL2 diff --git a/BUILDING.md b/BUILDING.md index e1dfea4..03db6df 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -23,7 +23,7 @@ For Linux the instructions for Ubuntu are provided, but you can find the equival ```bash # For Ubuntu, simply run: -sudo apt-get install cmake ninja libsdl2-dev libgtk-3-dev lld llvm clang-15 +sudo apt-get install cmake ninja libsdl2-dev libdbus-1-dev lld llvm clang-15 ``` ### Windows diff --git a/CMakeLists.txt b/CMakeLists.txt index c104f86..a52b053 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ endif() if (CMAKE_SYSTEM_NAME MATCHES "Linux") option(RECOMP_FLATPAK "Configure the build for Flatpak compatibility." OFF) + # Use xdg-desktop-portal for file dialogs to avoid GTK runtime mismatches in AppImages. + set(NFD_PORTAL ON CACHE BOOL "Use xdg-desktop-portal for native file dialogs on Linux" FORCE) endif() # Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24: diff --git a/src/game/config.cpp b/src/game/config.cpp index ee76ca5..896f83e 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -134,7 +134,14 @@ namespace recomp { } std::filesystem::path zelda64::get_app_folder_path() { - // directly check for portable.txt (windows and native linux binary) + // Prefer portable.txt next to the executable so portable mode works even + // when launched from a different working directory. + const auto program_path = zelda64::get_program_path(); + if (!program_path.empty() && std::filesystem::exists(program_path / "portable.txt")) { + return program_path; + } + + // Keep compatibility with legacy launchers that rely on the current dir. if (std::filesystem::exists("portable.txt")) { return std::filesystem::current_path(); } diff --git a/src/main/main.cpp b/src/main/main.cpp index 85b7514..e64666d 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -700,7 +700,11 @@ int main(int argc, char** argv) { recomp::start(cfg); + // Skip NFD_Quit on Linux: the portal backend's dbus_bus_get() returns a shared + // connection that aborts on unref. Process exit cleans up the connection safely. +#ifndef __linux__ NFD_Quit(); +#endif if (preloaded) { release_preload(preload_context); diff --git a/src/main/support.cpp b/src/main/support.cpp index 6bdbb74..15d5e99 100644 --- a/src/main/support.cpp +++ b/src/main/support.cpp @@ -48,10 +48,24 @@ namespace zelda64 { std::filesystem::path get_program_path() { #if defined(__APPLE__) return get_bundle_resource_directory(); -#elif defined(__linux__) && defined(RECOMP_FLATPAK) - return "/app/bin"; #else - return ""; + // Resolve resources relative to the executable location instead of the launch + // working directory so packaged builds (e.g. AppImage) work from any CWD. + static const std::filesystem::path program_path = []() -> std::filesystem::path { + char* base_path = SDL_GetBasePath(); + if (base_path != nullptr) { + std::filesystem::path ret{ base_path }; + SDL_free(base_path); + return ret; + } +#if defined(__linux__) && defined(RECOMP_FLATPAK) + return "/app/bin"; +#else + std::error_code ec; + return std::filesystem::current_path(ec); +#endif + }(); + return program_path; #endif }