name: release-binaries # Builds the Linux x86_64 PGO AppImage and publishes it as a GitHub pre-release. on: workflow_dispatch: inputs: publish_release: description: Publish the AppImage as a GitHub release type: boolean default: true push: branches: - nx2 # A binary only changes when build inputs change; docs-only pushes skip the build. paths: - "src/**" - "CMakeLists.txt" - "CMakeModules/**" - "externals/**" - "dist/**" - "tools/**" - ".patch/**" - "cpmfile.json" - ".github/workflows/release-binaries.yml" permissions: contents: read # Clang major the PGO build uses, from apt.llvm.org. Eden's profile is written by a current clang # and an older reader refuses it, so this has to stay at or above whatever produced eden.profdata; # bump it when a refreshed profile needs a newer LLVM. env: PGO_LLVM_VERSION: '23' PLATFORM: linux-x86_64-pgo # A running build is never cancelled: it finishes and publishes. A push meanwhile queues one build; # a later push replaces it, so the newest commit builds as soon as the running one is done. concurrency: group: release-binaries-${{ github.ref }} cancel-in-progress: false jobs: build: name: Linux x86_64 PGO AppImage runs-on: ubuntu-24.04 env: CCACHE_DIR: ${{ github.workspace }}/.ccache CCACHE_MAXSIZE: 3000M steps: - name: Check out source uses: actions/checkout@v5 - name: Install dependencies shell: bash run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ autoconf cmake g++ gcc git glslang-tools libglu1-mesa-dev \ libpulse-dev libtool libudev-dev libxkbcommon-x11-0 \ mesa-common-dev nasm ninja-build qt6-base-private-dev \ qt6-charts-dev qt6-tools-dev libavfilter-dev libavcodec-dev \ libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev \ spirv-tools spirv-headers libusb-1.0-0-dev \ libboost-dev libboost-fiber-dev libboost-context-dev \ libopus-dev libasound2-dev ccache \ libxcb-cursor0 libxcb-icccm4 libxcb-image0 \ libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xkb1 - name: Install Qt uses: jurplel/install-qt-action@v4 with: version: '6.8.3' host: linux target: desktop arch: linux_gcc_64 modules: qtcharts cache: true # Ubuntu's own clang 18 cannot read a profile from a current LLVM, so take clang from the LLVM # apt repo. The versioned packages are named explicitly: that repo's unversioned clang/lld # metapackages can lag the binaries they depend on and then resolve to nothing. lld-23 only # ships ld.lld under /usr/lib/llvm-23/bin, so -B points the linker search there. - name: Install clang for PGO shell: bash run: | set -euo pipefail curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc > /dev/null echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-$PGO_LLVM_VERSION main" | sudo tee /etc/apt/sources.list.d/llvm.list > /dev/null sudo apt-get update sudo apt-get install -y --no-install-recommends \ "clang-$PGO_LLVM_VERSION" "lld-$PGO_LLVM_VERSION" "clang-$PGO_LLVM_VERSION" --version # Eden's periodically updated profile: https://github.com/Eden-CI/PGO - name: Download PGO profile shell: bash run: | set -euo pipefail curl -fsSL -o eden.profdata \ https://github.com/Eden-CI/PGO/releases/latest/download/eden.profdata test -s eden.profdata - name: Cache CPM downloads uses: actions/cache@v5 with: path: .cache/cpm key: cpm-${{ runner.os }}-${{ hashFiles('cpmfile.json', 'CMakeLists.txt', 'src/**/CMakeLists.txt') }} restore-keys: | cpm-${{ runner.os }}- # The sha in the key makes every run save a fresh cache (actions/cache never saves over an # exact hit), and restore-keys seeds it from the newest one. - name: Cache compiler objects uses: actions/cache@v5 with: path: .ccache key: objects-${{ env.PLATFORM }}-${{ github.sha }} restore-keys: | objects-${{ env.PLATFORM }}- # Same flags Eden's CI passes for its clang PGO build. - name: Configure shell: bash run: | set -euo pipefail profile="-fprofile-use=$PWD/eden.profdata -Wno-backend-plugin \ -Wno-profile-instr-unprofiled -Wno-profile-instr-out-of-date" cmake -S . -B build/release -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=OFF \ -DYUZU_TESTS=OFF \ -DYUZU_CMD=ON \ -DYUZU_ROOM=OFF \ -DYUZU_ROOM_STANDALONE=OFF \ -DYUZU_USE_BUNDLED_QT=OFF \ "-DCMAKE_PREFIX_PATH=$QT_ROOT_DIR" \ -DYUZU_USE_BUNDLED_SDL3=ON \ -DVulkanHeaders_FORCE_BUNDLED=ON \ -DVulkanUtilityLibraries_FORCE_BUNDLED=ON \ -DENABLE_UPDATE_CHECKER=OFF \ -DUSE_DISCORD_PRESENCE=OFF \ -DUSE_CCACHE=ON \ "-DCMAKE_C_COMPILER=clang-$PGO_LLVM_VERSION" \ "-DCMAKE_CXX_COMPILER=clang++-$PGO_LLVM_VERSION" \ "-DCMAKE_EXE_LINKER_FLAGS=-B/usr/lib/llvm-$PGO_LLVM_VERSION/bin -fuse-ld=lld" \ "-DCMAKE_C_FLAGS=$profile" \ "-DCMAKE_CXX_FLAGS=$profile" - name: Build shell: bash run: | cmake --build build/release --target yuzu yuzu-cmd --parallel ccache --show-stats # A self-contained AppImage: linuxdeploy bundles every library the two programs need except # the base system ones (glibc, X11/Wayland client libraries, the GPU driver and Vulkan loader), # and its Qt plugin adds the Qt libraries and platform plugins. Runs on glibc 2.39+ systems. - name: Package AppImage shell: bash run: | set -euo pipefail test -x build/release/bin/eglantine test -x build/release/bin/eden-cli strip build/release/bin/eglantine build/release/bin/eden-cli tools="$RUNNER_TEMP/linuxdeploy" mkdir -p "$tools" curl -fsSL -o "$tools/linuxdeploy-x86_64.AppImage" \ https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage curl -fsSL -o "$tools/linuxdeploy-plugin-qt-x86_64.AppImage" \ https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage chmod +x "$tools"/*.AppImage # The desktop file names its icon dev.eglantine.eglantine. icon="$RUNNER_TEMP/dev.eglantine.eglantine.png" cp dist/Eglantine.png "$icon" export APPIMAGE_EXTRACT_AND_RUN=1 export QMAKE="$QT_ROOT_DIR/bin/qmake" export LDAI_OUTPUT="eglantine-${GITHUB_SHA}-${PLATFORM}.AppImage" export OUTPUT="$LDAI_OUTPUT" export ARCH=x86_64 "$tools/linuxdeploy-x86_64.AppImage" --appdir AppDir \ --executable build/release/bin/eglantine \ --executable build/release/bin/eden-cli \ --desktop-file dist/dev.eden_emu.eden.desktop \ --icon-file "$icon" \ --plugin qt \ --output appimage test -s "$LDAI_OUTPUT" sha256sum "$LDAI_OUTPUT" | tee "$LDAI_OUTPUT.sha256" - name: Upload AppImage uses: actions/upload-artifact@v7 with: name: eglantine-${{ env.PLATFORM }}-${{ github.sha }} path: | eglantine-${{ github.sha }}-${{ env.PLATFORM }}.AppImage eglantine-${{ github.sha }}-${{ env.PLATFORM }}.AppImage.sha256 if-no-files-found: error compression-level: 0 retention-days: 7 # Publishes the AppImage as a GitHub pre-release: on pushes to nx2, and on manual runs unless # "Publish the AppImage as a GitHub release" is unticked. release: name: Publish release needs: build if: github.event_name == 'push' || inputs.publish_release runs-on: ubuntu-24.04 permissions: contents: write steps: - name: Download AppImage uses: actions/download-artifact@v7 with: name: eglantine-${{ env.PLATFORM }}-${{ github.sha }} path: dist - name: Create release shell: bash env: GH_TOKEN: ${{ github.token }} run: | set -euo pipefail ls -la dist gh release create "build-${GITHUB_RUN_NUMBER}" dist/* \ --repo "${GITHUB_REPOSITORY}" \ --target "${GITHUB_SHA}" \ --prerelease \ --title "Eglantine ${GITHUB_REF_NAME} build ${GITHUB_RUN_NUMBER} (${GITHUB_SHA::7})" \ --notes "Automatic Linux x86_64 PGO build of ${GITHUB_REF_NAME} at ${GITHUB_SHA}. Make the AppImage executable (chmod +x) and run it. It bundles its libraries and needs glibc 2.39 or newer (Ubuntu 24.04, Fedora 40, Debian 13, Arch). It is compiled with profile-guided optimization (clang plus Eden's profile). The .sha256 file holds its checksum."