mirror of
https://github.com/citron-neo/PR.git
synced 2026-07-05 15:22:02 -07:00
Initial CI setup with Discord notifications and updated repository links
This repository builds upon the excellent work of previous contributors: - pkgforge-dev for the original Citron AppImage build scripts and infrastructure - CollectingW for the Citron-Nightly build workflows and automation Changes made in this commit: - Updated all repository links from pkgforge-dev/Citron-AppImage and CollectingW/Citron-Nightly to Zephyron-Dev/Citron-CI - Added Discord webhook notifications for successful builds (Android, Linux, Windows) - Integrated automated notifications with build metadata (version, date, download links) Build workflows included: - Android: Daily APK builds for arm64-v8a - Linux: Multiple variants (x86_64, x86_64_v3, PGO optimized) as AppImages - Windows: x64 builds with Qt6 support All builds run daily at 12 AM UTC and can be triggered manually via workflow_dispatch.
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
name: Build Citron (Android)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
name: Build Android APK
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
git_hash: ${{ steps.get_hash.outputs.git_hash }}
|
||||
|
||||
steps:
|
||||
- name: Clone Citron Source Code
|
||||
run: git clone --recursive --depth 1 https://git.citron-emu.org/citron/emulator.git citron_source
|
||||
|
||||
- name: Clean and Force-Update Submodules
|
||||
working-directory: ./citron_source
|
||||
run: |
|
||||
git submodule deinit --all --force
|
||||
git submodule update --init --recursive --force
|
||||
|
||||
- name: Get Citron Commit Hash
|
||||
id: get_hash
|
||||
working-directory: ./citron_source
|
||||
run: echo "git_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y -qq wget unzip curl git cmake build-essential pkg-config zip glslang-tools
|
||||
|
||||
- name: Install Android SDK
|
||||
run: |
|
||||
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
|
||||
unzip -q commandlinetools-linux-11076708_latest.zip
|
||||
mkdir -p android-sdk/cmdline-tools
|
||||
mv cmdline-tools android-sdk/cmdline-tools/latest
|
||||
echo "ANDROID_HOME=$PWD/android-sdk" >> $GITHUB_ENV
|
||||
echo "$PWD/android-sdk/cmdline-tools/latest/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Accept Android SDK licenses and install components
|
||||
run: |
|
||||
yes | sdkmanager --licenses > /dev/null || true
|
||||
sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"
|
||||
|
||||
- name: Install Android NDK
|
||||
run: |
|
||||
wget -q https://dl.google.com/android/repository/android-ndk-r26b-linux.zip
|
||||
unzip -q android-ndk-r26b-linux.zip
|
||||
echo "ANDROID_NDK_HOME=$PWD/android-ndk-r26b" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
cmake -B build-android -S citron_source \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_ABI=arm64-v8a \
|
||||
-DANDROID_PLATFORM=android-30 \
|
||||
-DENABLE_QT=OFF \
|
||||
-DENABLE_SDL2=OFF \
|
||||
-DENABLE_WEB_SERVICE=OFF \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=ON \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=ON \
|
||||
-DANDROID_ARM_NEON=ON \
|
||||
-DCITRON_ENABLE_LTO=ON
|
||||
|
||||
- name: Build with CMake
|
||||
run: |
|
||||
cmake --build build-android --config Release --parallel $(nproc)
|
||||
|
||||
- name: Build APK with Gradle
|
||||
run: |
|
||||
cd citron_source/src/android
|
||||
export ANDROID_SDK_ROOT="$ANDROID_HOME"
|
||||
./gradlew assembleMainlineRelease
|
||||
|
||||
- name: Upload APK artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: citron-android-nightly
|
||||
path: citron_source/src/android/app/build/outputs/apk/mainline/release/*.apk
|
||||
|
||||
release-android:
|
||||
name: "Release Android Nightly"
|
||||
needs: [build-android]
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download APK artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: citron-android-nightly
|
||||
path: .
|
||||
|
||||
- name: Get version info for release name
|
||||
shell: bash
|
||||
run: |
|
||||
echo "DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
|
||||
echo "GIT_HASH=${{ needs.build-android.outputs.git_hash }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Delete previous nightly release and tag
|
||||
run: gh release delete "nightly-android" --repo "${{ github.repository }}" --cleanup-tag -y || true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create new nightly release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: "Continuous Build: (Android Nightly: ${{ env.GIT_HASH }})"
|
||||
tag_name: "nightly-android"
|
||||
prerelease: true
|
||||
files: "*.apk"
|
||||
|
||||
- name: Post to Discord
|
||||
if: success()
|
||||
run: |
|
||||
DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/tag/nightly-android"
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d "{\"content\":\"🤖 **New Android Build Available!**\n\n📦 **Version:** \`${{ env.GIT_HASH }}\`\n📅 **Date:** ${{ env.DATE }}\n🔗 **Download:** $DOWNLOAD_URL\"}" \
|
||||
https://discord.com/api/webhooks/1428304731809517588/fG7t7MBprKFss5oGcI05DIFM3JdO41Z0juSV_zOfb9K-UTvyI2fd3-Ciwi48npWXYHLb
|
||||
@@ -0,0 +1,140 @@
|
||||
name: Build Citron (Linux)
|
||||
concurrency:
|
||||
group: build-nightly-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }} # Use matrix to select the runner
|
||||
timeout-minutes: 120
|
||||
strategy:
|
||||
fail-fast: false # Allows all matrix jobs to complete
|
||||
matrix:
|
||||
include:
|
||||
# --- x86_64 Builds ---
|
||||
- name: "Citron Build (Normal x86_64)"
|
||||
os: ubuntu-latest
|
||||
arch_suffix: ""
|
||||
build_arg: ""
|
||||
- name: "Citron Build (Optimized x86_64)"
|
||||
os: ubuntu-latest
|
||||
arch_suffix: "_v3"
|
||||
build_arg: "v3"
|
||||
- name: "Citron Build (Normal PGO x86_64)"
|
||||
os: ubuntu-latest
|
||||
arch_suffix: "_pgo"
|
||||
build_arg: "pgo"
|
||||
- name: "Citron Build (Optimized PGO x86_64)"
|
||||
os: ubuntu-latest
|
||||
arch_suffix: "_v3_pgo"
|
||||
build_arg: "v3-pgo"
|
||||
|
||||
container: ghcr.io/pkgforge-dev/archlinux:latest
|
||||
|
||||
steps:
|
||||
- name: Install Git
|
||||
run: pacman -Syu --noconfirm --needed git
|
||||
|
||||
- name: Checkout Workflow Scripts
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout Upstream Source Code
|
||||
run: git clone --recurse-submodules https://git.citron-emu.org/citron/emulator.git emulator
|
||||
|
||||
- name: Prepare Build Environment
|
||||
run: |
|
||||
mv get-dependencies.sh emulator/
|
||||
mv build-citron.sh emulator/
|
||||
mv package-citron.sh emulator/
|
||||
|
||||
- name: Add Git Safe Directory
|
||||
working-directory: ./emulator
|
||||
run: git config --global --add safe.directory "$PWD"
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./emulator
|
||||
run: chmod +x ./get-dependencies.sh && ./get-dependencies.sh
|
||||
|
||||
- name: Build Citron from source
|
||||
working-directory: ./emulator
|
||||
run: |
|
||||
NPROC_VAL=$(nproc --all)
|
||||
JOBS_VAL=$((NPROC_VAL > 4 ? 4 : NPROC_VAL))
|
||||
chmod +x ./build-citron.sh
|
||||
JOBS=${JOBS_VAL} DEVEL=true ./build-citron.sh ${{ matrix.build_arg }}
|
||||
|
||||
- name: Package AppImage with Correct Name
|
||||
working-directory: ./emulator
|
||||
run: |
|
||||
GIT_SHA=$(git rev-parse --short HEAD)
|
||||
|
||||
export APP_VERSION="${GIT_SHA}"
|
||||
export VERSION="${GIT_SHA}"
|
||||
export ARCH_SUFFIX="${{ matrix.arch_suffix }}"
|
||||
export DEVEL="true"
|
||||
|
||||
chmod +x ./package-citron.sh
|
||||
./package-citron.sh
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifacts${{ matrix.arch_suffix }}
|
||||
path: emulator/dist/
|
||||
|
||||
release:
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
name: "release"
|
||||
needs: [build]
|
||||
permissions:
|
||||
actions: read
|
||||
security-events: write
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Upstream Repository
|
||||
run: git clone https://git.citron-emu.org/citron/emulator.git .
|
||||
|
||||
- name: Set Version
|
||||
id: version
|
||||
run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: Artifacts*
|
||||
merge-multiple: true
|
||||
path: .
|
||||
|
||||
- name: Del Previous Release
|
||||
run: gh release delete "nightly-linux" --repo "${GITHUB_REPOSITORY}" --cleanup-tag -y && sleep 5
|
||||
env:
|
||||
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
continue-on-error: true
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: "Continuous Build (Linux Nightly: ${{ steps.version.outputs.sha }})"
|
||||
tag_name: "nightly-linux"
|
||||
prerelease: true
|
||||
draft: false
|
||||
generate_release_notes: false
|
||||
make_latest: false
|
||||
files: |
|
||||
*.AppImage*
|
||||
*.tar.zst
|
||||
|
||||
- name: Post to Discord
|
||||
if: success()
|
||||
run: |
|
||||
DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/tag/nightly-linux"
|
||||
DATE=$(date +'%Y-%m-%d')
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d "{\"content\":\"🐧 **New Linux Build Available!**\n\n📦 **Version:** \`${{ steps.version.outputs.sha }}\`\n📅 **Date:** ${DATE}\n🔗 **Download:** $DOWNLOAD_URL\n\n✨ Includes x86_64, x86_64_v3, PGO builds\"}" \
|
||||
https://discord.com/api/webhooks/1428304731809517588/fG7t7MBprKFss5oGcI05DIFM3JdO41Z0juSV_zOfb9K-UTvyI2fd3-Ciwi48npWXYHLb
|
||||
@@ -0,0 +1,111 @@
|
||||
name: Build Citron (Windows)
|
||||
concurrency:
|
||||
group: build-windows-nightly-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Citron Build (Windows)"
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 120
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Vulkan SDK
|
||||
shell: pwsh
|
||||
run: |
|
||||
$vulkan_sdk_url = "https://sdk.lunarg.com/sdk/download/1.3.283.0/windows/VulkanSDK-1.3.283.0-Installer.exe"
|
||||
Invoke-WebRequest -Uri $vulkan_sdk_url -OutFile VulkanSDK-Installer.exe
|
||||
Start-Process -FilePath ".\VulkanSDK-Installer.exe" -ArgumentList "--accept-licenses", "--default-answer", "--confirm-command", "install" -Wait
|
||||
echo "C:\VulkanSDK\1.3.283.0\Bin" | Out-File -FilePath $env:GITHUB_PATH -Append
|
||||
|
||||
- name: Clone Citron Source
|
||||
shell: bash
|
||||
run: git clone --recursive "https://git.citron-emu.org/citron/emulator.git" citron
|
||||
|
||||
- name: Get Nightly Version
|
||||
id: version
|
||||
working-directory: ./citron
|
||||
shell: bash
|
||||
run: |
|
||||
git fetch --tags
|
||||
VERSION=$(git rev-parse --short HEAD)
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: ./citron
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake -B build -S . -G "Visual Studio 17 2022" -A x64 ^
|
||||
-DCITRON_USE_BUNDLED_VCPKG=ON ^
|
||||
-DCITRON_ENABLE_LTO=ON ^
|
||||
-DCITRON_USE_BUNDLED_QT=ON ^
|
||||
-DENABLE_QT6=ON ^
|
||||
-DCITRON_TESTS=OFF ^
|
||||
-DUSE_DISCORD_PRESENCE=ON
|
||||
|
||||
- name: Build Citron
|
||||
working-directory: ./citron
|
||||
shell: cmd
|
||||
run: cmake --build build --config Release --parallel
|
||||
|
||||
- name: Package Windows Build
|
||||
shell: pwsh
|
||||
run: |
|
||||
mkdir dist
|
||||
echo "Creating final zip archive..."
|
||||
Compress-Archive -Path ".\citron\build\bin\Release\*" -DestinationPath ".\dist\Citron-windows-nightly-${{ steps.version.outputs.VERSION }}.zip"
|
||||
|
||||
- name: Upload Windows Build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Citron-Windows-Nightly
|
||||
path: "dist/*.zip"
|
||||
|
||||
release:
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
name: "Release"
|
||||
needs: [build]
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: Citron-Windows-Nightly
|
||||
path: .
|
||||
- name: Get Version from Filename
|
||||
shell: bash
|
||||
run: |
|
||||
FILENAME=$(ls *.zip)
|
||||
VERSION=${FILENAME#Citron-windows-nightly-}
|
||||
VERSION=${VERSION%.zip}
|
||||
echo "APP_VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
- name: Delete Previous Release
|
||||
run: gh release delete "nightly-windows" --repo "${{ github.repository }}" --cleanup-tag -y || true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Release Artifacts
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: "Continuous Build (Windows Nightly: ${{ env.APP_VERSION }})"
|
||||
tag_name: "nightly-windows"
|
||||
prerelease: true
|
||||
files: "*.zip"
|
||||
|
||||
- name: Post to Discord
|
||||
if: success()
|
||||
run: |
|
||||
DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/tag/nightly-windows"
|
||||
DATE=$(date +'%Y-%m-%d')
|
||||
curl -H "Content-Type: application/json" \
|
||||
-d "{\"content\":\"🪟 **New Windows Build Available!**\n\n📦 **Version:** \`${{ env.APP_VERSION }}\`\n📅 **Date:** ${DATE}\n🔗 **Download:** $DOWNLOAD_URL\"}" \
|
||||
https://discord.com/api/webhooks/1428304731809517588/fG7t7MBprKFss5oGcI05DIFM3JdO41Z0juSV_zOfb9K-UTvyI2fd3-Ciwi48npWXYHLb
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-merge-conflict
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: fix-byte-order-marker
|
||||
- id: mixed-line-ending
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
- id: check-yaml
|
||||
- id: no-commit-to-branch
|
||||
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.10.0.1
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
args: ["--severity=error"]
|
||||
|
||||
- repo: https://github.com/scop/pre-commit-shfmt
|
||||
rev: v3.10.0-2
|
||||
hooks:
|
||||
- id: shfmt
|
||||
args: ["-w", "-s"]
|
||||
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
rev: v1.7.6
|
||||
hooks:
|
||||
- id: actionlint
|
||||
|
||||
- repo: https://github.com/woodruffw/zizmor
|
||||
rev: v0.8.0
|
||||
hooks:
|
||||
- id: zizmor
|
||||
files: ^\.github/workflows/.*\.ya?ml$
|
||||
@@ -0,0 +1 @@
|
||||
0.8.0
|
||||
@@ -0,0 +1,69 @@
|
||||
# Maintainer: Collecting <collecting@citron-emu.org>
|
||||
|
||||
# The '-git' suffix signifies this is a bleeding-edge build from the git repo
|
||||
pkgname=citron-git
|
||||
pkgver=0.1.r0.g1a2b3c4 # This will be replaced by the pkgver() function
|
||||
pkgrel=1
|
||||
pkgdesc="A Nintendo Switch emulator"
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://citron-emu.org/"
|
||||
license=('GPL2')
|
||||
|
||||
# Dependencies needed to run the emulator
|
||||
depends=(
|
||||
'boost-libs' 'enet' 'fmt' 'ffmpeg' 'gamemode' 'glslang' 'hicolor-icon-theme'
|
||||
'libdecor' 'libxkbcommon-x11' 'mbedtls2' 'nlohmann-json' 'qt6-base'
|
||||
'qt6-multimedia' 'sdl2' 'vulkan-icd-loader'
|
||||
)
|
||||
|
||||
# Dependencies needed only to build the emulator from source
|
||||
makedepends=(
|
||||
'boost' 'catch2' 'cmake' 'git' 'ninja' 'nasm' 'qt6-tools' 'vulkan-headers'
|
||||
)
|
||||
|
||||
# This points to the source code repository
|
||||
source=("git+https://git.citron-emu.org/citron/emulator.git")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
# This function automatically generates a version string based on the latest git commit
|
||||
pkgver() {
|
||||
cd "$pkgname"
|
||||
git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
|
||||
}
|
||||
|
||||
# This function runs before the build and is used to apply patches
|
||||
prepare() {
|
||||
cd "$pkgname"
|
||||
# Apply compatibility patches for newer Boost versions
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::asio::io_service\b/boost::asio::io_context/g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::asio::io_service::strand\b/boost::asio::strand<boost::asio::io_context::executor_type>/g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's|#include *<boost/process/async_pipe.hpp>|#include <boost/process/v1/async_pipe.hpp>|g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::process::async_pipe\b/boost::process::v1::async_pipe/g'
|
||||
}
|
||||
|
||||
# This function contains the build commands
|
||||
build() {
|
||||
cd "$pkgname"
|
||||
# makepkg sets CFLAGS and CXXFLAGS, so we don't need to specify arch flags
|
||||
cmake -B build -S . -GNinja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=OFF \
|
||||
-DCITRON_USE_BUNDLED_QT=OFF \
|
||||
-DUSE_SYSTEM_QT=ON \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=OFF \
|
||||
-DCITRON_USE_BUNDLED_SDL2=OFF \
|
||||
-DCITRON_TESTS=OFF \
|
||||
-DCITRON_CHECK_SUBMODULES=OFF \
|
||||
-DCITRON_ENABLE_LTO=ON \
|
||||
-DCITRON_USE_QT_MULTIMEDIA=ON \
|
||||
-DENABLE_QT_TRANSLATION=ON
|
||||
|
||||
ninja -C build
|
||||
}
|
||||
|
||||
# This function installs the built files into a temporary directory
|
||||
package() {
|
||||
cd "$pkgname"
|
||||
DESTDIR="$pkgdir/" ninja -C build install
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
# Citron-Nightly 🐧
|
||||
|
||||
[](https://github.com/Zephyron-Dev/Citron-CI/releases/latest)
|
||||
[](https://github.com/Zephyron-Dev/Citron-CI/releases/latest)
|
||||
|
||||
This repository makes Nightly builds for **x86_64** (generic) and **x86_64_v3** on Linux, and also Windows & Android builds! If your CPU is less than 10 years old, for Linux, use the x86_64_v3 build since it has a significant performance boost. These builds are all produced @ 12 AM UTC every single day.
|
||||
|
||||
* [Latest Commits Can Be Found Here](https://git.citron-emu.org/citron/emulator/-/commits/f3374ea7e61cb0bba79d17272964717e37935575)
|
||||
|
||||
* [Latest Android Nightly Release](https://github.com/Zephyron-Dev/Citron-CI/releases/tag/nightly-android)
|
||||
|
||||
* [Latest Linux Nightly Release](https://github.com/Zephyron-Dev/Citron-CI/releases/tag/nightly-linux)
|
||||
|
||||
* [Latest Windows Nightly Release](https://github.com/Zephyron-Dev/Citron-CI/releases/tag/nightly-windows)
|
||||
|
||||
# READ THIS IF YOU HAVE ISSUES
|
||||
|
||||
If you are on wayland (specially GNOME wayland) and get freezes or crahes you are likely affected by this issue that affects all Qt6 apps: https://github.com/Zephyron-Dev/Citron-CI/issues/50
|
||||
|
||||
To fix it simply set the env variable `QT_QPA_PLATFORM=xcb`
|
||||
|
||||
---
|
||||
|
||||
**Looking for AppImages of other emulators? Check:** [AnyLinux-AppImages](https://pkgforge-dev.github.io/Anylinux-AppImages/)
|
||||
|
||||
----
|
||||
|
||||
AppImage made using [sharun](https://github.com/VHSgunzo/sharun), which makes it extremely easy to turn any binary into a portable package without using containers or similar tricks.
|
||||
|
||||
**This AppImage bundles everything and should work on any linux distro, even on musl based ones.**
|
||||
|
||||
It is possible that this appimage may fail to work with appimagelauncher, I recommend these alternatives instead:
|
||||
|
||||
* [AM](https://github.com/ivan-hc/AM) `am -i citron` or `appman -i citron`
|
||||
|
||||
* [dbin](https://github.com/xplshn/dbin) `dbin install citron.appimage`
|
||||
|
||||
* [soar](https://github.com/pkgforge/soar) `soar install citron`
|
||||
|
||||
This appimage works without fuse2 as it can use fuse3 instead, it can also work without fuse at all thanks to the [uruntime](https://github.com/VHSgunzo/uruntime)
|
||||
|
||||
<details>
|
||||
<summary><b><i>raison d'être</i></b></summary>
|
||||
<img src="https://github.com/user-attachments/assets/d40067a6-37d2-4784-927c-2c7f7cc6104b" alt="Inspiration Image">
|
||||
</a>
|
||||
</details>
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
ARCH="${ARCH:-$(uname -m)}"
|
||||
BUILD_PGO=false
|
||||
|
||||
if [ "$1" = 'v3-pgo' ] && [ "$ARCH" = 'x86_64' ]; then
|
||||
ARCH_FLAGS="-march=x86-64-v3 -O3 -USuccess -UNone -fuse-ld=lld"
|
||||
BUILD_PGO=true
|
||||
elif [ "$1" = 'pgo' ] && [ "$ARCH" = 'x86_64' ]; then
|
||||
ARCH_FLAGS="-march=x86-64 -mtune=generic -O3 -USuccess -UNone -fuse-ld=lld"
|
||||
BUILD_PGO=true
|
||||
elif [ "$1" = 'v3' ] && [ "$ARCH" = 'x86_64' ]; then
|
||||
ARCH_FLAGS="-march=x86-64-v3 -O3 -USuccess -UNone -fuse-ld=lld"
|
||||
elif [ "$ARCH" = 'x86_64' ]; then
|
||||
ARCH_FLAGS="-march=x86-64 -mtune=generic -O3 -USuccess -UNone -fuse-ld=lld"
|
||||
else
|
||||
|
||||
ARCH_FLAGS="-march=armv8-a -mtune=generic -O3 -USuccess -UNone -fuse-ld=lld"
|
||||
|
||||
fi
|
||||
|
||||
git clone --recursive "https://git.citron-emu.org/citron/emulator.git" ./citron
|
||||
cd ./citron
|
||||
|
||||
if [ "$DEVEL" = 'true' ]; then
|
||||
CITRON_TAG="$(git rev-parse --short HEAD)"
|
||||
VERSION="$CITRON_TAG"
|
||||
else
|
||||
CITRON_TAG=$(git describe --tags)
|
||||
git checkout "$CITRON_TAG"
|
||||
VERSION="$(echo "$CITRON_TAG" | awk -F'-' '{print $1}')"
|
||||
fi
|
||||
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::asio::io_service\b/boost::asio::io_context/g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::asio::io_service::strand\b/boost::asio::strand<boost::asio::io_context::executor_type>/g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's|#include *<boost/process/async_pipe.hpp>|#include <boost/process/v1/async_pipe.hpp>|g'
|
||||
find . -type f \( -name '*.cpp' -o -name '*.h' \) | xargs sed -i 's/\bboost::process::async_pipe\b/boost::process::v1::async_pipe/g'
|
||||
sed -i '/sse2neon/d' ./src/video_core/CMakeLists.txt
|
||||
sed -i '/sse2neon/d' ./src/video_core/CMakeLists.txt
|
||||
sed -i 's/cmake_minimum_required(VERSION 2.8)/cmake_minimum_required(VERSION 3.5)/' externals/xbyak/CMakeLists.txt
|
||||
|
||||
HEADER_PATH=$(pacman -Ql qt6-base | grep 'qpa/qplatformnativeinterface.h$' | awk '{print $2}')
|
||||
if [ -z "$HEADER_PATH" ]; then
|
||||
echo "ERROR: Could not find qplatformnativeinterface.h path." >&2
|
||||
exit 1
|
||||
fi
|
||||
QT_PRIVATE_INCLUDE_DIR=$(dirname "$(dirname "$HEADER_PATH")")
|
||||
CXX_FLAGS_EXTRA="-I${QT_PRIVATE_INCLUDE_DIR}"
|
||||
|
||||
if [ -z "$JOBS" ]; then JOBS=$(nproc --all); fi
|
||||
|
||||
if [ "$BUILD_PGO" = true ]; then
|
||||
# STAGE 1: Build with instrumentation using manual flags for reliability
|
||||
mkdir build_instrumented && cd build_instrumented
|
||||
PGO_FLAGS="-fprofile-generate"
|
||||
cmake .. -GNinja \
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=OFF -DCITRON_USE_BUNDLED_QT=OFF -DUSE_SYSTEM_QT=ON -DENABLE_QT6=ON \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=OFF -DCITRON_USE_BUNDLED_SDL2=ON -DCITRON_USE_EXTERNAL_SDL2=OFF \
|
||||
-DCITRON_TESTS=OFF -DCITRON_CHECK_SUBMODULES=OFF -DCITRON_USE_LLVM_DEMANGLE=OFF \
|
||||
-DCITRON_ENABLE_LTO=ON -DCITRON_USE_QT_MULTIMEDIA=ON -DCITRON_USE_QT_WEB_ENGINE=OFF \
|
||||
-DENABLE_QT_TRANSLATION=ON -DUSE_DISCORD_PRESENCE=ON -DBUNDLE_SPEEX=ON -DCITRON_USE_FASTER_LD=OFF \
|
||||
-DCITRON_USE_EXTERNAL_Vulkan_HEADERS=ON -DCITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES=ON \
|
||||
-DCITRON_ENABLE_UPDATER=OFF -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $PGO_FLAGS -Wno-error -w ${CXX_FLAGS_EXTRA}" \
|
||||
-DCMAKE_C_FLAGS="$ARCH_FLAGS $PGO_FLAGS" \
|
||||
-DCMAKE_SYSTEM_PROCESSOR="$(uname -m)" -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
ninja -j${JOBS}
|
||||
|
||||
# STAGE 2: Generate, merge, and copy profile data
|
||||
echo "Starting instrumented application to generate profile data..."
|
||||
export LLVM_PROFILE_FILE="${PWD}/citron.profraw"
|
||||
xvfb-run -a --server-args="-screen 0 1024x768x24" ./bin/citron &
|
||||
XVFB_PID=$!
|
||||
echo "Running for 20 seconds to collect data... (PID: $XVFB_PID)"
|
||||
sleep 20
|
||||
echo "Stopping application..."
|
||||
kill -9 $XVFB_PID || true
|
||||
echo "Application stopped."
|
||||
llvm-profdata merge -o ./default.profdata "${LLVM_PROFILE_FILE}"
|
||||
|
||||
cd .. && rm -rf build && mkdir build
|
||||
echo "Copying profile data to the final build directory..."
|
||||
cp build_instrumented/default.profdata build/
|
||||
cd build
|
||||
|
||||
# STAGE 3: Build again using manual flags for reliability
|
||||
PGO_FLAGS="-fprofile-use=${PWD}/default.profdata"
|
||||
cmake .. -GNinja \
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=OFF -DCITRON_USE_BUNDLED_QT=OFF -DUSE_SYSTEM_QT=ON -DENABLE_QT6=ON \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=OFF -DCITRON_USE_BUNDLED_SDL2=ON -DCITRON_USE_EXTERNAL_SDL2=OFF \
|
||||
-DCITRON_TESTS=OFF -DCITRON_CHECK_SUBMODULES=OFF -DCITRON_USE_LLVM_DEMANGLE=OFF \
|
||||
-DCITRON_ENABLE_LTO=ON -DCITRON_USE_QT_MULTIMEDIA=ON -DCITRON_USE_QT_WEB_ENGINE=OFF \
|
||||
-DENABLE_QT_TRANSLATION=ON -DUSE_DISCORD_PRESENCE=ON -DBUNDLE_SPEEX=ON -DCITRON_USE_FASTER_LD=OFF \
|
||||
-DCITRON_USE_EXTERNAL_Vulkan_HEADERS=ON -DCITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES=ON \
|
||||
-DCITRON_ENABLE_UPDATER=OFF -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $PGO_FLAGS -Wno-error -w ${CXX_FLAGS_EXTRA}" \
|
||||
-DCMAKE_C_FLAGS="$ARCH_FLAGS $PGO_FLAGS" \
|
||||
-DCMAKE_SYSTEM_PROCESSOR="$(uname -m)" -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
else
|
||||
# REGULAR BUILD
|
||||
mkdir build && cd build
|
||||
cmake .. -GNinja \
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=OFF -DCITRON_USE_BUNDLED_QT=OFF -DUSE_SYSTEM_QT=ON -DENABLE_QT6=ON \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=OFF -DCITRON_USE_BUNDLED_SDL2=ON -DCITRON_USE_EXTERNAL_SDL2=OFF \
|
||||
-DCITRON_TESTS=OFF -DCITRON_CHECK_SUBMODULES=OFF -DCITRON_USE_LLVM_DEMANGLE=OFF \
|
||||
-DCITRON_ENABLE_LTO=ON -DCITRON_USE_QT_MULTIMEDIA=ON -DCITRON_USE_QT_WEB_ENGINE=OFF \
|
||||
-DENABLE_QT_TRANSLATION=ON -DUSE_DISCORD_PRESENCE=ON -DBUNDLE_SPEEX=ON -DCITRON_USE_FASTER_LD=OFF \
|
||||
-DCITRON_USE_EXTERNAL_Vulkan_HEADERS=ON -DCITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES=ON \
|
||||
-DCITRON_ENABLE_UPDATER=OFF -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS -Wno-error -w ${CXX_FLAGS_EXTRA}" \
|
||||
-DCMAKE_C_FLAGS="$ARCH_FLAGS" \
|
||||
-DCMAKE_SYSTEM_PROCESSOR="$(uname -m)" -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
fi
|
||||
|
||||
ninja -j${JOBS}
|
||||
sudo ninja install
|
||||
echo "$VERSION" >~/version
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
pacman -Syu --noconfirm --needed \
|
||||
base-devel \
|
||||
boost \
|
||||
boost-libs \
|
||||
catch2 \
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
enet \
|
||||
fmt \
|
||||
ffmpeg \
|
||||
gamemode \
|
||||
gcc \
|
||||
git \
|
||||
glslang \
|
||||
glu \
|
||||
hidapi \
|
||||
libdecor \
|
||||
libvpx \
|
||||
libxi \
|
||||
libxkbcommon-x11 \
|
||||
libxss \
|
||||
lld \
|
||||
llvm \
|
||||
mbedtls2 \
|
||||
mesa \
|
||||
nasm \
|
||||
ninja \
|
||||
nlohmann-json \
|
||||
numactl \
|
||||
openal \
|
||||
pulseaudio \
|
||||
pulseaudio-alsa \
|
||||
qt6-base \
|
||||
qt6-networkauth \
|
||||
qt6-multimedia \
|
||||
qt6-tools \
|
||||
qt6-wayland \
|
||||
qt6-translations \
|
||||
sdl2 \
|
||||
unzip \
|
||||
vulkan-headers \
|
||||
vulkan-mesa-layers \
|
||||
wget \
|
||||
xcb-util-cursor \
|
||||
xcb-util-image \
|
||||
xcb-util-renderutil \
|
||||
xcb-util-wm \
|
||||
xorg-server-xvfb \
|
||||
zip \
|
||||
zsync
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
ARCH="${ARCH:-$(uname -m)}"
|
||||
|
||||
# The VERSION is now passed as an environment variable from the workflow
|
||||
if [ -z "$APP_VERSION" ]; then
|
||||
echo "Error: APP_VERSION environment variable is not set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Construct unique names for the AppImage and tarball based on the build matrix.
|
||||
OUTNAME_BASE="citron_nightly-${APP_VERSION}-linux-${ARCH}${ARCH_SUFFIX}"
|
||||
export OUTNAME_APPIMAGE="${OUTNAME_BASE}.AppImage"
|
||||
export OUTNAME_TAR="${OUTNAME_BASE}.tar.zst"
|
||||
|
||||
URUNTIME="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/uruntime2appimage.sh"
|
||||
SHARUN="https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/refs/heads/main/useful-tools/quick-sharun.sh"
|
||||
|
||||
export DESKTOP=/usr/share/applications/org.citron_emu.citron.desktop
|
||||
export ICON=/usr/share/icons/hicolor/scalable/apps/org.citron_emu.citron.svg
|
||||
export DEPLOY_OPENGL=1
|
||||
export DEPLOY_VULKAN=1
|
||||
export DEPLOY_PIPEWIRE=1
|
||||
|
||||
wget --retry-connrefused --tries=30 "$SHARUN" -O ./quick-sharun
|
||||
chmod +x ./quick-sharun
|
||||
|
||||
./quick-sharun /usr/bin/citron* /usr/lib/libgamemode.so* /usr/lib/libpulse.so*
|
||||
|
||||
echo "Copying Qt translation files..."
|
||||
|
||||
mkdir -p ./AppDir/usr/share/qt6
|
||||
|
||||
cp -r /usr/share/qt6/translations ./AppDir/usr/share/qt6/
|
||||
|
||||
if [ "$DEVEL" = 'true' ]; then
|
||||
sed -i 's|Name=citron|Name=citron nightly|' ./AppDir/*.desktop
|
||||
fi
|
||||
|
||||
echo 'SHARUN_ALLOW_SYS_VK_ICD=1' > ./AppDir/.env
|
||||
|
||||
|
||||
echo "Creating tar.zst archive..."
|
||||
|
||||
(cd AppDir && tar -c --zstd -f ../"$OUTNAME_TAR" usr)
|
||||
echo "Successfully created $OUTNAME_TAR"
|
||||
|
||||
|
||||
wget --retry-connrefused --tries=30 "$URUNTIME" -O ./uruntime2appimage
|
||||
chmod +x ./uruntime2appimage
|
||||
|
||||
./uruntime2appimage
|
||||
|
||||
echo "Renaming versioned AppImage to the final suffixed name: ${OUTNAME_APPIMAGE}..."
|
||||
|
||||
SOURCE_APPIMAGE="citron_nightly-${APP_VERSION}-${ARCH}.AppImage"
|
||||
|
||||
mv -v "${SOURCE_APPIMAGE}" "${OUTNAME_APPIMAGE}"
|
||||
mv -v "${SOURCE_APPIMAGE}.zsync" "${OUTNAME_APPIMAGE}.zsync"
|
||||
|
||||
mkdir -p ./dist
|
||||
|
||||
mv -v ./*.AppImage* ./dist
|
||||
mv -v ./*.tar.zst ./dist
|
||||
Reference in New Issue
Block a user