aboutsummaryrefslogtreecommitdiff
path: root/.github/workflows/release-binaries.yml
diff options
context:
space:
mode:
Diffstat (limited to '.github/workflows/release-binaries.yml')
-rw-r--r--.github/workflows/release-binaries.yml197
1 files changed, 171 insertions, 26 deletions
diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml
index 8835844060..36be3f1c64 100644
--- a/.github/workflows/release-binaries.yml
+++ b/.github/workflows/release-binaries.yml
@@ -30,7 +30,7 @@ permissions:
# 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'
+ PGO_LLVM_VERSION: "23"
concurrency:
group: release-binaries-${{ github.ref }}
@@ -42,8 +42,9 @@ jobs:
runs-on: ${{ matrix.runner }}
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
- CCACHE_MAXSIZE: 1500M
+ CCACHE_MAXSIZE: 3000M
SCCACHE_DIR: ${{ github.workspace }}/.sccache
+ SCCACHE_CACHE_SIZE: 3G
strategy:
fail-fast: false
matrix:
@@ -67,10 +68,12 @@ jobs:
- platform: linux-aarch64-pgo
runner: ubuntu-24.04-arm
pgo: true
+ - platform: macos-arm64
+ runner: macos-15
steps:
- name: Check out source
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Install Linux dependencies
if: startsWith(matrix.platform, 'linux')
@@ -85,13 +88,26 @@ jobs:
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
+ libopus-dev libasound2-dev ccache \
+ libxcb-cursor0 libxcb-icccm4 libxcb-image0 \
+ libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xkb1
+
+ # The packages docs/Deps.md lists for macOS, plus ccache.
+ - name: Install macOS dependencies
+ if: startsWith(matrix.platform, 'macos')
+ shell: bash
+ env:
+ HOMEBREW_NO_INSTALL_CLEANUP: 1
+ run: |
+ brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja \
+ nlohmann-json openssl pkg-config qt@6 sdl3 speexdsp zlib zstd cmake catch2 molten-vk \
+ vulkan-loader spirv-tools vulkan-utility-libraries ccache
- name: Install Qt on Linux x86_64
if: startsWith(matrix.platform, 'linux') && runner.arch != 'ARM64'
uses: jurplel/install-qt-action@v4
with:
- version: '6.8.3'
+ version: "6.8.3"
host: linux
target: desktop
arch: linux_gcc_64
@@ -102,7 +118,7 @@ jobs:
if: startsWith(matrix.platform, 'linux') && runner.arch == 'ARM64'
uses: jurplel/install-qt-action@v4
with:
- version: '6.8.3'
+ version: "6.8.3"
host: linux_arm64
target: desktop
arch: linux_gcc_arm64
@@ -146,7 +162,7 @@ jobs:
if: matrix.platform == 'windows-x86_64'
uses: jurplel/install-qt-action@v4
with:
- version: '6.8.3'
+ version: "6.8.3"
host: windows
target: desktop
arch: win64_msvc2022_64
@@ -183,6 +199,7 @@ jobs:
with:
msystem: UCRT64
update: true
+ cache: true
install: >-
git make autoconf libtool automake-wrapper patch jq pactoys ninja
pacboy: >-
@@ -194,7 +211,7 @@ jobs:
lerc:p graphite2:p libwebp:p libtiff:p brotli:p ccache:p
- name: Cache CPM downloads
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: .cache/cpm
key: cpm-${{ runner.os }}-${{ hashFiles('cpmfile.json', 'CMakeLists.txt', 'src/**/CMakeLists.txt') }}
@@ -204,7 +221,7 @@ jobs:
# 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 of the same platform.
- name: Cache compiler objects
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: |
.ccache
@@ -266,6 +283,27 @@ jobs:
-DCMAKE_C_COMPILER_LAUNCHER=sccache
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
+ - name: Configure macOS
+ if: startsWith(matrix.platform, 'macos')
+ shell: bash
+ run: |
+ set -euo pipefail
+ 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=$(brew --prefix qt@6);$(brew --prefix zlib)" \
+ "-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" \
+ -DVulkanHeaders_FORCE_BUNDLED=ON \
+ -DVulkanUtilityLibraries_FORCE_BUNDLED=ON \
+ -DENABLE_UPDATE_CHECKER=OFF \
+ -DUSE_DISCORD_PRESENCE=OFF \
+ -DUSE_CCACHE=ON
+
# MinGW build: system Qt and libraries from MSYS2, clang plus Eden's PGO profile. The profile
# path is converted to its Windows form because clang runs with the MSYS mount underneath.
- name: Configure MinGW PGO
@@ -335,9 +373,6 @@ jobs:
set -euo pipefail
test -x build/release/bin/eglantine
test -x build/release/bin/eden-cli
- # Libraries Qt's xcb platform plugin needs, so linuxdeploy can resolve and bundle them.
- sudo apt-get install -y --no-install-recommends libxcb-cursor0 libxcb-icccm4 libxcb-image0 \
- libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xkb1
tools="$RUNNER_TEMP/linuxdeploy"
mkdir -p "$tools"
arch=$(uname -m) # aarch64 or x86_64
@@ -411,11 +446,70 @@ jobs:
deps "$dll"
done
+ # A self-contained app bundle: macdeployqt copies Qt and every other Homebrew library both
+ # programs load into the bundle, then the leftover Homebrew search paths are removed so a
+ # machine with Homebrew still uses the bundled copies. Ad-hoc signed, not notarized.
+ - name: Package macOS app
+ if: startsWith(matrix.platform, 'macos')
+ shell: bash
+ run: |
+ set -euo pipefail
+ app=build/release/bin/eglantine.app
+ test -x "$app/Contents/MacOS/eglantine"
+ test -x build/release/bin/eden-cli
+ cp build/release/bin/eden-cli "$app/Contents/MacOS/eden-cli"
+ "$(brew --prefix qt@6)/bin/macdeployqt" "$app" \
+ -executable="$app/Contents/MacOS/eden-cli" -libpath="$(brew --prefix)/lib" \
+ -always-overwrite -verbose=1
+ # Qt's virtual keyboard input plugin pulls in the QML stack, which the emulator doesn't use.
+ rm -f "$app/Contents/PlugIns/platforminputcontexts/libqtvirtualkeyboardplugin.dylib"
+ binaries=$(find "$app/Contents" -type f \( -perm -u+x -o -name '*.dylib' \) \
+ -exec sh -c 'file -b "$1" | grep -q Mach-O' _ {} \; -print)
+ for binary in $binaries; do
+ otool -l "$binary" | awk '/cmd LC_RPATH/ {getline; getline; print $2}' |
+ { grep -E '^/(opt/homebrew|usr/local)/' || true; } | while read -r rpath; do
+ install_name_tool -delete_rpath "$rpath" "$binary" 2> /dev/null
+ done
+ done
+ # Libraries that load their dependencies through @rpath find them in the bundle.
+ for program in eglantine eden-cli; do
+ install_name_tool -add_rpath @executable_path/../Frameworks \
+ "$app/Contents/MacOS/$program" 2> /dev/null
+ done
+ leaks=$(for binary in $binaries; do
+ otool -L "$binary" | grep -E '^\s+/(opt/homebrew|usr/local)/'
+ otool -l "$binary" | awk '/cmd LC_RPATH/ {getline; getline; print $2}' |
+ grep -E '^/(opt/homebrew|usr/local)/'
+ done || true)
+ if [ -n "$leaks" ]; then
+ echo "References still pointing outside the bundle:"
+ echo "$leaks" | sort -u
+ exit 1
+ fi
+ # macdeployqt invalidates the signatures. The programs get the entitlements when the
+ # tree has them (the Hypervisor CPU backend needs com.apple.security.hypervisor).
+ codesign --force --deep --sign - "$app"
+ if [ -f dist/eglantine.entitlements ]; then
+ codesign --force --sign - --entitlements dist/eglantine.entitlements \
+ "$app/Contents/MacOS/eden-cli"
+ codesign --force --sign - --entitlements dist/eglantine.entitlements "$app"
+ fi
+ codesign --verify --deep --strict "$app"
+ ditto -c -k --keepParent "$app" "eglantine-${GITHUB_SHA}-${{ matrix.platform }}.zip"
+ ls -la "eglantine-${GITHUB_SHA}-${{ matrix.platform }}.zip"
+ # Also ship a .dmg (drag eglantine.app onto Applications).
+ dmgdir=$(mktemp -d)
+ ditto "$app" "$dmgdir/eglantine.app"
+ ln -s /Applications "$dmgdir/Applications"
+ hdiutil create -volname "Eglantine" -srcfolder "$dmgdir" -ov -format UDZO \
+ "eglantine-${GITHUB_SHA}-${{ matrix.platform }}.dmg"
+ ls -la "eglantine-${GITHUB_SHA}-${{ matrix.platform }}.dmg"
+
# The artifact is the bin folder itself: GitHub zips artifacts on download, and uploading a
# zip gave a zip inside a zip. The release job zips it once for the release.
- name: Upload Windows binary
if: matrix.platform == 'windows-x86_64'
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: eglantine-${{ matrix.platform }}-${{ github.sha }}
path: build/release/bin/
@@ -424,7 +518,7 @@ jobs:
- name: Upload MinGW binary
if: matrix.mingw
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: eglantine-${{ matrix.platform }}-${{ github.sha }}
path: build/release/bin/
@@ -434,7 +528,7 @@ jobs:
# Both Linux files go in one artifact: the tar.gz and the AppImage.
- name: Upload Linux binary
if: startsWith(matrix.platform, 'linux')
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: eglantine-${{ matrix.platform }}-${{ github.sha }}
path: |
@@ -444,6 +538,19 @@ jobs:
compression-level: 0
retention-days: 7
+ # Zipped with ditto beforehand: the bundle's framework symlinks don't survive artifact zipping.
+ - name: Upload macOS app
+ if: startsWith(matrix.platform, 'macos')
+ uses: actions/upload-artifact@v7
+ with:
+ name: eglantine-${{ matrix.platform }}-${{ github.sha }}
+ path: |
+ eglantine-${{ github.sha }}-${{ matrix.platform }}.zip
+ eglantine-${{ github.sha }}-${{ matrix.platform }}.dmg
+ if-no-files-found: error
+ compression-level: 0
+ retention-days: 7
+
# Publishes every binary as a GitHub pre-release once every platform built: on pushes to nx2
# and nx2-experimental, and on manual runs unless "Publish the binaries as a GitHub release" is
# unticked.
@@ -456,7 +563,7 @@ jobs:
contents: write
steps:
- name: Download binaries
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
pattern: eglantine-*-${{ github.sha }}
path: artifacts
@@ -466,33 +573,71 @@ jobs:
run: |
set -euo pipefail
mkdir dist
+ # Asset names drop the commit sha: the release tag already identifies the build, and
+ # stable names let the notes table link to them.
+ strip_sha() { sed "s/-${GITHUB_SHA}//" <<< "$1"; }
for artifact in artifacts/*/; do
name=$(basename "$artifact")
if compgen -G "$artifact*.AppImage" > /dev/null; then
# Linux: ship the AppImage and the tar.gz as they are.
- cp "$artifact"/*.AppImage "$artifact"/*.tar.gz dist/
+ for file in "$artifact"*.AppImage "$artifact"*.tar.gz; do
+ cp "$file" "dist/$(strip_sha "$(basename "$file")")"
+ done
+ elif compgen -G "$artifact*.zip" > /dev/null; then
+ for file in "$artifact"*.zip "$artifact"*.dmg; do
+ [[ -e "$file" ]] && cp "$file" "dist/$(strip_sha "$(basename "$file")")"
+ done
else
- (cd "$artifact" && zip -qr "${GITHUB_WORKSPACE}/dist/${name}.zip" .)
+ (cd "$artifact" && zip -qr "${GITHUB_WORKSPACE}/dist/$(strip_sha "$name").zip" .)
fi
done
+ ls -la dist
- name: Create release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
- ls -la dist
- gh release create "build-${GITHUB_RUN_NUMBER}" dist/* \
+ set -euo pipefail
+ tag="build-${GITHUB_RUN_NUMBER}"
+ base="https://github.com/${GITHUB_REPOSITORY}/releases/download/${tag}"
+
+ cat > notes.md <<EOF
+ Automatic build of \`${GITHUB_REF_NAME}\` at ${GITHUB_SHA}.
+
+ ## Linux
+
+ Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
+
+ | Build Type | Standard | PGO (Recommended) | Notes |
+ | --- | --- | --- | --- |
+ | amd64 | [AppImage](${base}/eglantine-linux-x86_64.AppImage) · [tar.gz](${base}/eglantine-linux-x86_64.tar.gz) | [AppImage](${base}/eglantine-linux-x86_64-pgo.AppImage) · [tar.gz](${base}/eglantine-linux-x86_64-pgo.tar.gz) | Make the AppImage executable (\`chmod +x\`) and run it |
+ | ARM (aarch64) | [AppImage](${base}/eglantine-linux-aarch64.AppImage) · [tar.gz](${base}/eglantine-linux-aarch64.tar.gz) | [AppImage](${base}/eglantine-linux-aarch64-pgo.AppImage) · [tar.gz](${base}/eglantine-linux-aarch64-pgo.tar.gz) | |
+
+ ## Windows
+
+ Windows packages are in-place zip files: extract and run \`eglantine.exe\`, or \`eden-cli.exe\` from a terminal.
+
+ | Build Type | Standard | PGO (Recommended) | Notes |
+ | --- | --- | --- | --- |
+ | amd64 / x86_64 (MSVC) | [MSVC zip](${base}/eglantine-windows-x86_64.zip) | | Use if you run into graphical issues on other builds |
+ | amd64 / x86_64 (MinGW) | | [PGO zip](${base}/eglantine-windows-x86_64-pgo.zip) | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
+
+ ## macOS
+
+ | Build Type | Standard | PGO (Recommended) | Notes |
+ | --- | --- | --- | --- |
+ | arm64 (Apple Silicon) | [zip](${base}/eglantine-macos-arm64.zip) | | macOS 15 or newer. Not notarized: right-click and choose Open the first time, or run \`xattr -dr com.apple.quarantine eglantine.app\`. \`eden-cli\` is inside the app, in \`Contents/MacOS\` |
+
+ The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eden's profile); prefer them when your CPU supports it.
+ EOF
+
+ gh release create "${tag}" dist/* \
--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--prerelease \
--title "Eglantine ${GITHUB_REF_NAME} build ${GITHUB_RUN_NUMBER} (${GITHUB_SHA::7})" \
- --notes "Automatic build of ${GITHUB_REF_NAME} at ${GITHUB_SHA}.
-
- Windows: extract the zip and run eglantine.exe, or eden-cli.exe from a terminal.
- Linux (AppImage): make it 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).
- Linux (tar.gz): extract it and run ./eglantine or ./eden-cli; it uses your system libraries, so Qt 6 and the usual libraries must be installed.
- The -pgo builds are the same programs compiled with profile-guided optimization (clang plus Eden's profile); prefer them when your CPU supports it. The Windows PGO build is a MinGW build, so it carries its own DLLs and needs no Visual C++ redistributable."
+ --notes-file notes.md
- name: Ping Discord
shell: bash