diff --git a/.github/workflows/rolling-release.yml b/.github/workflows/rolling-release.yml index b9f2a3151..e63962c85 100644 --- a/.github/workflows/rolling-release.yml +++ b/.github/workflows/rolling-release.yml @@ -202,7 +202,7 @@ jobs: linux-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2.3.1 with: @@ -212,14 +212,16 @@ jobs: shell: bash run: | # Workaround for https://github.com/actions/runner-images/issues/675 - # TODO: Update to LLVM 18 + scripts/retry.sh wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo scripts/retry.sh apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main' + sudo scripts/retry.sh apt-get update && sudo scripts/retry.sh apt-get -y install \ cmake ninja-build ccache libegl1-mesa-dev libevdev-dev libwayland-dev libwayland-egl-backend-dev libxrandr-dev libdbus-1-dev \ extra-cmake-modules libcurl4-openssl-dev libssl-dev libasound2-dev libpulse-dev libx11-xcb-dev build-essential git libclang-dev \ libclang-11-dev libclang-12-dev patchelf libglib2.0-dev libfontconfig1-dev libharfbuzz-dev libjpeg-dev libpng-dev libfreetype-dev \ libinput-dev libxcb-*-dev libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libwayland-dev libgl1-mesa-dev libegl-dev \ - libegl1-mesa-dev libgl1-mesa-dev libssl-dev libx11-dev libx11-xcb-dev llvm-12 lld-12 clang-12 + libegl1-mesa-dev libgl1-mesa-dev libssl-dev libx11-dev libx11-xcb-dev libfuse2 llvm-16 lld-16 clang-16 - name: Cache Dependencies id: cache-deps @@ -237,10 +239,10 @@ jobs: run: | mkdir build cd build - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_NOGUI_FRONTEND=OFF -DBUILD_QT_FRONTEND=ON -DBUILD_TESTS=OFF -DUSE_EGL=ON -DUSE_SDL2=ON -DUSE_WAYLAND=ON -DUSE_X11=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH=$HOME/deps -DCMAKE_TOOLCHAIN_FILE=../scripts/clang-toolchain.cmake .. + cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_NOGUI_FRONTEND=OFF -DBUILD_QT_FRONTEND=ON -DBUILD_TESTS=OFF -DUSE_WAYLAND=ON -DUSE_X11=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH=$HOME/deps -DCMAKE_TOOLCHAIN_FILE=../scripts/clang-toolchain.cmake .. cmake --build . --parallel cd .. - scripts/make-appimage.sh $(realpath ./build) $(realpath .) $HOME/deps DuckStation-x64 + scripts/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64 - name: Upload Qt AppImage uses: actions/upload-artifact@v1 @@ -262,7 +264,7 @@ jobs: - name: Generate AppStream XML run: | - scripts/flatpak/generate-metainfo.sh scripts/flatpak/org.duckstation.duckstation.metainfo.xml + scripts/generate-metainfo.sh scripts/flatpak/org.duckstation.duckstation.metainfo.xml cat scripts/flatpak/org.duckstation.duckstation.metainfo.xml flatpak run org.freedesktop.appstream-glib validate scripts/flatpak/org.duckstation.duckstation.metainfo.xml diff --git a/scripts/clang-toolchain.cmake b/scripts/clang-toolchain.cmake index 856772e7b..7a601d668 100644 --- a/scripts/clang-toolchain.cmake +++ b/scripts/clang-toolchain.cmake @@ -1,5 +1,5 @@ -set(CMAKE_C_COMPILER /usr/bin/clang-12) -set(CMAKE_CXX_COMPILER /usr/bin/clang++-12) +set(CMAKE_C_COMPILER /usr/bin/clang-16) +set(CMAKE_CXX_COMPILER /usr/bin/clang++-16) set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld") set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld") -set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld") \ No newline at end of file +set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld") diff --git a/scripts/flatpak/duckstation-qt.desktop b/scripts/duckstation-qt.desktop similarity index 100% rename from scripts/flatpak/duckstation-qt.desktop rename to scripts/duckstation-qt.desktop diff --git a/scripts/duckstation-qt.png b/scripts/duckstation-qt.png new file mode 100644 index 000000000..cf342223a Binary files /dev/null and b/scripts/duckstation-qt.png differ diff --git a/scripts/flatpak/org.duckstation.duckstation.json b/scripts/flatpak/org.duckstation.duckstation.json index b95a29821..67067e395 100644 --- a/scripts/flatpak/org.duckstation.duckstation.json +++ b/scripts/flatpak/org.duckstation.duckstation.json @@ -47,8 +47,8 @@ ], "post-install": [ "cp -a \"${FLATPAK_BUILDER_BUILDDIR}/bin\" ${FLATPAK_DEST}", - "install -Dm644 data/resources/images/duck.png ${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/org.duckstation.duckstation.png", - "install -Dm644 scripts/flatpak/duckstation-qt.desktop ${FLATPAK_DEST}/share/applications/org.duckstation.duckstation.desktop", + "install -Dm644 scripts/duckstation-qt.png ${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/org.duckstation.duckstation.png", + "install -Dm644 scripts/duckstation-qt.desktop ${FLATPAK_DEST}/share/applications/org.duckstation.duckstation.desktop", "desktop-file-edit --set-key=Icon --set-value=org.duckstation.duckstation ${FLATPAK_DEST}/share/applications/org.duckstation.duckstation.desktop", "install -Dm644 scripts/flatpak/org.duckstation.duckstation.metainfo.xml ${FLATPAK_DEST}/share/metainfo/org.duckstation.duckstation.metainfo.xml" ] diff --git a/scripts/flatpak/generate-metainfo.sh b/scripts/generate-metainfo.sh similarity index 100% rename from scripts/flatpak/generate-metainfo.sh rename to scripts/generate-metainfo.sh diff --git a/scripts/make-appimage.sh b/scripts/make-appimage.sh index 7b9f6e996..ca029b480 100755 --- a/scripts/make-appimage.sh +++ b/scripts/make-appimage.sh @@ -25,278 +25,146 @@ # # For more information, please refer to +SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}") + +function retry_command { + # Package servers tend to be unreliable at times.. + # Retry a bunch of times. + local RETRIES=10 + + for i in $(seq 1 "$RETRIES"); do + "$@" && break + if [ "$i" == "$RETRIES" ]; then + echo "Command \"$@\" failed after ${RETRIES} retries." + exit 1 + fi + done +} + if [ "$#" -ne 4 ]; then - echo "Syntax: $0 " + echo "Syntax: $0 " exit 1 fi -BUILDDIR=$1 -ROOTDIR=$2 +ROOTDIR=$1 +BUILDDIR=$2 DEPSDIR=$3 NAME=$4 -BINDIR="$DSDIR/bin" - BINARY=duckstation-qt APPDIRNAME=DuckStation.AppDir -STRIP=llvm-strip-12 +STRIP=strip -declare -a SYSLIBS=( - "libz.so.1" - "libuuid.so.1" - "libapparmor.so.1" - "libblkid.so.1" - "libbsd.so.0" - "libdbus-1.so.3" - "libgcrypt.so.20" - "liblzma.so.5" - "libmount.so.1" - "libnsl.so.1" - "libpcre.so.3" - "libselinux.so.1" - "libsystemd.so.0" - "libudev.so.1" - "libwrap.so.0" - "libharfbuzz.so.0" - "libX11.so.6" - "libX11-xcb.so.1" - "libXau.so.6" - "libXcomposite.so.1" - "libXcursor.so.1" - "libXdamage.so.1" - "libXdmcp.so.6" - "libXext.so.6" - "libXfixes.so.3" - "libXi.so.6" - "libXinerama.so.1" - "libXrandr.so.2" - "libXrender.so.1" - "libXxf86vm.so.1" - "libasyncns.so.0" - "libcrypto.so.1.1" - "liblz4.so.1" - "libpulse.so.0" - "libxcb.so.1" - "libxcb-render.so.0" - "libxcb-shm.so.0" - "libxkbcommon.so.0" - "libxkbcommon-x11.so.0" - "pulseaudio/libpulsecommon-13.99.so" - "libfreetype.so.6" - "libpcre2-16.so.0" - "libexpat.so.1" - "libffi.so.7" - "libgraphite2.so.3" - "libresolv.so.2" - "libgpg-error.so.0" - "libpcre2-16.so.0" - "libxcb-icccm.so.4" - "libxcb-image.so.0" - "libxcb-keysyms.so.1" - "libxcb-randr.so.0" - "libxcb-render.so.0" - "libxcb-render-util.so.0" - "libxcb-shape.so.0" - "libxcb-sync.so.1" - "libxcb-cursor.so.0" - "libxcb-util.so.1" - "libxcb-xfixes.so.0" - "libxcb-xkb.so.1" - "libevdev.so.2" - "libgudev-1.0.so.0" - "libinput.so.10" - "libjpeg.so.8" - "libmtdev.so.1" - "libpng16.so.16" - "libuuid.so.1" - "libSM.so.6" - "libICE.so.6" - "libfontconfig.so.1" - "libglib-2.0.so.0" - "libcurl-gnutls.so.4" - "libnghttp2.so.14" - "libidn2.so.0" - "librtmp.so.1" - "libssh.so.4" - "libpsl.so.5" - "libnettle.so.7" - "libgnutls.so.30" - "libgssapi_krb5.so.2" - "libldap_r-2.4.so.2" - "liblber-2.4.so.2" - "libbrotlidec.so.1" - "libunistring.so.2" - "libhogweed.so.5" - "libgmp.so.10" - "libp11-kit.so.0" - "libtasn1.so.6" - "libkrb5.so.3" - "libk5crypto.so.3" - "libcom_err.so.2" - "libkrb5support.so.0" - "libsasl2.so.2" - "libgssapi.so.3" - "libbrotlicommon.so.1" - "libkeyutils.so.1" - "libheimntlm.so.0" - "libkrb5.so.26" - "libasn1.so.8" - "libhcrypto.so.4" - "libroken.so.18" - "libwind.so.0" - "libheimbase.so.1" - "libhx509.so.5" - "libsqlite3.so.0" - "libcrypt.so.1" - "libdbus-1.so.3" -) - -declare -a DEPLIBS=( - "libSDL2-2.0.so.0" -) - -declare -a QTLIBS=( - "libQt6Core.so.6" - "libQt6Gui.so.6" - "libQt6Network.so.6" - "libQt6OpenGL.so.6" - "libQt6Svg.so.6" - "libQt6WaylandClient.so.6" - "libQt6WaylandCompositor.so.6" +declare -a MANUAL_QT_LIBS=( "libQt6WaylandEglClientHwIntegration.so.6" - "libQt6WaylandEglCompositorHwIntegration.so.6" - "libQt6Widgets.so.6" - "libQt6XcbQpa.so.6" ) -declare -a QTPLUGINS=( - "plugins/iconengines" - "plugins/imageformats" - "plugins/platforms" - #"plugins/platformthemes" # Enable this if we want to ship GTK+ themes at any point. - "plugins/wayland-decoration-client" - "plugins/wayland-graphics-integration-client" - "plugins/wayland-graphics-integration-server" - "plugins/wayland-shell-integration" - "plugins/xcbglintegrations" +declare -a MANUAL_QT_PLUGINS=( + "wayland-decoration-client" + "wayland-graphics-integration-client" + "wayland-shell-integration" ) set -e -if [ ! -f appimagetool-x86_64.AppImage ]; then - wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage - chmod +x appimagetool-x86_64.AppImage +LINUXDEPLOY=./linuxdeploy-x86_64.AppImage +LINUXDEPLOY_PLUGIN_QT=./linuxdeploy-plugin-qt-x86_64.AppImage +APPIMAGETOOL=./appimagetool-x86_64.AppImage +PATCHELF=patchelf + +if [ ! -f "$LINUXDEPLOY" ]; then + retry_command wget -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x "$LINUXDEPLOY" +fi + +if [ ! -f "$LINUXDEPLOY_PLUGIN_QT" ]; then + retry_command wget -O "$LINUXDEPLOY_PLUGIN_QT" https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage + chmod +x "$LINUXDEPLOY_PLUGIN_QT" +fi + +if [ ! -f "$APPIMAGETOOL" ]; then + retry_command wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage + chmod +x "$APPIMAGETOOL" fi OUTDIR=$(realpath "./$APPDIRNAME") SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}") rm -fr "$OUTDIR" -mkdir "$OUTDIR" -mkdir -p "$OUTDIR/usr/bin" "$OUTDIR/usr/lib" "$OUTDIR/usr/lib/pulseaudio" +# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off. +# It also doesn't strip the Qt libs. We can't strip them after running linuxdeploy, because +# patchelf corrupts the libraries (but they still work), but patchelf+strip makes them crash +# on load. So, make a backup copy, strip the original (since that's where linuxdeploy finds +# the libs to copy), then swap them back after we're done. +# Isn't Linux packaging amazing? -echo "Copying binary and resources..." -cp -a "$BUILDDIR/bin"/* "$OUTDIR/usr/bin" - -# We don't need tests -rm -f "$OUTDIR"/usr/bin/*-tests - -# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system. -echo "Patching RPATH in ${BINARY}..." -patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY" - -# Currently we leave the main binary unstripped, uncomment if this is not desired. -#$STRIP "$OUTDIR/usr/bin/$BINARY" - -# Libraries we pull in from the system. -echo "Copying system libraries..." -for lib in "${SYSLIBS[@]}"; do - blib=$(basename "$lib") - if [ -f "/lib/x86_64-linux-gnu/$lib" ]; then - cp "/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib" - elif [ -f "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" ]; then - cp "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib" - elif [ -f "$CHROOT/lib/$lib" ]; then - cp "$CHROOT/lib/$lib" "$OUTDIR/usr/lib/$blib" - elif [ -f "$CHROOT/usr/lib/$lib" ]; then - cp "$CHROOT/usr/lib/$lib" "$OUTDIR/usr/lib/$blib" - else - echo "*** Failed to find '$blib'" - exit 1 - fi - - $STRIP "$OUTDIR/usr/lib/$blib" +rm -fr "$DEPSDIR.bak" +cp -a "$DEPSDIR" "$DEPSDIR.bak" +IFS=" +" +for i in $(find "$DEPSDIR" -iname '*.so'); do + echo "Stripping deps library ${i}" + strip "$i" done -# Dependencies we built, at this point it's just SDL. -echo "Copying dependency libraries..." -for lib in "${DEPLIBS[@]}"; do - blib=$(basename "$lib") - if [ -f "$DEPSDIR/lib/$lib" ]; then - cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib" - else - echo "*** Failed to find '$blib'" - exit 1 - fi +echo "Copying desktop file..." +cp "$ROOTDIR/scripts/duckstation-qt.desktop" "org.duckstation.duckstation.desktop" +cp "$ROOTDIR/scripts/duckstation-qt.png" "duckstation-qt.png" - $STRIP "$OUTDIR/usr/lib/$blib" +echo "Running linuxdeploy to create AppDir..." +EXTRA_QT_PLUGINS="core;gui;network;svg;waylandclient;widgets;xcbqpa" \ +EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \ +QMAKE="$DEPSDIR/bin/qmake" \ +NO_STRIP="1" \ +$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/duckstation-qt" \ +--desktop-file="org.duckstation.duckstation.desktop" --icon-file="duckstation-qt.png" + +echo "Copying resources into AppDir..." +cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin" + +# LinuxDeploy's Qt plugin doesn't include Wayland support. So manually copy in the additional Wayland libraries. +echo "Copying Qt Wayland libraries..." +for lib in "${MANUAL_QT_LIBS[@]}"; do + srcpath="$DEPSDIR/lib/$lib" + dstpath="$OUTDIR/usr/lib/$lib" + echo " $srcpath -> $dstpath" + cp "$srcpath" "$dstpath" + $PATCHELF --set-rpath '$ORIGIN' "$dstpath" done -echo "Copying Qt libraries..." -for lib in "${QTLIBS[@]}"; do - cp -aL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib" - $STRIP "$OUTDIR/usr/lib/$lib" +# .. and plugins. +echo "Copying Qt Wayland plugins..." +for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do + srcpath="$DEPSDIR/plugins/$GROUP" + dstpath="$OUTDIR/usr/plugins/$GROUP" + echo " $srcpath -> $dstpath" + mkdir -p "$dstpath" + + for srcsopath in $(find "$DEPSDIR/plugins/$GROUP" -iname '*.so'); do + # This is ../../ because it's usually plugins/group/name.so + soname=$(basename "$srcsopath") + dstsopath="$dstpath/$soname" + echo " $srcsopath -> $dstsopath" + cp "$srcsopath" "$dstsopath" + $PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath" + done done -echo "Copying Qt plugins..." -mkdir -p "$OUTDIR/usr/lib/plugins" -for plugin in "${QTPLUGINS[@]}"; do - mkdir -p "$OUTDIR/usr/lib/$plugin" - cp -aL "$DEPSDIR/$plugin"/*.so "$OUTDIR/usr/lib/$plugin/" -done +# Restore unstripped deps (for cache). +rm -fr "$DEPSDIR" +mv "$DEPSDIR.bak" "$DEPSDIR" -for so in $(find "$OUTDIR/usr/lib/plugins" -iname '*.so'); do - # This is ../../ because it's usually plugins/group/name.so - echo "Patching RPATH in ${so}..." - patchelf --set-rpath '$ORIGIN/../..' "$so" - $STRIP "$so" -done +# Fix up translations. +rm -fr "$OUTDIR/usr/bin/translations" +mv "$OUTDIR/usr/translations" "$OUTDIR/usr/bin" +cp -a "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin" -for so in $(find "$OUTDIR/usr/lib" -maxdepth 1); do - if [ -f "$so" ]; then - echo "Patching RPATH in ${so}" - patchelf --set-rpath '$ORIGIN' "$so" - fi -done +# Generate AppStream meta-info. +echo "Generating AppStream metainfo..." +mkdir -p "$OUTDIR/usr/share/metainfo" +"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo/org.duckstation.duckstation.appdata.xml" -echo "Creating qt.conf..." -cat > "$OUTDIR/usr/bin/qt.conf" << EOF -[Paths] -Plugins = ../lib/plugins -EOF +echo "Generating AppImage..." +rm -f "$NAME.AppImage" +$APPIMAGETOOL -v "$OUTDIR" "$NAME.AppImage" -echo "Creating desktop..." -cat > "$OUTDIR/duckstation-qt.desktop" << EOF -[Desktop Entry] -Type=Application -Name=DuckStation -GenericName=PlayStation 1 Emulator -Comment=Fast PlayStation 1 emulator -Icon=duckstation-qt -TryExec=duckstation-qt -Exec=duckstation-qt %f -Categories=Game;Emulator;Qt; -EOF -cp "$ROOTDIR/data/resources/images/duck.png" "$OUTDIR/duckstation-qt.png" - -echo "Creating AppRun..." -cat > "$OUTDIR/AppRun" << EOF -#!/bin/sh - -APPDIR=\$(dirname "\$0") -exec "\$APPDIR/usr/bin/$BINARY" "\$@" -EOF -chmod +x "$OUTDIR/AppRun" - -echo "Generate AppImage" -./appimagetool-x86_64.AppImage -v "$OUTDIR" "$NAME.AppImage" diff --git a/scripts/flatpak/org.duckstation.duckstation.metainfo.xml.in b/scripts/org.duckstation.duckstation.metainfo.xml.in similarity index 100% rename from scripts/flatpak/org.duckstation.duckstation.metainfo.xml.in rename to scripts/org.duckstation.duckstation.metainfo.xml.in