Build native binaries #94
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: Build native binaries | |
| on: | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| output: | |
| - freetype-library | |
| - harfbuzz-library | |
| - slang-library | |
| - tracy-exe | |
| - tracy-library | |
| - vma-library | |
| os: | |
| - ubuntu-24.04 | |
| - windows-2025 | |
| - macos-15 | |
| name: ${{ matrix.output }} (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| EXANITE_BUILD_OUTPUT: submodules/Exanite.GameDev/outputs/native | |
| steps: | |
| # We always install all dependencies for simplicity | |
| # The duplicated dependencies are intentional | |
| - name: Setup dependencies (Linux) | |
| if: "runner.os == 'Linux'" | |
| run: | | |
| sudo apt-get update | |
| # harfbuzz-library | |
| sudo apt-get install -y pkg-config ragel gtk-doc-tools gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev | |
| # tracy-exe | |
| sudo apt-get install -y libglfw3-dev libfreetype-dev libcapstone-dev libdbus-1-dev libtbb-dev libgtk-3-dev debuginfod libwayland-dev libxkbcommon-dev libglvnd-dev wayland-protocols | |
| - name: Update Wayland for Tracy (Linux) | |
| if: "runner.os == 'Linux'" | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libffi-dev libxml2-dev meson ninja-build | |
| git clone https://gitlab.freedesktop.org/wayland/wayland | |
| cd wayland | |
| git checkout 1.24.0 | |
| meson setup build --prefix=/usr -Ddocumentation=false -Dtests=false | |
| ninja -C build | |
| sudo ninja -C build install | |
| - name: Enable long paths for Git (Windows) | |
| if: "runner.os == 'Windows'" | |
| run: git config --system core.longpaths true | |
| - name: Setup MSVC (Windows) | |
| if: "runner.os == 'Windows'" | |
| uses: TheMrMilchmann/setup-msvc-dev@v4 | |
| with: | |
| arch: x64 | |
| - name: Setup dependencies (Mac) | |
| if: "runner.os == 'macOS'" | |
| run: | | |
| brew update | |
| # harfbuzz-library | |
| brew install pkg-config ragel gtk-doc freetype glib cairo | |
| # tracy-exe | |
| brew install glfw freetype capstone tbb | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.0.100" | |
| - name: Get date for caching | |
| id: "get-date" | |
| shell: pwsh | |
| run: | | |
| echo "date=$(Get-Date -Format "yyyy-MM-dd")" >> $env:GITHUB_OUTPUT | |
| - name: Cache .git folder | |
| uses: actions/cache@v4 | |
| with: | |
| path: .git | |
| key: git-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/.gitmodules') }}-${{ steps.get-date.outputs.date }} | |
| restore-keys: | | |
| git-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/.gitmodules') }} | |
| - name: Checkout repository | |
| uses: actions/checkout@v5.0.0 | |
| with: | |
| token: ${{ secrets._GITHUB_TOKEN }} | |
| persist-credentials: true | |
| submodules: false | |
| lfs: false | |
| - name: Initialize Exanite.GameDev submodule | |
| run: | | |
| git config --global url."https://x-access-token:${{ secrets._GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/" | |
| git submodule update --init --recursive submodules/Exanite.GameDev | |
| - name: Fetch Slang tags | |
| working-directory: submodules/Exanite.GameDev/native/slang | |
| run: | | |
| git fetch https://github.com/shader-slang/slang.git "refs/tags/*:refs/tags/*" | |
| - name: Setup build system | |
| working-directory: submodules/Exanite.GameDev | |
| run: dotnet build projects/Exanite.Engine.BuildSystem | |
| - name: Build | |
| working-directory: submodules/Exanite.GameDev | |
| run: dotnet run --project projects/Exanite.Engine.BuildSystem -- build-${{ matrix.output }} | |
| # This currently sets RPath information on Mac and Linux | |
| - name: Post-process binaries | |
| shell: pwsh | |
| run: | | |
| $outputFolder = "${{ env.EXANITE_BUILD_OUTPUT }}" | |
| $files = Get-ChildItem -Path $outputFolder -Filter * -Recurse -File | |
| foreach ($file in $files) { | |
| switch ($true) { | |
| $IsWindows {} | |
| $IsLinux { | |
| # Set RPath | |
| patchelf --set-rpath "`$ORIGIN" $($file.FullName) | |
| # Set SoName | |
| patchelf --set-soname $($file.Name) $($file.FullName) | |
| } | |
| $IsMacOS { | |
| $rpaths = otool -l $($file.FullName) | | |
| Select-String -Pattern "path (.*) \(offset \d+\)" | | |
| ForEach-Object { $_.Matches.Groups[1].Value } | |
| # Clear existing rpaths | |
| foreach ($rpath in $rpaths) { | |
| install_name_tool -delete_rpath "$rpath" $($file.FullName) | |
| } | |
| # Set RPath | |
| install_name_tool -add_rpath "@loader_path" $($file.FullName) | |
| # Set install name | |
| $newName = "@rpath/$($file.Name)" | |
| install_name_tool -id "$newName" $($file.FullName) | |
| } | |
| } | |
| } | |
| # This helps with debugging since the contents vary per platform | |
| - name: Display build folder contents | |
| shell: pwsh | |
| working-directory: submodules/Exanite.GameDev/outputs/cache/cmake-ci | |
| run: | | |
| Get-ChildItem -Recurse | Select-Object -ExpandProperty FullName | |
| # This helps with debugging since the tools required are not cross-platform | |
| - name: Display binary information | |
| shell: pwsh | |
| run: | | |
| $outputFolder = "${{ env.EXANITE_BUILD_OUTPUT }}" | |
| if (-not (Test-Path $outputFolder)) { | |
| return | |
| } | |
| $files = Get-ChildItem -Path $outputFolder -Filter "*" -Recurse -File | |
| foreach ($file in $files) { | |
| Write-Host "Showing binary information for $($file.Name):" | |
| try { | |
| switch ($true) { | |
| $IsWindows { | |
| Write-Host "Symbols for $($file.Name):" | |
| dumpbin /EXPORTS $($file.FullName) | |
| Write-Host "" | |
| Write-Host "Dependencies for $($file.Name):" | |
| dumpbin /DEPENDENTS $($file.FullName) | |
| } | |
| $IsLinux { | |
| Write-Host "Symbols for $($file.Name):" | |
| nm -D -g $($file.FullName) | |
| Write-Host "" | |
| Write-Host "Dependencies for $($file.Name):" | |
| ldd $file.FullName | |
| Write-Host "" | |
| Write-Host "Required glibc version for $($file.Name):" | |
| objdump -T $($file.FullName) | Select-String "GLIBC_[.\d]+" | ForEach-Object { $_.Matches.Groups[0].Value } | Sort-Object -Unique | |
| Write-Host "" | |
| Write-Host "Soname for $($file.Name):" | |
| $soname = readelf -d $($file.FullName) | Select-String "SONAME" | |
| Write-Host $soname | |
| Write-Host "" | |
| Write-Host "RPath for $($file.Name):" | |
| $rpath = readelf -d $($file.FullName) | Select-String "RPATH|RUNPATH" | |
| if ($rpath) { | |
| Write-Host $rpath | |
| } else { | |
| Write-Host "No RPath found" | |
| } | |
| Write-Host "" | |
| Write-Host "Readelf for $($file.Name):" | |
| readelf -d $($file.FullName) | |
| } | |
| $IsMacOS { | |
| Write-Host "Symbols for $($file.Name):" | |
| nm -gU $($file.FullName) | |
| Write-Host "" | |
| Write-Host "Dependencies for $($file.Name):" | |
| otool -L $($file.FullName) | |
| Write-Host "" | |
| Write-Host "Install name for $($file.Name):" | |
| otool -D $($file.FullName) | |
| Write-Host "" | |
| Write-Host "RPath for $($file.Name):" | |
| $rpath = otool -l $file | Select-String -Pattern "LC_RPATH" -Context 1, 2 | |
| if ($rpath) { | |
| Write-Host $rpath | |
| } else { | |
| Write-Host "No RPath found" | |
| } | |
| Write-Host "" | |
| Write-Host "Required macOS version for $($file.Name):" | |
| otool -l $($file.FullName) | Select-String "LC_BUILD_VERSION" -Context 0,3 | |
| } | |
| } | |
| Write-Host "" | |
| } | |
| catch {} | |
| } | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: ${{ matrix.output }}-${{ matrix.os }} | |
| path: ${{ env.EXANITE_BUILD_OUTPUT }} | |
| combine-outputs: | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: [build] | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| path: artifacts | |
| - name: Combine into one folder | |
| run: | | |
| mkdir combined | |
| cp -r artifacts/*/* combined | |
| # File info is printed here because "file"'s command output is easier to read | |
| - name: Display binary information | |
| shell: pwsh | |
| run: | | |
| $folder = "combined" | |
| $files = Get-ChildItem -Path $folder -Filter "*" -Recurse -File | |
| foreach ($file in $files) { | |
| Write-Host "Showing binary information for $($file.Name):" | |
| file $($file.FullName) | |
| Write-Host | |
| } | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: Built binaries | |
| path: combined |