Skip to content

Multiplatform build and upload #750

Multiplatform build and upload

Multiplatform build and upload #750

Workflow file for this run

name: Multiplatform build and upload
on:
workflow_dispatch:
inputs:
tag:
description: "Release tag"
required: false
type: string
build_android_arm64v8a_release:
description: 'Build Android arm64-v8a Release'
required: true
default: true
type: boolean
build_android_arm64v8a_debug:
description: 'Build Android arm64-v8a Debug'
required: true
default: true
type: boolean
build_android_armv7a_release:
description: 'Build Android armeabi-v7a Release'
required: true
default: true
type: boolean
build_android_armv7a_debug:
description: 'Build Android armeabi-v7a Debug'
required: true
default: true
type: boolean
build_ios_release:
description: 'Build iOS Release'
required: true
default: true
type: boolean
build_ios_debug:
description: 'Build iOS Debug'
required: true
default: true
type: boolean
build_osx_release:
description: 'Build OSX Release'
required: true
default: true
type: boolean
build_osx_debug:
description: 'Build OSX Debug'
required: true
default: true
type: boolean
build_linux_x86_64_release:
description: 'Build Linux x86_64 Release'
required: true
default: true
type: boolean
build_linux_x86_64_debug:
description: 'Build Linux x86_64 Debug'
required: true
default: true
type: boolean
build_linux_aarch64_release:
description: 'Build Linux aarch64 Release'
required: true
default: true
type: boolean
build_linux_aarch64_debug:
description: 'Build Linux aarch64 Debug'
required: true
default: true
type: boolean
build_windows_release:
description: 'Build Windows Release'
required: true
default: true
type: boolean
build_windows_debug:
description: 'Build Windows Debug'
required: true
default: true
type: boolean
env:
GH_TOKEN: ${{ secrets.GNUS_TOKEN_1 }}
jobs:
build:
runs-on: ${{matrix.host}}
container:
image: ${{matrix.container}}
credentials:
username: ${{github.actor}}
password: ${{secrets.GNUS_TOKEN_1}}
strategy:
fail-fast: false
matrix:
target: [ Android, iOS, OSX, Linux, Windows ]
build-type: [ Debug, Release ]
abi: [ "" ]
include:
- target: Linux
host: sg-ubuntu-linux
abi: x86_64
build-type: Debug
container: ghcr.io/geniusventures/debian-bullseye:latest
- target: Linux
host: sg-ubuntu-linux
abi: x86_64
build-type: Release
container: ghcr.io/geniusventures/debian-bullseye:latest
- target: Linux
host: sg-arm-linux
abi: aarch64
build-type: Debug
container: ghcr.io/geniusventures/debian-bullseye:latest
- target: Linux
host: sg-arm-linux
abi: aarch64
build-type: Release
container: ghcr.io/geniusventures/debian-bullseye:latest
- target: Windows
host: SG-WIN11
- target: OSX
host: gv-OSX-Large
- target: iOS
host: gv-OSX-Large
- target: Android
host: sg-ubuntu-linux
build-type: Release
abi: arm64-v8a
- target: Android
host: sg-ubuntu-linux
build-type: Release
abi: armeabi-v7a
- target: Android
host: sg-ubuntu-linux
build-type: Debug
abi: arm64-v8a
- target: Android
host: sg-ubuntu-linux
build-type: Debug
abi: armeabi-v7a
exclude:
- target: Android
abi: ""
- target: Linux
abi: ""
steps:
- name: Configure Git Bash on Windows
if: ${{ runner.environment == 'self-hosted' && matrix.target == 'Windows' }}
run: |
$gitBinPath = "C:\Program Files\Git\bin"
if (Test-Path $gitBinPath) {
Add-Content -Path $env:GITHUB_PATH -Value $gitBinPath
$env:PATH = "$gitBinPath;$env:PATH"
}
Write-Output "Git Bash configured for bash shell commands"
$bashLocation = (Get-Command bash.exe -ErrorAction SilentlyContinue).Source
if ($bashLocation) {
Write-Output "Bash location: $bashLocation"
} else {
Write-Output "WARNING: bash.exe not found in PATH"
}
- name: Check if build should run
if: ${{ github.event_name == 'workflow_dispatch' }}
shell: bash
run: |
SHOULD_RUN="true"
# Only check inputs on workflow_dispatch events
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
case '${{matrix.target}}-${{matrix.abi}}-${{ matrix.build-type }}' in
Android-arm64-v8a-Release)
if [ '${{ inputs.build_android_arm64v8a_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Android-arm64-v8a-Debug)
if [ '${{ inputs.build_android_arm64v8a_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Android-armeabi-v7a-Release)
if [ '${{ inputs.build_android_armv7a_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Android-armeabi-v7a-Debug)
if [ '${{ inputs.build_android_armv7a_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
iOS-*-Release)
if [ '${{ inputs.build_ios_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
iOS-*-Debug)
if [ '${{ inputs.build_ios_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
OSX-*-Release)
if [ '${{ inputs.build_osx_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
OSX-*-Debug)
if [ '${{ inputs.build_osx_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Linux-x86_64-Release)
if [ '${{ inputs.build_linux_x86_64_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Linux-x86_64-Debug)
if [ '${{ inputs.build_linux_x86_64_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Linux-aarch64-Release)
if [ '${{ inputs.build_linux_aarch64_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Linux-aarch64-Debug)
if [ '${{ inputs.build_linux_aarch64_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Windows-*-Release)
if [ '${{ inputs.build_windows_release }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
Windows-*-Debug)
if [ '${{ inputs.build_windows_debug }}' != 'true' ]; then SHOULD_RUN="false"; fi
;;
esac
fi
if [ "$SHOULD_RUN" == "false" ]; then
echo "Skipping build for ${{ matrix.target }} ${{ matrix.abi }} ${{ matrix.build-type }}"
exit 78
fi
- name: Clean workspace (self-hosted runners)
if: ${{ runner.environment == 'self-hosted' }}
working-directory: ${{runner.workspace}}
run: |
echo "=== PRE-CLEANUP DEBUG ==="
echo "Current working directory: $(pwd)"
echo "Runner workspace: ${{runner.workspace}}"
echo "GitHub workspace: ${{github.workspace}}"
# Use sudo on Linux to handle root-owned files left by container jobs
SUDO=""
if [ "$(uname)" = "Linux" ]; then
SUDO="sudo"
fi
echo "=== CLEANUP ARTIFACTS ==="
# Clean contents of thirdparty directory but keep the directory itself
if [ -d "thirdparty" ]; then
echo "Cleaning thirdparty directory contents..."
$SUDO rm -rf thirdparty/* thirdparty/.* 2>/dev/null || true
echo "thirdparty directory cleaned (kept the directory)"
fi
echo "=== POST-CLEANUP DEBUG ==="
echo "Runner workspace contents:"
ls -la
if [ -d "thirdparty" ]; then
echo "thirdparty directory exists and contains:"
ls -la thirdparty/ 2>/dev/null || echo " (empty)"
fi
shell: bash
- name: Checkout
uses: actions/checkout@v4
with:
submodules: "recursive"
- name: Configure Linux host
if: ${{ runner.os == 'Linux'}}
run: |
sudo update-alternatives --install /usr/bin/cc cc $(which clang) 100
sudo update-alternatives --install /usr/bin/c++ c++ $(which clang++) 100
sudo update-alternatives --set cc $(which clang)
sudo update-alternatives --set c++ $(which clang++)
sudo apt install libvulkan-dev ninja-build -y
echo "CMAKE_GENERATOR=Ninja" >> $GITHUB_ENV
- name: Configure macOS host
if: ${{ runner.os == 'macOS'}}
run: |
brew install ninja bash gnu-tar
# Ensure GNU tar is first in PATH
if [ -d "/opt/homebrew/opt/gnu-tar/libexec/gnubin" ]; then
echo "PATH=/opt/homebrew/opt/gnu-tar/libexec/gnubin:$PATH" >> $GITHUB_ENV
echo "Using GNU tar from /opt/homebrew"
elif [ -d "/usr/local/opt/gnu-tar/libexec/gnubin" ]; then
echo "PATH=/usr/local/opt/gnu-tar/libexec/gnubin:$PATH" >> $GITHUB_ENV
echo "Using GNU tar from /usr/local"
else
echo "WARNING: GNU tar installation not found in expected locations"
echo "Available tar: $(which tar)"
fi
echo "CMAKE_GENERATOR=Ninja" >> $GITHUB_ENV
- name: Add Darwin toolchain
if: ${{ matrix.target == 'OSX'}}
run: rustup target add x86_64-apple-darwin
- name: Add iOS toolchain
if: ${{ matrix.target == 'iOS' }}
run: |
rustup toolchain install nightly-aarch64-apple-darwin
rustup component add rust-src --toolchain nightly-aarch64-apple-darwin
rustup target add aarch64-apple-ios
- name: Add Android toolchain
if: ${{ matrix.target == 'Android' }}
run: |
NDK_VERSION="r27b"
NDK_DIR="$HOME/android-ndk-$NDK_VERSION"
if [ ! -d "$NDK_DIR" ]; then
echo "Downloading Android NDK..."
wget https://dl.google.com/android/repository/android-ndk-$NDK_VERSION-linux.zip -O ndk.zip
unzip -o ndk.zip -d $HOME
rm ndk.zip
else
echo "Android NDK already exists at $NDK_DIR, skipping download"
fi
echo "ANDROID_NDK_HOME=$NDK_DIR" >> $GITHUB_ENV
rustup target add aarch64-linux-android
rustup target add armv7-linux-androideabi
- name: Install bindgen
run: cargo install cbindgen
- name: Add wasm Rust target
run: rustup target add wasm32-unknown-emscripten
- name: Set build directory
run: |
if [ '${{matrix.abi}}' ]; then
BUILD_DIRECTORY=build/${{matrix.target}}/${{matrix.build-type}}/${{matrix.abi}}
else
BUILD_DIRECTORY=build/${{matrix.target}}/${{matrix.build-type}}
fi
echo "BUILD_DIRECTORY=$BUILD_DIRECTORY" >> $GITHUB_ENV
shell: bash
- name: Configure CMake for Mac
if: ${{ matrix.target == 'OSX'}}
run: cmake -S build/${{matrix.target}} -B $BUILD_DIRECTORY -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DPLATFORM=MAC_UNIVERSAL
- name: Configure CMake for iOS
if: ${{ matrix.target == 'iOS'}}
run: cmake -S build/${{matrix.target}} -B $BUILD_DIRECTORY -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DPLATFORM=OS64
- name: Configure CMake for Android
if: ${{ matrix.target == 'Android'}}
run: cmake -S build/${{matrix.target}} -B $BUILD_DIRECTORY -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DANDROID_ABI=${{matrix.abi}}
- name: Configure CMake for Windows
if: ${{ matrix.target == 'Windows' }}
run: cmake -S build/${{matrix.target}} -B $env:BUILD_DIRECTORY -DCMAKE_BUILD_TYPE=${{matrix.build-type}}
- name: Configure CMake for Linux
if: ${{ matrix.target == 'Linux' }}
run: cmake -S build/${{matrix.target}} -B $BUILD_DIRECTORY -DCMAKE_BUILD_TYPE=${{matrix.build-type}}
- name: Build thirdparty
working-directory: ${{env.BUILD_DIRECTORY}}
run: cmake --build . --config ${{matrix.build-type}} -j
- name: Compress directories
if: github.ref_name == 'main' || github.ref_name == 'develop'
working-directory: ${{env.BUILD_DIRECTORY}}
shell: bash
run: |
if [ '${{matrix.abi}}' ]; then
FILE_NAME="${{matrix.target}}-${{matrix.abi}}-${{matrix.build-type}}.tar.gz"
else
FILE_NAME="${{matrix.target}}-${{matrix.build-type}}.tar.gz"
fi
echo "FILE_NAME=$FILE_NAME" >> $GITHUB_ENV
tar --no-wildcards-match-slash --exclude='./*/src' --exclude='./*/tmp' --transform='s|^\.|${{env.BUILD_DIRECTORY}}|g' -czf $FILE_NAME ./*/
- name: Set release tag
shell: bash
run: |
if ${{ github.event_name == 'workflow_dispatch' }} && [ '${{ github.event.inputs.tag }}' ]; then
RELEASE_TAG="${{ github.event.inputs.tag }}"
IS_TAG_RELEASE="true"
else
if [ '${{matrix.abi}}' ]; then
RELEASE_TAG="${{ matrix.target }}-${{matrix.abi}}-${{ github.ref_name }}-${{ matrix.build-type }}"
else
RELEASE_TAG="${{ matrix.target }}-${{ github.ref_name }}-${{ matrix.build-type }}"
fi
IS_TAG_RELEASE="false"
fi
echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV
echo "IS_TAG_RELEASE=$IS_TAG_RELEASE" >> $GITHUB_ENV
- name: Create release tag
if: github.ref_name == 'main' || github.ref_name == 'develop'
shell: bash
id: create-release-tag
run: |
echo "Checking if release $RELEASE_TAG exists..."
if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
if [ "$IS_TAG_RELEASE" == "false" ]; then
echo "Deleting existing release/tag $RELEASE_TAG..."
gh release delete "$RELEASE_TAG" --yes || true
git push origin ":refs/tags/$RELEASE_TAG" || true
git tag -d "$RELEASE_TAG" || true
fi
fi
echo "Creating new tag $RELEASE_TAG..."
git tag -f "$RELEASE_TAG" "${{ github.sha }}"
git push origin "$RELEASE_TAG" --force
echo "Creating GitHub release $RELEASE_TAG..."
gh release create "$RELEASE_TAG" \
--target "${{ github.sha }}" \
-t "${{ matrix.target }} ${{ github.ref_name }} ${{ matrix.build-type }} build" \
-n "Branch: ${{ github.ref_name }} | SHA: ${{ github.sha }}" \
$( [ "$IS_TAG_RELEASE" = "true" ] && echo "" || echo "--prerelease" )
- name: Upload file
if: github.ref_name == 'main' || github.ref_name == 'develop'
working-directory: ${{env.BUILD_DIRECTORY}}
run: gh release upload ${{env.RELEASE_TAG}} ${{env.FILE_NAME}} --clobber