@@ -38,69 +38,175 @@ jobs:
3838 fail-fast : false
3939 matrix :
4040 config :
41- - {name: "ubuntu-22.04", os: "ubuntu-22.04", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
42- - {name: "ubuntu-24.04", os: "ubuntu-24.04", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
43- - {name: "ubuntu-24.04-arm", os: "ubuntu-24.04-arm", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
44- - {name: "windows-x64", os: "windows-latest", cmake_extra: "-T v142,host=x86"}
45- - {name: "windows-32", os: "windows-latest", cmake_extra: "-T v142,host=x86 -A Win32"}
46- - {name: "windows-arm", os: "windows-11-arm", cmake_extra: "-T v143,host=ARM64 -A ARM64"}
41+ # x86_64 Linux builds
42+ - {name: "ubuntu-22.04-x64", os: "ubuntu-22.04", arch: "x86_64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
43+ - {name: "ubuntu-24.04-x64", os: "ubuntu-24.04", arch: "x86_64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
44+
45+ # ARM Linux builds - cross-compiled with QEMU testing (Jetson, Raspberry Pi compatible)
46+ - {name: "ubuntu-22.04-arm64", os: "ubuntu-22.04", arch: "aarch64", cross_compile: true, cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
47+ - {name: "ubuntu-22.04-armhf", os: "ubuntu-22.04", arch: "armv7", cross_compile: true, cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
48+
49+ # Native ARM build (optional - can be enabled for additional validation)
50+ # - {name: "ubuntu-24.04-arm64-native", os: "ubuntu-24.04-arm", arch: "aarch64", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
51+
52+ # Windows builds
53+ - {name: "windows-x64", os: "windows-latest", arch: "x86_64", cmake_extra: "-T v142,host=x86"}
54+ - {name: "windows-x86", os: "windows-latest", arch: "x86", cmake_extra: "-T v142,host=x86 -A Win32"}
55+ - {name: "windows-arm64", os: "windows-11-arm", arch: "aarch64", cmake_extra: "-T v143,host=ARM64 -A ARM64"}
56+
57+ # macOS builds (Apple Silicon + Intel)
58+ - {name: "macos-latest", os: "macos-latest", arch: "universal"}
59+
4760 steps :
4861 - uses : actions/checkout@v4
4962
63+ # Set up cross-compilation toolchain for ARM on Linux
64+ - name : Install cross-compilation toolchain
65+ if : matrix.config.cross_compile && runner.os == 'Linux'
66+ run : |
67+ sudo apt-get update
68+ if [[ "${{ matrix.config.arch }}" == "aarch64" ]]; then
69+ sudo apt-get install -y --no-install-recommends \
70+ gcc-aarch64-linux-gnu \
71+ g++-aarch64-linux-gnu \
72+ qemu-user-static
73+ echo "CMAKE_TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE=${GITHUB_WORKSPACE}/.github/toolchains/aarch64-linux-gnu.cmake" >> $GITHUB_ENV
74+ echo "QEMU_LD_PREFIX=/usr/aarch64-linux-gnu" >> $GITHUB_ENV
75+ elif [[ "${{ matrix.config.arch }}" == "armv7" ]]; then
76+ sudo apt-get install -y --no-install-recommends \
77+ gcc-arm-linux-gnueabihf \
78+ g++-arm-linux-gnueabihf \
79+ qemu-user-static
80+ echo "CMAKE_TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE=${GITHUB_WORKSPACE}/.github/toolchains/arm-linux-gnueabihf.cmake" >> $GITHUB_ENV
81+ echo "QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf" >> $GITHUB_ENV
82+ fi
83+
84+ # Cache dependencies for Linux
85+ - name : Cache APT packages
86+ if : runner.os == 'Linux'
87+ uses : actions/cache@v4
88+ with :
89+ path : /var/cache/apt/archives
90+ key : ${{ runner.os }}-apt-${{ matrix.config.name }}-${{ hashFiles('.github/workflows/cppcmake.yml') }}
91+ restore-keys : |
92+ ${{ runner.os }}-apt-${{ matrix.config.name }}-
93+ ${{ runner.os }}-apt-
94+
95+ # Cache build artifacts with ccache
96+ - name : Cache ccache
97+ if : runner.os == 'Linux' || runner.os == 'macOS'
98+ uses : actions/cache@v4
99+ with :
100+ path : ~/.ccache
101+ key : ${{ runner.os }}-ccache-${{ matrix.config.name }}-${{ github.sha }}
102+ restore-keys : |
103+ ${{ runner.os }}-ccache-${{ matrix.config.name }}-
104+ ${{ runner.os }}-ccache-
105+
106+ - name : Install ccache
107+ if : runner.os == 'Linux' || runner.os == 'macOS'
108+ run : |
109+ if [[ "${{ runner.os }}" == "Linux" ]]; then
110+ sudo apt-get install -y ccache
111+ elif [[ "${{ runner.os }}" == "macOS" ]]; then
112+ brew install ccache
113+ fi
114+ ccache --max-size=500M
115+ ccache --set-config=compression=true
116+
117+ - name : Install dependencies
118+ if : runner.os == 'Linux'
119+ run : |
120+ if [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
121+ sudo apt-get install -y --no-install-recommends libpugixml-dev
122+ fi
123+
50124 - name : Configure CMake
51125 run : |
52- if [[ "${{ matrix.config.name }}" = ubuntu-2* ]]; then
53- sudo apt-get install -y --no-install-recommends libpugixml-dev
54- fi
55- cmake --version
56- cmake -S . -B build \
57- -DCMAKE_BUILD_TYPE=Release \
58- -DCMAKE_INSTALL_PREFIX=${PWD}/install \
59- -DLSL_UNITTESTS=ON \
60- -DLSL_BENCHMARKS=ON \
61- -DCPACK_PACKAGE_DIRECTORY=${PWD}/package \
62- -Dlslgitrevision=${{ github.sha }} \
63- -Dlslgitbranch=${{ github.ref }} \
64- ${{ matrix.config.cmake_extra }} \
65- ${{ github.event.inputs.cmakeextra }}
66- echo ${PWD}
67-
68- - name : make
69- run : cmake --build build --config Release -j
70-
71- - name : make install
126+ # Set up ccache as compiler wrapper
127+ if [[ "${{ runner.os }}" == "Linux" ]] || [[ "${{ runner.os }}" == "macOS" ]]; then
128+ export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
129+ export CC="ccache gcc"
130+ export CXX="ccache g++"
131+ fi
132+
133+ cmake --version
134+ cmake -S . -B build \
135+ -DCMAKE_BUILD_TYPE=Release \
136+ -DCMAKE_INSTALL_PREFIX=${PWD}/install \
137+ -DLSL_UNITTESTS=ON \
138+ -DLSL_BENCHMARKS=ON \
139+ -DCPACK_PACKAGE_DIRECTORY=${PWD}/package \
140+ -DCPACK_PACKAGE_FILE_NAME="liblsl-${{ matrix.config.arch }}" \
141+ -Dlslgitrevision=${{ github.sha }} \
142+ -Dlslgitbranch=${{ github.ref }} \
143+ ${CMAKE_TOOLCHAIN} \
144+ ${{ matrix.config.cmake_extra }} \
145+ ${{ github.event.inputs.cmakeextra }}
146+ echo "Build directory: ${PWD}"
147+
148+ - name : Build
149+ run : |
150+ cmake --build build --config Release -j
151+ # Show ccache statistics
152+ if command -v ccache &> /dev/null; then
153+ ccache -s
154+ fi
155+
156+ - name : Install
72157 run : cmake --build build --config Release --target install
73158
74- - name : test install using examples
159+ - name : Test install using examples
75160 run : |
76- # Test that the in-tree install was successful by building the examples
77- cmake -S examples -B examples/build \
78- -DLSL_INSTALL_ROOT=${PWD}/install \
79- -DCMAKE_INSTALL_PREFIX=examples/build/install \
80- -DLSL_COMFY_DEFAULTS=ON \
81- ${{ matrix.config.cmake_extra }} \
82- ${{ github.event.inputs.cmakeextra }}
83- cmake --build examples/build --target install --config Release -j
161+ # Set up QEMU for cross-compiled binaries
162+ QEMU_RUNNER=""
163+ if [[ "${{ matrix.config.cross_compile }}" == "true" ]]; then
164+ if [[ "${{ matrix.config.arch }}" == "aarch64" ]]; then
165+ QEMU_RUNNER="qemu-aarch64-static -L /usr/aarch64-linux-gnu"
166+ elif [[ "${{ matrix.config.arch }}" == "armv7" ]]; then
167+ QEMU_RUNNER="qemu-arm-static -L /usr/arm-linux-gnueabihf"
168+ fi
169+ fi
170+
171+ # Test that the in-tree install was successful by building the examples
172+ cmake -S examples -B examples/build \
173+ -DLSL_INSTALL_ROOT=${PWD}/install \
174+ -DCMAKE_INSTALL_PREFIX=examples/build/install \
175+ -DLSL_COMFY_DEFAULTS=ON \
176+ ${CMAKE_TOOLCHAIN} \
177+ ${{ matrix.config.cmake_extra }} \
178+ ${{ github.event.inputs.cmakeextra }}
179+ cmake --build examples/build --target install --config Release -j
180+
181+ # Run example with QEMU if cross-compiled
182+ if [[ -n "$QEMU_RUNNER" ]]; then
183+ $QEMU_RUNNER ./examples/build/install/bin/HandleMetaData
184+ else
84185 ./examples/build/install/bin/HandleMetaData
186+ fi
85187
86- - name : package
188+ - name : Package
87189 run : |
88- echo $GITHUB_REF
89- cmake --build build --target package --config Release -j
90- echo $PWD
91- ls -la
92- # On Debian / Ubuntu the dependencies can only be resolved for
93- # already installed packages. Therefore, we have built all
94- # packages without dependencies in the previous step,
95- # install them and rebuild them with dependency discovery enabled
96- if [[ "${{ matrix.config.os }}" == ubuntu-* ]]; then
97- cmake -DCPACK_DEBIAN_PACKAGE_SHLIBDEPS=ON .
98- sudo dpkg -i package/*.deb
99- cmake --build build --target package --config Release -j
100- dpkg -I package/liblsl*.deb
101- fi
102- cmake -E remove_directory package/_CPack_Packages
103- cp testing/lslcfgs/default.cfg .
190+ echo "Creating package for ${{ matrix.config.arch }}"
191+ cmake --build build --target package --config Release -j
192+
193+ # On Debian / Ubuntu the dependencies can only be resolved for
194+ # already installed packages (only for native builds, not cross-compiled)
195+ if [[ "${{ matrix.config.os }}" == ubuntu-* ]] && [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
196+ cmake -DCPACK_DEBIAN_PACKAGE_SHLIBDEPS=ON build
197+ sudo dpkg -i package/*.deb
198+ cmake --build build --target package --config Release -j
199+ dpkg -I package/liblsl*.deb
200+ fi
201+
202+ # For cross-compiled ARM packages, add architecture to package metadata
203+ if [[ "${{ matrix.config.cross_compile }}" == "true" ]]; then
204+ echo "Cross-compiled ${{ matrix.config.arch }} package created"
205+ ls -lh package/
206+ fi
207+
208+ cmake -E remove_directory package/_CPack_Packages
209+ cp testing/lslcfgs/default.cfg . 2>/dev/null || true
104210
105211 - name : upload install dir
106212 uses : actions/upload-artifact@master
@@ -124,16 +230,35 @@ jobs:
124230 ip -6 route
125231 fi
126232
127- # run internal tests
128- - name : unit tests
233+ # Run internal tests (with QEMU for cross-compiled binaries)
234+ - name : Unit tests
129235 run : |
130- if [[ "${{ matrix.config.name }}" = ubuntu-2* ]]; then
236+ # Set up core dumps for debugging (native builds only)
237+ if [[ "${{ matrix.config.name }}" == ubuntu-* ]] && [[ "${{ matrix.config.cross_compile }}" != "true" ]]; then
131238 ulimit -c unlimited
132239 echo "$PWD/dumps/corefile-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
133240 fi
134241 mkdir -p dumps
135- install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
136- install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
242+
243+ # Set up QEMU for cross-compiled binaries
244+ QEMU_RUNNER=""
245+ if [[ "${{ matrix.config.cross_compile }}" == "true" ]]; then
246+ if [[ "${{ matrix.config.arch }}" == "aarch64" ]]; then
247+ QEMU_RUNNER="qemu-aarch64-static -L /usr/aarch64-linux-gnu"
248+ elif [[ "${{ matrix.config.arch }}" == "armv7" ]]; then
249+ QEMU_RUNNER="qemu-arm-static -L /usr/arm-linux-gnueabihf"
250+ fi
251+ echo "Running tests with QEMU: $QEMU_RUNNER"
252+ fi
253+
254+ # Run unit tests
255+ if [[ -n "$QEMU_RUNNER" ]]; then
256+ $QEMU_RUNNER install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
257+ $QEMU_RUNNER install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
258+ else
259+ install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
260+ install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
261+ fi
137262 timeout-minutes : 10
138263
139264 - name : upload dump
0 commit comments