Add ARM (explicit) runners to github CI/CD #724
Workflow file for this run
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: 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 |