name: Build on: push: branches: - master # For testing. - actions tags: - "v*.*" paths-ignore: - '*.{txt,md}' - 'Tools/**' - '.{editorconfig,gitattributes,gitignore}' - 'appveyor.yml' pull_request: branches: - master paths-ignore: - '*.{txt,md}' - 'Tools/**' - '.{editorconfig,gitattributes,gitignore}' - 'appveyor.yml' env: BUILD_CONFIGURATION: Release jobs: build-windows: strategy: fail-fast: false matrix: platform: [x64, ARM64] runs-on: windows-latest steps: - uses: actions/checkout@v6 with: submodules: recursive - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0 - name: Check Valid Version Tags id: valid-tags shell: bash run: | # This is required for git describe --always to work for git-version.cpp. git fetch --deepen=15000 --no-recurse-submodules --tags || exit 0 echo "count=$(git tag -l 'v[0-9]*' | wc -l | tr -d ' ')" >> $GITHUB_OUTPUT # $env:GITHUB_OUTPUT on pwsh - name: Fetch upstream tags # Fallback to fetching tags from upstream if: steps.valid-tags.outputs.count == '0' shell: bash run: | # TODO: should try to fetch tags from whereever this repo was forked from before fetching from official repo git remote add upstream https://github.com/hrydgard/ppsspp.git git fetch --deepen=15000 --no-recurse-submodules --tags --force upstream || exit 0 - name: Create git-version.cpp for Windows # Not sure why the one at git-version-gen.cmd couldn't get the version properly. #if: github.ref_type == 'tag' run: | $GIT_VERSION=git describe --always echo "Num of Valid Tags = ${{ steps.valid-tags.outputs.count }}" echo "Test GitVer = ${{ github.ref_name }} / $GIT_VERSION / ${GITHUB_REF_NAME}" echo "const char *PPSSPP_GIT_VERSION = `"$GIT_VERSION`";" > git-version.cpp echo "#define PPSSPP_GIT_VERSION_NO_UPDATE 1" >> git-version.cpp # Generate Windows/win-version.h too. if ($GIT_VERSION.StartsWith("v")) { $WIN_VERSION_COMMA=$GIT_VERSION -replace '^v', '' -replace '-g[0-9a-f]+$', '' -replace '[-\.]', ',' echo "Test WinVer = $WIN_VERSION_COMMA" echo "#define PPSSPP_WIN_VERSION_STRING `"$GIT_VERSION`"" > Windows/win-version.h echo "#define PPSSPP_WIN_VERSION_COMMA $WIN_VERSION_COMMA" >> Windows/win-version.h echo "#define PPSSPP_WIN_VERSION_NO_UPDATE 1" >> Windows/win-version.h } - name: Build Windows working-directory: ${{ env.GITHUB_WORKSPACE }} run: msbuild /m /p:TrackFileAccess=false /p:Configuration=${{ env.BUILD_CONFIGURATION }} /p:Platform=${{ matrix.platform }} Windows/PPSSPP.sln - name: Package build working-directory: ${{ env.GITHUB_WORKSPACE }} run: | mkdir ppsspp cp PPSSPP*.exe ppsspp/ cp *.pdb ppsspp/ cp Windows/*.bat ppsspp/ cp -r assets ppsspp/assets - name: Package headless (non-Win32) if: matrix.platform != 'Win32' run: cp Windows/${{ matrix.platform }}/Release/*.exe ppsspp/ - name: Package headless (Win32) if: matrix.platform == 'Win32' run: cp Windows/Release/*.exe ppsspp/ - name: Upload build uses: actions/upload-artifact@v7 with: name: Windows ${{ matrix.platform }} build path: ppsspp/ - name: Create release if: github.ref_type == 'tag' working-directory: ${{ env.GITHUB_WORKSPACE }} run: | rm ppsspp/PPSSPPHeadless* rm ppsspp/UnitTest* rm ppsspp/*.pdb mkdir releases Compress-Archive -Path "ppsspp/*" -Update -DestinationPath "releases/PPSSPP-${{ github.ref_name }}-Windows-${{ matrix.platform }}.zip" - name: Upload release uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 if: github.ref_type == 'tag' with: files: releases/*.zip build-uwp: runs-on: windows-latest steps: - uses: actions/checkout@v6 with: submodules: recursive - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0 - name: Restore NuGet packages working-directory: ${{ github.workspace }}/UWP run: nuget restore PPSSPP_UWP.sln - name: Build UWP working-directory: ${{ env.GITHUB_WORKSPACE }} run: msbuild /m /p:TrackFileAccess=false /p:Configuration=${{ env.BUILD_CONFIGURATION }} /p:Platform=x64 /p:AppxPackageSigningEnabled=false UWP/PPSSPP_UWP.sln test-windows: runs-on: windows-latest needs: build-windows timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: submodules: false - name: Fetch tests working-directory: ${{ env.GITHUB_WORKSPACE }} # Doing this to avoid ffmpeg and other large submodules. run: git submodule update --init pspautotests assets/lang - name: Download build uses: actions/download-artifact@v8 with: name: Windows x64 build path: ppsspp/ - name: Execute unit tests working-directory: ${{ env.GITHUB_WORKSPACE }} run: ppsspp\\UnitTest.exe ALL - name: Execute headless tests working-directory: ${{ env.GITHUB_WORKSPACE }} run: python test.py -g --graphics=software build: name: build (${{ matrix.id }}) strategy: fail-fast: false matrix: include: - os: ubuntu-26.04 extra: test cc: clang cxx: clang++ args: ./b.sh --headless --unittest id: clang-normal - os: ubuntu-26.04 cc: gcc cxx: g++ args: ./b.sh --headless --unittest id: gcc-normal - os: ubuntu-26.04 extra: android cc: clang cxx: clang++ args: cd android && ./ab.sh -j2 APP_ABI=arm64-v8a UNITTEST=1 HEADLESS=1 id: android-arm64 - os: ubuntu-26.04 extra: android cc: clang cxx: clang++ args: cd android && ./ab.sh -j2 APP_ABI=armeabi-v7a UNITTEST=1 HEADLESS=1 id: android-arm32 - os: ubuntu-26.04 extra: android cc: clang cxx: clang++ args: cd android && ./ab.sh -j2 APP_ABI=x86_64 UNITTEST=1 HEADLESS=1 id: android-x86_64 - os: ubuntu-26.04 extra: android cc: clang cxx: clang++ args: cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1 id: android-vr - os: ubuntu-26.04 extra: android cc: clang cxx: clang++ args: ./b.sh --libretro_android ppsspp_libretro id: android-libretro - os: ubuntu-26.04 extra: qt cc: gcc cxx: g++ args: ./b.sh --qt id: qt - os: ubuntu-26.04 extra: libretro cc: gcc cxx: g++ args: make -C libretro -f Makefile -j2 id: gcc-libretro - os: ubuntu-26.04 extra: libretro cc: clang cxx: clang++ args: make -C libretro -f Makefile -j2 id: clang-libretro - os: ubuntu-26.04 extra: loongarch64 cc: gcc cxx: g++ args: ./b.sh --loongarch64 PPSSPPHeadless id: loongarch64 - os: macos-latest extra: test cc: clang cxx: clang++ args: ./b.sh --headless --unittest --no-png id: macos - os: macos-latest extra: libretro_mac cc: clang cxx: clang++ args: ./b.sh --libretro id: macos-libretro - os: macos-latest extra: ios cc: clang cxx: clang++ args: ./b-ios.sh id: ios runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 with: submodules: recursive - name: Fetch tags for macOS releases if: runner.os == 'macOS' # This is required for git describe --always to work for git-version.cpp. run: | git fetch --deepen=15000 --no-recurse-submodules --tags || exit 0 - name: Install Qt uses: jurplel/install-qt-action@48d3ad6db93f3627c8ee7a0454bc6f3744f7e730 # v4.3.1 if: matrix.extra == 'qt' with: cache: true version: 5.15.2 setup-python: false - name: Setup Android NDK uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0 if: matrix.extra == 'android' id: setup-ndk with: ndk-version: r21e - name: Install Linux dependencies if: runner.os == 'Linux' && matrix.extra != 'android' && matrix.extra != 'loongarch64' run: | sudo apt-get update -y -qq sudo apt-get install libsdl3-dev libgl1-mesa-dev libglu1-mesa-dev libsdl3-ttf-dev libfontconfig1-dev - name: Install macOS SDL3 dependencies if: runner.os == 'macOS' && matrix.id == 'macos' run: brew install sdl3 sdl3_ttf - name: Install loongarch64 cross-compilation dependencies if: matrix.extra == 'loongarch64' run: | sudo apt-get update -y -qq sudo apt-get install -y gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu binutils-loongarch64-linux-gnu libgl-dev libglu1-mesa-dev sudo cmake/scripts/setup-loongarch64-cross.sh - name: Install iOS dependencies if: matrix.id == 'ios' run: | brew install ldid dpkg pillow # Check Xcode version xcodebuild -version # List available Xcode versions ls /Applications | grep Xcode sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer - name: Create iOS Version.txt file if: matrix.id == 'ios' run: | # Create Version.txt file (should probably do this during building process) mkdir -p build-ios/PPSSPP.app GIT_VERSION=$(git describe --always --tags) echo ${GIT_VERSION#v} > build-ios/PPSSPP.app/Version.txt - name: Create macOS & iOS git-version.cpp for tagged release if: github.ref_type == 'tag' && (matrix.id == 'macos' || matrix.id == 'ios') run: | echo "const char *PPSSPP_GIT_VERSION = \"${GITHUB_REF_NAME}\";" > git-version.cpp echo "#define PPSSPP_GIT_VERSION_NO_UPDATE 1" >> git-version.cpp - name: Setup ccache uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 # Disable ccache on macos for now, it's become buggy for some reason. if: matrix.id != 'macos' with: key: ${{ matrix.id }} - name: Execute build env: CC: ${{ matrix.cc }} CXX: ${{ matrix.cxx }} NDK: ${{ steps.setup-ndk.outputs.ndk-path }} NDK_CCACHE: ccache USE_CCACHE: 1 run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export CCACHE_SLOPPINESS=clang_index_store,ivfsoverlay,include_file_ctime,include_file_mtime,modules,system_headers,time_macros if [ "${{ matrix.extra }}" == "android" ]; then export CCACHE_FILECLONE=true export CCACHE_DEPEND=true export CCACHE_COMPILERCHECK=content elif [ "$RUNNER_OS" == "macOS" ]; then export CCACHE_SLOPPINESS=pch_defines,$CCACHE_SLOPPINESS export CCACHE_FILECLONE=true export CCACHE_DEPEND=true export CCACHE_COMPILERCHECK=content fi ${{ matrix.args }} - name: Package build if: matrix.extra == 'test' || matrix.id == 'ios' run: | mkdir -p ppsspp if [ -e build*/$BUILD_CONFIGURATION/PPSSPPSDL ]; then cp build*/$BUILD_CONFIGURATION/PPSSPPSDL ppsspp/ elif [ -e build*/PPSSPPSDL.app ]; then cp -a build*/PPSSPPSDL.app ppsspp/ # GitHub Actions zipping kills symlinks and permissions. pushd ppsspp zip -qry PPSSPPSDL.zip PPSSPPSDL.app rm -rf PPSSPPSDL.app popd elif [ -e build-ios/PPSSPP.app ]; then # Get the final files generated by b-ios.h script find build -name 'PPSSPP*.ipa' -exec cp -a '{}' ppsspp/ \; find build -name 'PPSSPP*.xcarchive' -exec cp -a '{}' ppsspp/ \; find build -name 'PPSSPP*.deb' -exec cp -a '{}' ppsspp/ \; find build -name 'org.ppsspp*.deb' -exec cp -a '{}' ppsspp/ \; elif [ -e build*/PPSSPPSDL ]; then cp build*/PPSSPPSDL ppsspp/ cp -r assets ppsspp/assets fi if [ -e build*/$BUILD_CONFIGURATION/PPSSPPHeadless ]; then cp build*/$BUILD_CONFIGURATION/PPSSPPHeadless ppsspp/ elif [ -e build*/PPSSPPHeadless ]; then cp build*/PPSSPPHeadless ppsspp/ fi if [ -e build*/$BUILD_CONFIGURATION/PPSSPPUnitTest ]; then cp build*/$BUILD_CONFIGURATION/PPSSPPUnitTest ppsspp/ elif [ -e build*/PPSSPPUnitTest ]; then cp build*/PPSSPPUnitTest ppsspp/ fi - name: Upload build uses: actions/upload-artifact@v7 if: matrix.extra == 'test' with: name: ${{ matrix.os }} build path: ppsspp/ - name: Upload iOS build uses: actions/upload-artifact@v7 if: matrix.id == 'ios' with: name: ${{ matrix.id }} build path: ppsspp/ - name: Create macOS release if: github.ref_type == 'tag' && matrix.id == 'macos' working-directory: ppsspp run: mv PPSSPPSDL.zip PPSSPPSDL-macOS-${GITHUB_REF_NAME}.zip - name: Upload macOS & iOS release uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 if: github.ref_type == 'tag' && (matrix.id == 'macos' || matrix.id == 'ios') with: files: | ppsspp/*.zip ppsspp/*.ipa ppsspp/*.deb body: > PPSSPP is a cross-platform PSP emulator. Visit PPSSPP [official website](https://ppsspp.org) for a [full changelog](https://ppsspp.org/index.html#news) as well as the [downloads section](https://ppsspp.org/downloads.html) for other platforms. test: strategy: fail-fast: false matrix: os: [ubuntu-26.04, macos-latest] runs-on: ${{ matrix.os }} needs: build timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: submodules: false - name: Fetch tests working-directory: ${{ env.GITHUB_WORKSPACE }} # Doing this to avoid ffmpeg and other large submodules. run: git submodule update --init pspautotests - name: Install Linux dependencies if: runner.os == 'Linux' run: | sudo apt-get update -y -qq sudo apt-get install libsdl3-dev libgl1-mesa-dev libglu1-mesa-dev libsdl3-ttf-dev libfontconfig1-dev - name: Install macOS dependencies if: runner.os == 'macOS' run: brew install sdl3 sdl3_ttf - name: Download build uses: actions/download-artifact@v8 with: name: ${{ matrix.os }} build path: ppsspp/ # Not sure where it's ending up, but test.py can't find it... - name: Fix headless permissions working-directory: ${{ env.GITHUB_WORKSPACE }} run: | cp `find . -name PPSSPPHeadless` . chmod +x PPSSPPHeadless cp `find . -name PPSSPPUnitTest` . chmod +x PPSSPPUnitTest - name: Execute unit tests working-directory: ${{ env.GITHUB_WORKSPACE }} run: ./PPSSPPUnitTest ALL - name: Execute headless tests working-directory: ${{ env.GITHUB_WORKSPACE }} run: python test.py -g --graphics=software test-headless-alpine: runs-on: ubuntu-latest container: image: alpine:latest options: --shm-size=8g steps: - name: Install Linux dependencies (Alpine) run: | apk add build-base wget git bash cmake python3 glu-dev sdl3-dev sdl3_ttf-dev - uses: actions/checkout@v6 with: submodules: recursive - name: Fix git detected dubious ownership in repository run: | chown -R $(id -u):$(id -g) $PWD - name: Setup ccache uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23 - name: Compile ffmpeg run: | cd ffmpeg && ./linux_x86-64.sh - name: Build for testing run: | ./b.sh --headless --unittest - name: Execute unit tests run: | ./build/PPSSPPUnitTest ALL - name: Execute headless tests run: | python test.py -g --graphics=software