Skip to content

Commit 5712974

Browse files
authored
Merge pull request #3 from labstreaminglayer/modernize_uldaq
Modernize project using uldaq and newer LSL App conventions
2 parents a913fe0 + 1230ffa commit 5712974

30 files changed

Lines changed: 3352 additions & 253 deletions

.github/workflows/build.yml

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# =============================================================================
2+
# MCCOutlet Build Workflow
3+
# =============================================================================
4+
# Builds, packages, and optionally signs/notarizes MCCOutlet for
5+
# Linux and macOS. Windows is not supported (uldaq requires libusb + POSIX).
6+
#
7+
# Features:
8+
# - Multi-platform builds (Linux, macOS)
9+
# - Qt6 integration
10+
# - Automatic liblsl and uldaq fetch
11+
# - CPack packaging
12+
# - macOS code signing and notarization (on release)
13+
# =============================================================================
14+
15+
name: Build
16+
17+
on:
18+
push:
19+
branches: [main, master, dev]
20+
tags: ['v*']
21+
pull_request:
22+
branches: [main, master]
23+
release:
24+
types: [published]
25+
workflow_dispatch:
26+
27+
env:
28+
BUILD_TYPE: Release
29+
30+
jobs:
31+
# ===========================================================================
32+
# Build Job - Multi-platform builds
33+
# ===========================================================================
34+
build:
35+
name: ${{ matrix.config.name }}
36+
runs-on: ${{ matrix.config.os }}
37+
strategy:
38+
fail-fast: false
39+
matrix:
40+
config:
41+
- { name: "Ubuntu 22.04", os: ubuntu-22.04 }
42+
- { name: "Ubuntu 24.04", os: ubuntu-24.04 }
43+
- { name: "macOS", os: macos-14 }
44+
45+
steps:
46+
- name: Checkout
47+
uses: actions/checkout@v4
48+
49+
# -----------------------------------------------------------------------
50+
# Install CMake 3.28+ (Ubuntu 22.04 ships with 3.22)
51+
# -----------------------------------------------------------------------
52+
- name: Install CMake
53+
if: runner.os == 'Linux'
54+
uses: lukka/get-cmake@latest
55+
56+
# -----------------------------------------------------------------------
57+
# Install system dependencies
58+
# -----------------------------------------------------------------------
59+
- name: Install Linux dependencies
60+
if: runner.os == 'Linux'
61+
run: |
62+
sudo apt-get update
63+
sudo apt-get install -y \
64+
autoconf automake libtool \
65+
libusb-1.0-0-dev \
66+
libgl1-mesa-dev libxkbcommon-dev libxcb-cursor0
67+
68+
- name: Install macOS dependencies
69+
if: runner.os == 'macOS'
70+
run: |
71+
brew install autoconf automake libtool libusb
72+
73+
# -----------------------------------------------------------------------
74+
# Install Qt6
75+
# -----------------------------------------------------------------------
76+
- name: Install Qt
77+
uses: jurplel/install-qt-action@v4
78+
with:
79+
version: '6.8.*'
80+
cache: true
81+
82+
# -----------------------------------------------------------------------
83+
# Configure
84+
# -----------------------------------------------------------------------
85+
- name: Configure CMake
86+
run: >
87+
cmake -S . -B build
88+
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
89+
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/install
90+
${{ matrix.config.cmake_extra }}
91+
92+
# -----------------------------------------------------------------------
93+
# Build
94+
# -----------------------------------------------------------------------
95+
- name: Build
96+
run: cmake --build build --config ${{ env.BUILD_TYPE }} --parallel
97+
98+
# -----------------------------------------------------------------------
99+
# Install
100+
# -----------------------------------------------------------------------
101+
- name: Install
102+
run: cmake --install build --config ${{ env.BUILD_TYPE }}
103+
104+
# -----------------------------------------------------------------------
105+
# Test CLI
106+
# -----------------------------------------------------------------------
107+
- name: Test CLI (Linux)
108+
if: runner.os == 'Linux'
109+
run: ./install/bin/MCCOutletCLI --help
110+
111+
- name: Test CLI (macOS)
112+
if: runner.os == 'macOS'
113+
run: ./install/MCCOutletCLI --help
114+
115+
# -----------------------------------------------------------------------
116+
# Package
117+
# -----------------------------------------------------------------------
118+
- name: Package
119+
run: cpack -C ${{ env.BUILD_TYPE }}
120+
working-directory: build
121+
122+
# -----------------------------------------------------------------------
123+
# Upload Artifacts
124+
# -----------------------------------------------------------------------
125+
- name: Upload Artifacts
126+
uses: actions/upload-artifact@v4
127+
with:
128+
name: package-${{ matrix.config.os }}
129+
path: |
130+
build/*.tar.gz
131+
build/*.deb
132+
if-no-files-found: ignore
133+
134+
# ===========================================================================
135+
# macOS Signing and Notarization (Release only)
136+
# ===========================================================================
137+
sign-macos:
138+
name: Sign & Notarize (macOS)
139+
needs: build
140+
if: github.event_name == 'release'
141+
runs-on: macos-14
142+
143+
steps:
144+
- name: Checkout
145+
uses: actions/checkout@v4
146+
147+
- name: Download macOS Artifact
148+
uses: actions/download-artifact@v4
149+
with:
150+
name: package-macos-14
151+
path: packages
152+
153+
- name: Extract Package
154+
run: |
155+
cd packages
156+
tar -xzf *.tar.gz
157+
# Move contents out of versioned subdirectory to packages/
158+
SUBDIR=$(ls -d MCCOutlet-*/ | head -1)
159+
mv "$SUBDIR"/* .
160+
rmdir "$SUBDIR"
161+
ls -la
162+
163+
# -----------------------------------------------------------------------
164+
# Install Apple Certificates
165+
# -----------------------------------------------------------------------
166+
- name: Install Apple Certificates
167+
env:
168+
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
169+
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
170+
run: |
171+
# Create temporary keychain with random password
172+
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
173+
MACOS_CI_KEYCHAIN_PWD=$(openssl rand -base64 32)
174+
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
175+
security default-keychain -s $KEYCHAIN_PATH
176+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
177+
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
178+
179+
# Import certificate
180+
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
181+
echo -n "$MACOS_CERTIFICATE" | base64 --decode -o $CERTIFICATE_PATH
182+
security import $CERTIFICATE_PATH -P "$MACOS_CERTIFICATE_PWD" -k $KEYCHAIN_PATH -A -t cert -f pkcs12
183+
rm $CERTIFICATE_PATH
184+
185+
# Allow codesign to access keychain
186+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
187+
security list-keychain -d user -s $KEYCHAIN_PATH
188+
189+
# Extract identity name and export to environment
190+
IDENTITY=$(security find-identity -v -p codesigning $KEYCHAIN_PATH | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}')
191+
echo "APPLE_CODE_SIGN_IDENTITY_APP=$IDENTITY" >> $GITHUB_ENV
192+
193+
# -----------------------------------------------------------------------
194+
# Setup Notarization Credentials
195+
# -----------------------------------------------------------------------
196+
- name: Setup Notarization
197+
env:
198+
NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
199+
NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
200+
NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
201+
run: |
202+
xcrun notarytool store-credentials "notarize-profile" \
203+
--apple-id "$NOTARIZATION_APPLE_ID" \
204+
--password "$NOTARIZATION_PWD" \
205+
--team-id "$NOTARIZATION_TEAM_ID"
206+
echo "APPLE_NOTARIZE_KEYCHAIN_PROFILE=notarize-profile" >> $GITHUB_ENV
207+
208+
# -----------------------------------------------------------------------
209+
# Sign and Notarize
210+
# -----------------------------------------------------------------------
211+
- name: Sign and Notarize
212+
env:
213+
ENTITLEMENTS_FILE: ${{ github.workspace }}/app.entitlements
214+
run: |
215+
# Sign GUI app bundle (--deep handles all nested code including lsl.framework)
216+
APP_PATH=$(find packages -name "*.app" -type d | head -1)
217+
if [[ -n "$APP_PATH" ]]; then
218+
./scripts/sign_and_notarize.sh "$APP_PATH" --notarize
219+
fi
220+
221+
# Sign CLI and its bundled lsl.framework
222+
CLI_PATH=$(find packages -name "MCCOutletCLI" -type f | head -1)
223+
if [[ -n "$CLI_PATH" ]]; then
224+
CLI_DIR=$(dirname "$CLI_PATH")
225+
# Sign framework first (dependency must be signed before dependent)
226+
if [[ -d "$CLI_DIR/Frameworks/lsl.framework" ]]; then
227+
codesign --force --sign "$APPLE_CODE_SIGN_IDENTITY_APP" --options runtime \
228+
"$CLI_DIR/Frameworks/lsl.framework"
229+
fi
230+
./scripts/sign_and_notarize.sh "$CLI_PATH" --notarize
231+
fi
232+
233+
# -----------------------------------------------------------------------
234+
# Repackage
235+
# -----------------------------------------------------------------------
236+
- name: Repackage
237+
run: |
238+
cd packages
239+
240+
# Remove original unsigned package
241+
rm -f *.tar.gz
242+
243+
# Get project version from CMakeLists.txt
244+
VERSION=$(grep 'VERSION [0-9]' ../CMakeLists.txt | head -1 | sed 's/.*VERSION \([0-9.]*\).*/\1/')
245+
echo "Detected version: $VERSION"
246+
247+
# Create signed package (universal binary)
248+
tar -cvzf "MCCOutlet-${VERSION}-macOS_universal-signed.tar.gz" \
249+
MCCOutlet.app MCCOutletCLI Frameworks
250+
251+
echo "Created package:"
252+
ls -la *.tar.gz
253+
254+
- name: Upload Signed Package
255+
uses: actions/upload-artifact@v4
256+
with:
257+
name: package-macos-signed
258+
path: packages/*-signed.tar.gz
259+
260+
- name: Upload to Release
261+
if: github.event_name == 'release'
262+
uses: softprops/action-gh-release@v2
263+
with:
264+
files: packages/*-signed.tar.gz
265+
266+
# ===========================================================================
267+
# Upload unsigned packages to release
268+
# ===========================================================================
269+
release:
270+
name: Upload to Release
271+
needs: build
272+
if: github.event_name == 'release'
273+
runs-on: ubuntu-latest
274+
275+
steps:
276+
- name: Download All Artifacts
277+
uses: actions/download-artifact@v4
278+
with:
279+
path: artifacts
280+
281+
- name: Upload to Release
282+
uses: softprops/action-gh-release@v2
283+
with:
284+
files: |
285+
artifacts/package-ubuntu-*/*.tar.gz
286+
artifacts/**/*.deb

.gitignore

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,10 @@
1-
build*/
2-
3-
# Prerequisites
4-
*.d
5-
6-
# Compiled Object files
7-
*.slo
8-
*.lo
9-
*.o
10-
*.obj
11-
12-
# Precompiled Headers
13-
*.gch
14-
*.pch
15-
16-
# Compiled Dynamic libraries
17-
*.so
18-
*.dylib
19-
*.dll
20-
21-
# Fortran module files
22-
*.mod
23-
*.smod
24-
25-
# Compiled Static libraries
26-
*.lai
27-
*.la
28-
*.a
29-
*.lib
30-
31-
# Executables
32-
*.exe
33-
*.out
34-
*.app
1+
ui_*.h
2+
/build*/
3+
/CMakeLists.txt.user
4+
/CMakeSettings.json
5+
/.vs/
6+
/out/
7+
.DS_Store
8+
.idea
9+
.cmake-build-*/
10+
.cache/

.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)