name: C/C++ CI on: push: paths-ignore: - '**/*.md' pull_request: paths-ignore: - '**/*.md' env: BUILD_CONFIG: Release SCCACHE_GHA_ENABLED: "true" PACKAGES: boost-system boost-filesystem boost-program-options boost-icl boost-variant curl openssl zlib jobs: format-check: name: Format Check (${{ matrix.path }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: path: - vita3k - tools steps: - name: Checkout uses: actions/checkout@v6 - name: Format check uses: jidicula/clang-format-action@v4.18.0 with: clang-format-version: '22' check-path: ${{ matrix.path }} build: name: Build (${{ matrix.os }}) needs: [format-check] runs-on: ${{ matrix.runs_on || matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest arch: x86_64 extra_cmake_args: -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DLINUXDEPLOY_COMMAND=/usr/local/bin/linuxdeploy-x86_64.AppImage cmake_preset: linux-ninja-clang-appimage - os: ubuntu-24.04-arm arch: aarch64 extra_cmake_args: -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DLINUXDEPLOY_COMMAND=/usr/local/bin/linuxdeploy-aarch64.AppImage cmake_preset: linux-ninja-clang-appimage - os: windows-latest arch: x86_64 cache_path: | C:\vcpkg\installed C:\vcpkg\packages vcpkg_triplet: x64-windows-static-md extra_cmake_args: -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static-md cmake_preset: windows-ninja - os: windows-11-arm cache_path: C:\msys2-ccache msys2_env: CLANGARM64 cmake_preset: windows-ninja - os: macos-intel runs_on: macos-latest cache_path: ~/Library/Caches/ccache extra_cmake_args: -DCMAKE_OSX_ARCHITECTURES="x86_64" -DFORCE_BUILD_OPENSSL_MAC=ON -DVITA3K_FORCE_CUSTOM_BOOST=ON cmake_preset: macos-ninja - os: macos-arm64 runs_on: macos-latest cache_path: ~/Library/Caches/ccache extra_cmake_args: -DCMAKE_OSX_ARCHITECTURES="arm64" -DFORCE_BUILD_OPENSSL_MAC=ON -DVITA3K_FORCE_CUSTOM_BOOST=ON cmake_preset: macos-ninja - os: android runs_on: ubuntu-latest cache_path: | /usr/local/share/vcpkg/installed /usr/local/share/vcpkg/packages steps: - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive - uses: actions/cache@v5 with: path: ${{ matrix.cache_path }} key: cache-${{ matrix.os }}-${{ env.BUILD_CONFIG }}-${{ github.sha }} restore-keys: | cache-${{ matrix.os }}-${{ env.BUILD_CONFIG }}- if: ${{ ! startsWith(matrix.os, 'ubuntu') }} - name: Set up build environment (macOS) run: | sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer brew install ccache create-dmg echo "$(brew --prefix ccache)/libexec" >> $GITHUB_PATH ccache --set-config=compiler_check=content if: startsWith(matrix.os, 'macos') - name: Set up build environment (Linux) run: | sudo add-apt-repository -y ppa:mhier/libboost-latest # boost repo sudo add-apt-repository universe sudo apt update sudo apt -y install libboost-filesystem1.83-dev libboost-program-options1.83-dev libboost-system1.83-dev libgtk-3-dev ninja-build libfuse2 sudo apt -y install gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev # Set up linuxdeploy for AppImage curl -sLO https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-${{ matrix.arch }}.AppImage sudo cp -f linuxdeploy-${{ matrix.arch }}.AppImage /usr/local/bin/ sudo chmod +x /usr/local/bin/linuxdeploy-${{ matrix.arch }}.AppImage # Set up linuxdeploy-plugin-qt for Qt bundling in AppImage curl -sLO https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/latest/download/linuxdeploy-plugin-qt-${{ matrix.arch }}.AppImage sudo cp -f linuxdeploy-plugin-qt-${{ matrix.arch }}.AppImage /usr/local/bin/ sudo chmod +x /usr/local/bin/linuxdeploy-plugin-qt-${{ matrix.arch }}.AppImage if: startsWith(matrix.os, 'ubuntu') - name: Set up build environment (Windows) run: | vcpkg install ${{ env.PACKAGES }} --triplet=${{ matrix.vcpkg_triplet }} if: startsWith(matrix.os, 'windows') && !matrix.msys2_env - uses: TheMrMilchmann/setup-msvc-dev@v4 with: arch: ${{ matrix.arch }} if: startsWith(matrix.os, 'windows') && !matrix.msys2_env - name: Set up build environment (Android) run: | sudo apt-get install -y ninja-build vcpkg install ${{ env.PACKAGES }} --triplet=arm64-android vcpkg install ${{ env.PACKAGES }} --triplet=x64-android if: matrix.os == 'android' - uses: hendrikmuhs/ccache-action@v1.2.23 if: matrix.os == 'android' - uses: mozilla-actions/sccache-action@v0.0.10 if: (startsWith(matrix.os, 'windows') && !matrix.msys2_env) || startsWith(matrix.os, 'ubuntu') with: disable_annotations: true - name: Set up MSYS2 (Windows ARM) uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msys2_env }} update: true cache: true install: | git pacboy: | clang:p ccache:p cmake:p lld:p ninja:p boost:p openssl:p curl:p zlib:p qt6-base:p qt6-svg:p qt6-tools:p if: matrix.msys2_env - name: Restore Gradle Cache uses: actions/cache@v5 with: path: '~/.gradle/' key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle', 'android/**/*.properties', 'android/**/*.xml', 'android/**/*.java', 'android/**/*.kt') }} restore-keys: | ${{ runner.os }}-gradle- if: matrix.os == 'android' - name: Decode Android keystore env: KEYSTORE_ENCODED: ${{ secrets.KEYSTORE }} run: | if [ -n "$KEYSTORE_ENCODED" ]; then echo "$KEYSTORE_ENCODED" | base64 --decode > /home/runner/keystore.jks fi if: matrix.os == 'android' - name: Reset ccache statistics run: ccache -z if: startsWith(matrix.os, 'macos') - name: Install Qt6 uses: jurplel/install-qt-action@v4 with: version: '6.8.2' cache: true if: matrix.os != 'android' && !matrix.msys2_env - name: Build Vita3K run: | cmake ${{ matrix.extra_cmake_args }} --preset ${{ matrix.cmake_preset }} cmake --build build/${{ matrix.cmake_preset }} --config ${{ env.BUILD_CONFIG }} if: matrix.os != 'android' && !matrix.msys2_env - name: Build Vita3K (MSYS2) shell: msys2 {0} run: | export CCACHE_DIR=$(cygpath -u "C:/msys2-ccache") cmake -G "Ninja Multi-Config" -B build/${{ matrix.cmake_preset }} \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache cmake --build build/${{ matrix.cmake_preset }} --config ${{ env.BUILD_CONFIG }} if: matrix.msys2_env - name: Deploy MSYS2 runtime libraries shell: msys2 {0} run: | BINDIR="build/${{ matrix.cmake_preset }}/bin/${{ env.BUILD_CONFIG }}" MSYS2_BINDIR="/${MSYSTEM,,}/bin" for dll in libc++.dll libunwind.dll; do if [ -f "$MSYS2_BINDIR/$dll" ]; then cp "$MSYS2_BINDIR/$dll" "$BINDIR/" fi done if: matrix.msys2_env - name: Print ccache statistics run: ccache -s if: startsWith(matrix.os, 'macos') - name: Print sccache statistics run: sccache --show-stats if: (startsWith(matrix.os, 'windows') && !matrix.msys2_env) || startsWith(matrix.os, 'ubuntu') - name: Build Vita3K (Android) env: SIGNING_STORE_PATH: "/home/runner/keystore.jks" SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} JVM_OPTS: -Xmx6G VCPKG_ROOT: /usr/local/share/vcpkg run: | mkdir -p android/app/assets rm -rf android/app/assets/data android/app/assets/shaders-builtin cp -r data android/app/assets/data cp -r vita3k/shaders-builtin android/app/assets/shaders-builtin export JAVA_HOME="$JAVA_HOME_17_X64" chmod +x android/gradlew if [ -e "$SIGNING_STORE_PATH" ]; then BUILD_TYPE=Release else BUILD_TYPE=Reldebug fi cd android ./gradlew --stacktrace --configuration-cache --build-cache --parallel --configure-on-demand :app:assemble${BUILD_TYPE} echo "APK_PATH=android/app/build/outputs/apk/${BUILD_TYPE,,}/app-${BUILD_TYPE,,}.apk" >> $GITHUB_ENV if: matrix.os == 'android' - name: Run tests working-directory: build/${{ matrix.cmake_preset }} run: ctest --build-config ${{ env.BUILD_CONFIG }} --output-on-failure if: matrix.os != 'android' && !matrix.msys2_env - name: Compute git short SHA shell: bash run: echo "GIT_SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - name: Create DMG (macOS) run: | cd build/${{ matrix.cmake_preset }}/bin/${{ env.BUILD_CONFIG }} create-dmg \ --volname "Vita3K Installer" \ --volicon Vita3K.app/Contents/Resources/Vita3K.icns \ --window-size 500 300 \ --icon-size 100 \ --icon Vita3K.app 120 115 \ --app-drop-link 360 115 \ vita3k-${{ env.GIT_SHORT_SHA }}-${{ matrix.os }}.dmg \ Vita3K.app rm -rf Vita3K.app if: startsWith(matrix.os, 'macos') - name: Prepare Linux AppImage artifact run: | cd build/${{ matrix.cmake_preset }}/bin/${{ env.BUILD_CONFIG }} mkdir -p ../appimage mv -f *AppImage* ../appimage/ if: startsWith(matrix.os, 'ubuntu') - name: Upload artifact (Linux AppImage) uses: actions/upload-artifact@v7 with: name: vita3k-${{ env.GIT_SHORT_SHA }}-${{ matrix.os }}-appimage path: build/${{ matrix.cmake_preset }}/bin/appimage if: startsWith(matrix.os, 'ubuntu') - name: Upload artifact (Android apk) uses: actions/upload-artifact@v7 with: name: vita3k-${{ env.GIT_SHORT_SHA }}-android path: ${{ env.APK_PATH }} if: matrix.os == 'android' - name: Upload artifact uses: actions/upload-artifact@v7 with: name: vita3k-${{ env.GIT_SHORT_SHA }}-${{ matrix.os }} path: build/${{ matrix.cmake_preset }}/bin/${{ env.BUILD_CONFIG }} if: matrix.os != 'android' create-release: needs: [build] runs-on: ubuntu-latest concurrency: group: create-release cancel-in-progress: false if: | github.ref == 'refs/heads/master' && github.repository == 'Vita3K/Vita3K' steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Download Artifacts uses: actions/download-artifact@v8 - name: Get commit info run: | echo "GIT_SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV echo "BUILD_VARIABLE=$(git rev-list --count HEAD)" >> $GITHUB_ENV echo "LAST_COMMIT_MESSAGE=$(git log -1 --pretty=format:'%s')" >> $GITHUB_ENV - name: Get last committer env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | COMMITTER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/${{ github.repository }}/commits/${{ github.sha }} \ | jq -r '.commit.author.name') echo "COMMITTER_NAME=$COMMITTER" >> $GITHUB_ENV - name: Prepare artifacts run: | mkdir -p artifacts-master artifacts-store files=$(find . -maxdepth 1 -type d -name "vita3k-*") for f in $files; do dir=$(basename $f) if [[ $dir == *-android ]]; then echo "Processing $dir (Android)" cp $dir/*.apk artifacts-master/android-latest.apk cp $dir/*.apk artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-android.apk elif [[ $dir == *-macos-intel ]]; then echo "Processing $dir (macOS Intel)" cp $dir/*.dmg artifacts-master/macos-latest.dmg cp $dir/*.dmg artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-macos-intel.dmg elif [[ $dir == *-macos-arm64 ]]; then echo "Processing $dir (macOS ARM64)" cp $dir/*.dmg artifacts-master/macos-arm64-latest.dmg cp $dir/*.dmg artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-macos-arm64.dmg elif [[ $dir == *-ubuntu-latest-appimage ]]; then echo "Processing $dir (x86_64 AppImage)" cp $dir/*.AppImage* artifacts-master/ cp $dir/*.AppImage* artifacts-store/ elif [[ $dir == *-ubuntu-24.04-arm-appimage ]]; then echo "Processing $dir (ARM64 AppImage)" cp $dir/*.AppImage* artifacts-master/ cp $dir/*.AppImage* artifacts-store/ elif [[ $dir == *-ubuntu-latest ]]; then echo "Processing $dir (Ubuntu x86_64)" (cd $dir && zip -r ../artifacts-master/ubuntu-latest.zip *) 7z a -mx=9 artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-ubuntu-x86_64.7z $dir elif [[ $dir == *-ubuntu-24.04-arm ]]; then echo "Processing $dir (Ubuntu ARM64)" (cd $dir && zip -r ../artifacts-master/ubuntu-aarch64-latest.zip *) 7z a -mx=9 artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-ubuntu-aarch64.7z $dir elif [[ $dir == *-windows-latest ]]; then echo "Processing $dir (Windows x86_64)" (cd $dir && zip -r ../artifacts-master/windows-latest.zip *) 7z a -mx=9 artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-windows-x86_64.7z $dir elif [[ $dir == *-windows-11-arm ]]; then echo "Processing $dir (Windows ARM64)" (cd $dir && zip -r ../artifacts-master/windows-arm64-latest.zip *) 7z a -mx=9 artifacts-store/vita3k-${{ env.BUILD_VARIABLE }}-${{ env.GIT_SHORT_SHA }}-windows-arm64.7z $dir fi done echo "=== artifacts-master ===" ls -al artifacts-master/ echo "=== artifacts-store ===" ls -al artifacts-store/ - name: "Upload to store repository" uses: tcnksm/ghr@v0 with: tag: ${{ env.BUILD_VARIABLE }} path: artifacts-store/ owner: ${{ github.repository_owner }} repository: Vita3K-builds name: "Build: ${{ env.BUILD_VARIABLE }}" body: "Corresponding commit: [${{ env.LAST_COMMIT_MESSAGE }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }}) (${{ env.COMMITTER_NAME }})" token: ${{ secrets.STORE_TOKEN }} - name: "Upload to master repository" uses: tcnksm/ghr@v0 with: tag: continuous path: artifacts-master/ delete: "true" owner: ${{ github.repository_owner }} repository: Vita3K name: "Automatic CI builds" body: "Corresponding commit: ${{ github.sha }}\nVita3K Build: ${{ env.BUILD_VARIABLE }}"