Skip to content

Add ARM (explicit) runners to github CI/CD #724

Add ARM (explicit) runners to github CI/CD

Add ARM (explicit) runners to github CI/CD #724

Workflow file for this run

name: C/C++ CI
on:
push:
branches:
- main
- dev
tags: ['*']
paths:
- '**'
- '!docs/**'
- '!.github/**'
- '.github/workflows/cppcmake.yml'
pull_request:
release:
types: ['created']
workflow_dispatch:
inputs:
cmakeextra:
description: 'Extra CMake options'
required: false
default: ''
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
config:
# x86_64 Linux builds
- {name: "ubuntu-22.04-x64", os: "ubuntu-22.04", arch: "x86_64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
- {name: "ubuntu-24.04-x64", os: "ubuntu-24.04", arch: "x86_64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
# ARM Linux builds - cross-compiled with QEMU testing (Jetson, Raspberry Pi compatible)
# SHLIBDEPS must be disabled for cross-compiled packages as the host system
# does not have the target architecture libraries installed
- {name: "ubuntu-22.04-arm64", os: "ubuntu-22.04", arch: "aarch64", cross_compile: true, cmake_extra: "-DLSL_BUNDLED_PUGIXML=ON -DLSL_DISABLE_PACKAGE_SHLIBDEPS=ON" }
- {name: "ubuntu-22.04-armhf", os: "ubuntu-22.04", arch: "armv7", cross_compile: true, cmake_extra: "-DLSL_BUNDLED_PUGIXML=ON -DLSL_DISABLE_PACKAGE_SHLIBDEPS=ON" }
# Native ARM build
# - {name: "ubuntu-24.04-arm64-native", os: "ubuntu-24.04-arm", arch: "aarch64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
# Windows builds
- {name: "windows-x64", os: "windows-latest", arch: "x86_64", cmake_extra: "-T v142,host=x86"}
- {name: "windows-x86", os: "windows-latest", arch: "x86", cmake_extra: "-T v142,host=x86 -A Win32"}
- {name: "windows-arm64", os: "windows-11-arm", arch: "aarch64", cmake_extra: "-T v143,host=ARM64 -A ARM64"}
# macOS builds (Apple Silicon + Intel)
# - {name: "macos-latest", os: "macos-latest", arch: "universal"}
steps:
- uses: actions/checkout@v5
# Set up cross-compilation toolchain for ARM on Linux
- name: Install cross-compilation toolchain
if: matrix.config.cross_compile && runner.os == 'Linux'
run: |
sudo apt-get update
if [[ "${{ matrix.config.arch }}" == "aarch64" ]]; then
sudo apt-get install -y --no-install-recommends \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu
echo "CMAKE_TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE=${GITHUB_WORKSPACE}/cmake/toolchains/aarch64-linux-gnu.cmake" >> $GITHUB_ENV
elif [[ "${{ matrix.config.arch }}" == "armv7" ]]; then
sudo apt-get install -y --no-install-recommends \
gcc-arm-linux-gnueabihf \
g++-arm-linux-gnueabihf
echo "CMAKE_TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE=${GITHUB_WORKSPACE}/cmake/toolchains/arm-linux-gnueabihf.cmake" >> $GITHUB_ENV
fi
# Cache dependencies for Linux
- name: Cache APT packages
if: runner.os == 'Linux'
uses: actions/cache@v4
with:
path: /var/cache/apt/archives
key: ${{ runner.os }}-apt-${{ matrix.config.name }}-${{ hashFiles('.github/workflows/cppcmake.yml') }}
restore-keys: |
${{ runner.os }}-apt-${{ matrix.config.name }}-
${{ runner.os }}-apt-
# Cache build artifacts with ccache
- name: Cache ccache
if: runner.os == 'Linux' || runner.os == 'macOS'
uses: actions/cache@v4
with:
path: ~/.ccache
key: ${{ runner.os }}-ccache-${{ matrix.config.name }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ccache-${{ matrix.config.name }}-
${{ runner.os }}-ccache-
- name: Install ccache
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
if [[ "${{ runner.os }}" == "Linux" ]]; then
sudo apt-get install -y ccache
elif [[ "${{ runner.os }}" == "macOS" ]]; then
brew install ccache
fi
ccache --max-size=500M
ccache --set-config=compression=true
- name: Install dependencies
if: runner.os == 'Linux'
run: |
if [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
sudo apt-get install -y --no-install-recommends libpugixml-dev
fi
- name: Configure CMake
run: |
# Set up ccache as compiler wrapper (skip for cross-compilation)
if [[ "${{ runner.os }}" == "Linux" || "${{ runner.os }}" == "macOS" ]] && [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
export CC="ccache gcc"
export CXX="ccache g++"
fi
cmake --version
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PWD}/install \
-DLSL_UNITTESTS=ON \
-DLSL_BENCHMARKS=ON \
-DCPACK_PACKAGE_DIRECTORY=${PWD}/package \
-DCPACK_PACKAGE_FILE_NAME="liblsl-${{ matrix.config.arch }}" \
-Dlslgitrevision=${{ github.sha }} \
-Dlslgitbranch=${{ github.ref }} \
${CMAKE_TOOLCHAIN} \
${{ matrix.config.cmake_extra }} \
${{ github.event.inputs.cmakeextra }}
echo "Build directory: ${PWD}"
- name: Build
run: |
cmake --build build --config Release -j
# Show ccache statistics
if command -v ccache &> /dev/null; then
ccache -s
fi
- name: Install
run: cmake --build build --config Release --target install
- name: Test install using examples
run: |
# Test that the in-tree install was successful by building the examples
cmake -S examples -B examples/build \
-DLSL_INSTALL_ROOT=${PWD}/install \
-DCMAKE_INSTALL_PREFIX=examples/build/install \
-DLSL_COMFY_DEFAULTS=ON \
${CMAKE_TOOLCHAIN} \
${{ matrix.config.cmake_extra }} \
${{ github.event.inputs.cmakeextra }}
cmake --build examples/build --target install --config Release -j
# Run example binary (skip for cross-compiled builds - no QEMU)
if [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
./examples/build/install/bin/HandleMetaData
else
echo "Skipping example execution for cross-compiled build (requires real ARM hardware)"
echo "Build validation successful - binary can be tested on target hardware"
fi
- name: Package
run: |
echo "Creating package for ${{ matrix.config.arch }}"
cmake --build build --target package --config Release -j
# On Debian / Ubuntu the dependencies can only be resolved for
# already installed packages (only for native builds, not cross-compiled)
if [[ "${{ matrix.config.os }}" == ubuntu-* ]] && [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
cmake -DCPACK_DEBIAN_PACKAGE_SHLIBDEPS=ON build
sudo dpkg -i package/*.deb
cmake --build build --target package --config Release -j
dpkg -I package/liblsl*.deb
fi
if [[ "${{ matrix.config.cross_compile }}" == "true" ]]; then
echo "Cross-compiled ${{ matrix.config.arch }} package created"
ls -lh package/
fi
cmake -E remove_directory package/_CPack_Packages
cp testing/lslcfgs/default.cfg . 2>/dev/null || true
- name: upload install dir
uses: actions/upload-artifact@master
with:
name: build-${{ matrix.config.name }}
path: install
- name: upload package
uses: actions/upload-artifact@master
with:
name: pkg-${{ matrix.config.name }}
path: package
- name: print network config
run: |
which ifconfig && ifconfig
if [ `which ip` ]; then
ip link
ip addr
ip route
ip -6 route
fi
# Run tests (native builds only)
- name: Unit tests
if: matrix.config.cross_compile != true
run: |
# Set up core dumps for debugging
if [[ "${{ matrix.config.name }}" == ubuntu-* ]]; then
ulimit -c unlimited
echo "$PWD/dumps/corefile-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
fi
mkdir -p dumps
# Run unit tests
install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
timeout-minutes: 10
- name: upload dump
if: failure()
uses: actions/upload-artifact@master
with:
name: dumps-${{ matrix.config.name }}
path: dumps
- name: upload to release page
if: github.event_name == 'release'
env:
TOKEN: "token ${{ secrets.GITHUB_TOKEN }}"
TAG: ${{ github.event.release.tag_name }}
UPLOAD_URL: ${{ github.event.release.upload_url }}
run: |
# Do try this at home! The REST API is documented at
# https://docs.github.com/en/free-pro-team@latest/rest and you can get a personal
# access token at https://github.com/settings/tokens
# (set TOKEN to "bearer abcdef1234")
# you can get the UPLOAD_URL with a short bash snippet; make sure to set the env var TAG:
# UPLOAD_URL=$(curl -H 'Accept: application/vnd.github.v3+json' $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases/tags/$TAG | jq -r .upload_url)
UPLOAD_URL=${UPLOAD_URL%\{*} # remove "{name,label}" suffix
for pkg in package/*.*; do
NAME=$(basename $pkg)
MIME=$(file --mime-type $pkg|cut -d ' ' -f2)
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: $TOKEN" -H "Content-Type: $MIME" --data-binary @$pkg $UPLOAD_URL?name=$NAME
done