[CPU/XThread] Add DWARF .eh_frame unwind info for JIT code on Linux #579
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| paths-ignore: | |
| - '*.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| pull_request: | |
| paths-ignore: | |
| - '*.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| workflow_dispatch: | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@main | |
| - name: Setup | |
| env: | |
| LLVM_VERSION: 21 | |
| run: | | |
| UBUNTU_BASE=$(lsb_release -cs) | |
| wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc | |
| sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-$LLVM_VERSION main" | |
| sudo apt-get -y update | |
| sudo apt-get -y install clang-format-$LLVM_VERSION | |
| - name: Lint | |
| run: ./xenia-build.py lint --all | |
| build-linux: | |
| name: Build Linux | |
| needs: lint | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@main | |
| with: | |
| fetch-depth: 0 | |
| - name: Cache premake5 | |
| id: cache-premake5 | |
| uses: actions/cache@main | |
| with: | |
| path: tools/build/bin/premake5 | |
| key: ${{ runner.os }}-premake5-${{ hashFiles('third_party/premake-core/**') }} | |
| - name: Cache Qt6 | |
| id: cache-qt-linux | |
| uses: actions/cache@v3 | |
| with: | |
| path: /opt/Qt | |
| key: ${{ runner.os }}-qt6-6.10.1 | |
| restore-keys: | | |
| ${{ runner.os }}-qt6- | |
| - name: Cache linuxdeploy tools | |
| id: cache-linuxdeploy | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/linuxdeploy | |
| key: ${{ runner.os }}-linuxdeploy-tools | |
| restore-keys: | | |
| ${{ runner.os }}-linuxdeploy- | |
| - name: Cache submodules | |
| id: cache-submodules | |
| uses: actions/cache@v3 | |
| with: | |
| path: third_party | |
| key: ${{ runner.os }}-submodules-${{ hashFiles('.gitmodules') }}-${{ hashFiles('.git/modules/third_party/*/HEAD') }} | |
| - name: Cache Vulkan SDK | |
| id: cache-vulkan-sdk-linux | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/vulkan-sdk | |
| key: ${{ runner.os }}-vulkan-sdk-latest | |
| - name: Setup | |
| run: | | |
| UBUNTU_BASE=$(lsb_release -cs) | |
| wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc | |
| sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-21 main" | |
| sudo apt-get -y update | |
| sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libsdl2-dev libvulkan-dev libx11-xcb-dev clang-21 ninja-build spirv-tools libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-cursor0 libxcb-shape0 libfontconfig1-dev libxtst-dev | |
| # Install Vulkan SDK | |
| if [ '${{ steps.cache-vulkan-sdk-linux.outputs.cache-hit }}' != 'true' ]; then | |
| wget -qO vulkan-sdk.tar.xz https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.xz | |
| mkdir -p ~/vulkan-sdk | |
| tar -xf vulkan-sdk.tar.xz -C ~/vulkan-sdk | |
| fi | |
| VULKAN_SDK_VERSION=$(ls ~/vulkan-sdk) | |
| echo "VULKAN_SDK=$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64" >> $GITHUB_ENV | |
| echo "$HOME/vulkan-sdk/$VULKAN_SDK_VERSION/x86_64/bin" >> $GITHUB_PATH | |
| # Install Qt 6.10.1 via aqtinstall | |
| if [ '${{ steps.cache-qt-linux.outputs.cache-hit }}' != 'true' ]; then | |
| pip install aqtinstall | |
| echo "Available architectures for Qt 6.10.1:" | |
| aqt list-qt linux desktop --arch 6.10.1 || true | |
| aqt install-qt linux desktop 6.10.1 linux_gcc_64 -O /opt/Qt | |
| fi | |
| export PATH="/opt/Qt/6.10.1/gcc_64/bin:$PATH" | |
| export CMAKE_PREFIX_PATH="/opt/Qt/6.10.1/gcc_64" | |
| export PKG_CONFIG_PATH="/opt/Qt/6.10.1/gcc_64/lib/pkgconfig:$PKG_CONFIG_PATH" | |
| export QT_DIR="/opt/Qt/6.10.1/gcc_64" | |
| echo "/opt/Qt/6.10.1/gcc_64/bin" >> $GITHUB_PATH | |
| echo "CMAKE_PREFIX_PATH=/opt/Qt/6.10.1/gcc_64" >> $GITHUB_ENV | |
| echo "PKG_CONFIG_PATH=/opt/Qt/6.10.1/gcc_64/lib/pkgconfig" >> $GITHUB_ENV | |
| echo "QT_DIR=/opt/Qt/6.10.1/gcc_64" >> $GITHUB_ENV | |
| # Download linuxdeploy tools if not cached | |
| if [ '${{ steps.cache-linuxdeploy.outputs.cache-hit }}' != 'true' ]; then | |
| mkdir -p ~/linuxdeploy | |
| wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -O ~/linuxdeploy/linuxdeploy | |
| wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage -O ~/linuxdeploy/linuxdeploy-plugin-qt | |
| wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-x86_64.AppImage -O ~/linuxdeploy/linuxdeploy-plugin-appimage | |
| chmod +x ~/linuxdeploy/linuxdeploy ~/linuxdeploy/linuxdeploy-plugin-qt ~/linuxdeploy/linuxdeploy-plugin-appimage | |
| fi | |
| echo "$HOME/linuxdeploy" >> $GITHUB_PATH | |
| # Verify shader tools are available | |
| which glslangValidator && glslangValidator --version || echo "Warning: glslangValidator not found" | |
| which spirv-opt && spirv-opt --version || echo "Warning: spirv-opt not found" | |
| which spirv-dis || echo "Warning: spirv-dis not found" | |
| # Update submodules if not cached | |
| if [ '${{ steps.cache-submodules.outputs.cache-hit }}' != 'true' ]; then | |
| git submodule update --init --depth=1 -j$(getconf _NPROCESSORS_ONLN) $(grep -oP '(?<=path = )(?!third_party\/(DirectXShaderCompiler|premake-(androidndk|export-compile-commands))).+' .gitmodules) | |
| fi | |
| if [ '${{ steps.cache-premake5.outputs.cache-hit }}' != 'true' ]; then | |
| ./xenia-build.py premake | |
| cp third_party/premake-core/bin/release/premake5 tools/build/bin | |
| fi | |
| # Fetch data repos (game-patches, optimized-settings) | |
| ./xenia-build.py fetchdata | |
| - name: Build | |
| env: | |
| CC: clang-21 | |
| CXX: clang++-21 | |
| run: ./xenia-build.py build --config=Release | |
| - name: Prepare artifacts | |
| id: prepare_artifacts | |
| run: | | |
| binary=build/bin/Linux/Release/xenia_edge | |
| if [ $(stat -c%s $binary) -le 100000 ]; then | |
| echo "::error::Binary is too small." | |
| fi | |
| chmod +x $binary | |
| mkdir -p artifacts/xenia_edge | |
| # Use linuxdeploy to bundle Qt dependencies | |
| export QMAKE=/opt/Qt/6.10.1/gcc_64/bin/qmake | |
| export LD_LIBRARY_PATH=/opt/Qt/6.10.1/gcc_64/lib:$LD_LIBRARY_PATH | |
| # Install icons with proper naming for linuxdeploy | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/16x16/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/32x32/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/48x48/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/64x64/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/128x128/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/256x256/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/512x512/apps | |
| mkdir -p artifacts/xenia_edge/usr/share/icons/hicolor/1024x1024/apps | |
| cp assets/icon/16.png artifacts/xenia_edge/usr/share/icons/hicolor/16x16/apps/xenia_edge.png | |
| cp assets/icon/32.png artifacts/xenia_edge/usr/share/icons/hicolor/32x32/apps/xenia_edge.png | |
| cp assets/icon/48.png artifacts/xenia_edge/usr/share/icons/hicolor/48x48/apps/xenia_edge.png | |
| cp assets/icon/64.png artifacts/xenia_edge/usr/share/icons/hicolor/64x64/apps/xenia_edge.png | |
| cp assets/icon/128.png artifacts/xenia_edge/usr/share/icons/hicolor/128x128/apps/xenia_edge.png | |
| cp assets/icon/256.png artifacts/xenia_edge/usr/share/icons/hicolor/256x256/apps/xenia_edge.png | |
| cp assets/icon/512.png artifacts/xenia_edge/usr/share/icons/hicolor/512x512/apps/xenia_edge.png | |
| cp assets/icon/1024.png artifacts/xenia_edge/usr/share/icons/hicolor/1024x1024/apps/xenia_edge.png | |
| # Copy all necessary files (excluding build artifacts) next to the binary in AppDir | |
| mkdir -p artifacts/xenia_edge/usr/bin | |
| # Copy directories (optimized_settings, game_patches, etc.) | |
| find build/bin/Linux/Release -maxdepth 1 -type d ! -name Release -exec cp -r {} artifacts/xenia_edge/usr/bin/ \; | |
| # Copy any additional runtime files if needed (currently just directories are copied) | |
| # Run linuxdeploy with Qt plugin to deploy all Qt dependencies and create AppImage | |
| export EXTRA_PLATFORM_PLUGINS="libqwayland.so" | |
| ~/linuxdeploy/linuxdeploy --appdir artifacts/xenia_edge \ | |
| --executable $binary \ | |
| --desktop-file assets/xenia_edge.desktop \ | |
| --icon-file assets/icon/256.png \ | |
| --plugin qt \ | |
| --output appimage | |
| # linuxdeploy creates the AppImage in the current directory | |
| # Find and rename it to a standard name | |
| appimage_file=$(ls -1 *.AppImage | head -n1) | |
| if [ -z "$appimage_file" ]; then | |
| echo "::error::AppImage file not found after linuxdeploy" | |
| exit 1 | |
| fi | |
| # Create final artifacts directory and move the AppImage there | |
| mkdir -p artifacts/release | |
| mv "$appimage_file" artifacts/release/xenia_edge.AppImage | |
| chmod +x artifacts/release/xenia_edge.AppImage | |
| # Also copy LICENSE | |
| cp LICENSE artifacts/release/ | |
| - name: Upload xenia edge artifacts | |
| if: steps.prepare_artifacts.outcome == 'success' | |
| uses: actions/upload-artifact@main | |
| with: | |
| name: xenia_edge_linux | |
| path: artifacts/release | |
| if-no-files-found: error | |
| build-windows: | |
| name: Build Windows | |
| needs: lint | |
| runs-on: windows-2025 | |
| env: | |
| POWERSHELL_TELEMETRY_OPTOUT: 1 | |
| steps: | |
| - uses: actions/checkout@main | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Cache Vulkan SDK | |
| id: cache-vulkan-sdk | |
| uses: actions/cache@v3 | |
| with: | |
| path: C:\VulkanSDK | |
| key: ${{ runner.os }}-vulkan-sdk-${{ hashFiles('**/vulkan-sdk.exe') }} | |
| restore-keys: | | |
| ${{ runner.os }}-vulkan-sdk- | |
| - name: Cache Qt6 | |
| id: cache-qt | |
| uses: actions/cache@v3 | |
| with: | |
| path: C:\Qt | |
| key: ${{ runner.os }}-qt6-6.10.1 | |
| restore-keys: | | |
| ${{ runner.os }}-qt6- | |
| - name: Cache submodules | |
| id: cache-submodules | |
| uses: actions/cache@v3 | |
| with: | |
| path: third_party | |
| key: ${{ runner.os }}-submodules-${{ hashFiles('.gitmodules') }}-${{ hashFiles('.git/modules/third_party/*/HEAD') }} | |
| - name: Setup | |
| run: | | |
| # Install Vulkan SDK which includes spirv-tools | |
| if (Test-Path -Path "C:\VulkanSDK") { | |
| echo "Vulkan SDK found in cache." | |
| } else { | |
| Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe" -OutFile "vulkan-sdk.exe" | |
| Start-Process -FilePath "vulkan-sdk.exe" -ArgumentList "--accept-licenses", "--default-answer", "--confirm-command", "install" -Wait | |
| } | |
| $env:VULKAN_SDK = "C:\VulkanSDK\$(Get-ChildItem -Path 'C:\VulkanSDK' -Directory | Select-Object -First 1 -ExpandProperty Name)" | |
| $env:PATH = "$env:VULKAN_SDK\Bin;$env:PATH" | |
| echo "VULKAN_SDK=$env:VULKAN_SDK" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| echo "$env:VULKAN_SDK\Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| # Verify shader tools are available | |
| $spirvOptPath = "$env:VULKAN_SDK\Bin\spirv-opt.exe" | |
| if (Test-Path $spirvOptPath) { | |
| & $spirvOptPath --version | |
| echo "spirv-opt found at: $spirvOptPath" | |
| } else { | |
| echo "Warning: spirv-opt.exe not found at expected location" | |
| } | |
| $glslangPath = "$env:VULKAN_SDK\Bin\glslangValidator.exe" | |
| if (Test-Path $glslangPath) { | |
| & $glslangPath --version | |
| echo "glslangValidator found at: $glslangPath" | |
| } else { | |
| echo "Warning: glslangValidator.exe not found at expected location" | |
| } | |
| $spirvDisPath = "$env:VULKAN_SDK\Bin\spirv-dis.exe" | |
| if (Test-Path $spirvDisPath) { | |
| echo "spirv-dis found at: $spirvDisPath" | |
| } else { | |
| echo "Warning: spirv-dis.exe not found at expected location" | |
| } | |
| # Verify FXC is available (from Windows SDK) | |
| $fxcPaths = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\fxc.exe" -ErrorAction SilentlyContinue | Sort-Object FullName | |
| if ($fxcPaths) { | |
| $fxcPath = $fxcPaths[-1].FullName | |
| echo "FXC found at: $fxcPath" | |
| } else { | |
| echo "Warning: fxc.exe not found in Windows SDK" | |
| } | |
| # Install Qt6 | |
| $qtCacheHit = '${{ steps.cache-qt.outputs.cache-hit }}' | |
| if ($qtCacheHit -ne 'true') { | |
| pip install aqtinstall | |
| aqt install-qt windows desktop 6.10.1 win64_msvc2022_64 -O C:\Qt | |
| } | |
| $cacheHit = '${{ steps.cache-submodules.outputs.cache-hit }}' | |
| if ($cacheHit -ne 'true') { | |
| git submodule update --init --depth=1 -j $env:NUMBER_OF_PROCESSORS (Select-String -CaseSensitive '(?<=path = )(?!third_party\/(premake-(androidndk|cmake|export-compile-commands))).+' .gitmodules).Matches.Value | |
| } | |
| # Fetch data repos (game-patches, optimized-settings) | |
| python xenia-build.py fetchdata | |
| - name: Build | |
| run: python xenia-build.py build --config=Release --target=xenia-app | |
| - name: Prepare artifacts | |
| id: prepare_artifacts | |
| run: | | |
| $binary = 'build\bin\Windows\Release\xenia_edge.exe' | |
| if ((get-item $binary).Length -le 100000) { | |
| echo "::error::$binary is too small." | |
| } | |
| robocopy . build\bin\Windows\Release LICENSE /r:0 /w:0 | |
| # Copy all files and directories (Qt DLLs, plugins, etc.) excluding build artifacts | |
| robocopy build\bin\Windows\Release artifacts\xenia_edge /MIR /r:0 /w:0 /XF *.lib *.idb *.exp /XD generic iconengines imageformats networkinformation styles tls | |
| If ($LastExitCode -le 7) { echo "LastExitCode = $LastExitCode";$LastExitCode = 0 } | |
| - name: Upload xenia edge artifacts | |
| if: steps.prepare_artifacts.outcome == 'success' | |
| uses: actions/upload-artifact@main | |
| with: | |
| name: xenia_edge_windows | |
| path: artifacts\xenia_edge | |
| if-no-files-found: error | |
| release: | |
| name: Create Release | |
| needs: [build-linux, build-windows] | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.repository == 'has207/xenia-edge' && | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/edge' | |
| steps: | |
| - name: Download Linux artifacts | |
| uses: actions/download-artifact@main | |
| with: | |
| name: xenia_edge_linux | |
| path: linux_artifacts | |
| - name: Download Windows artifacts | |
| uses: actions/download-artifact@main | |
| with: | |
| name: xenia_edge_windows | |
| path: windows_artifacts | |
| - name: Create Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| # Create zips | |
| cd linux_artifacts | |
| # For Linux, just rename the AppImage (no need to zip a single file) | |
| mv xenia_edge.AppImage ../xenia_edge_linux.AppImage | |
| cd ../windows_artifacts | |
| 7z a ../xenia_edge_windows.zip * -xr!'*.pdb' -mx9 -bb3 | |
| cd .. | |
| # Create release | |
| tag=${GITHUB_SHA::7} | |
| gh release create $tag xenia_edge_linux.AppImage xenia_edge_windows.zip \ | |
| --target $GITHUB_SHA -t "xenia_edge" --generate-notes |