Skip to content

Build native binaries #94

Build native binaries

Build native binaries #94

Workflow file for this run

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