Skip to content

Commit 8b1b286

Browse files
committed
Modernize template app
* CMake * Apple-framework * Apple sign & notarize
1 parent edf3d52 commit 8b1b286

34 files changed

Lines changed: 2437 additions & 713 deletions

.appveyor.yml

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

.github/workflows/build.yml

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# =============================================================================
2+
# LSL Application Build Workflow
3+
# =============================================================================
4+
# This workflow builds, tests, and packages the LSL application for all
5+
# supported platforms. It serves as a reference for other LSL applications.
6+
#
7+
# Features:
8+
# - Multi-platform builds (Linux, macOS, Windows)
9+
# - Qt6 integration
10+
# - Automatic liblsl fetch via FetchContent
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 (arm64)", os: macos-14 }
44+
- { name: "macOS (x64)", os: macos-13 }
45+
- { name: "Windows", os: windows-latest }
46+
47+
steps:
48+
- name: Checkout
49+
uses: actions/checkout@v4
50+
51+
# -----------------------------------------------------------------------
52+
# Install Qt6 (6.8 LTS across all platforms)
53+
# -----------------------------------------------------------------------
54+
- name: Install Linux dependencies
55+
if: runner.os == 'Linux'
56+
run: |
57+
sudo apt-get update
58+
sudo apt-get install -y libgl1-mesa-dev libxkbcommon-dev libxcb-cursor0
59+
60+
- name: Install Qt
61+
uses: jurplel/install-qt-action@v4
62+
with:
63+
version: '6.8.*'
64+
cache: true
65+
66+
# -----------------------------------------------------------------------
67+
# Configure
68+
# -----------------------------------------------------------------------
69+
- name: Configure CMake
70+
run: >
71+
cmake -S . -B build
72+
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
73+
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/install
74+
-DLSL_FETCH_IF_MISSING=ON
75+
76+
# -----------------------------------------------------------------------
77+
# Build
78+
# -----------------------------------------------------------------------
79+
- name: Build
80+
run: cmake --build build --config ${{ env.BUILD_TYPE }} --parallel
81+
82+
# -----------------------------------------------------------------------
83+
# Install
84+
# -----------------------------------------------------------------------
85+
- name: Install
86+
run: cmake --install build --config ${{ env.BUILD_TYPE }}
87+
88+
# -----------------------------------------------------------------------
89+
# Test CLI
90+
# -----------------------------------------------------------------------
91+
- name: Test CLI (Unix)
92+
if: runner.os != 'Windows'
93+
run: ./install/LSLTemplateCLI --help
94+
95+
- name: Test CLI (Windows)
96+
if: runner.os == 'Windows'
97+
run: ./install/LSLTemplateCLI.exe --help
98+
99+
# -----------------------------------------------------------------------
100+
# Package
101+
# -----------------------------------------------------------------------
102+
- name: Package
103+
run: cpack -C ${{ env.BUILD_TYPE }}
104+
working-directory: build
105+
106+
# -----------------------------------------------------------------------
107+
# Upload Artifacts
108+
# -----------------------------------------------------------------------
109+
- name: Upload Artifacts
110+
uses: actions/upload-artifact@v4
111+
with:
112+
name: package-${{ matrix.config.os }}
113+
path: |
114+
build/*.zip
115+
build/*.tar.gz
116+
build/*.deb
117+
if-no-files-found: ignore
118+
119+
# ===========================================================================
120+
# macOS Signing and Notarization (Release only)
121+
# ===========================================================================
122+
sign-macos:
123+
name: Sign & Notarize (macOS)
124+
needs: build
125+
if: github.event_name == 'release'
126+
runs-on: macos-14
127+
128+
steps:
129+
- name: Checkout
130+
uses: actions/checkout@v4
131+
132+
- name: Download macOS Artifact
133+
uses: actions/download-artifact@v4
134+
with:
135+
name: package-macos-14
136+
path: packages
137+
138+
- name: Extract Package
139+
run: |
140+
cd packages
141+
tar -xzf *.tar.gz
142+
ls -la
143+
144+
# -----------------------------------------------------------------------
145+
# Install Apple Certificates
146+
# -----------------------------------------------------------------------
147+
- name: Install Apple Certificates
148+
env:
149+
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
150+
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
151+
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
152+
run: |
153+
# Create temporary keychain
154+
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
155+
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
156+
security default-keychain -s $KEYCHAIN_PATH
157+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
158+
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
159+
160+
# Import certificate
161+
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
162+
echo -n "$MACOS_CERTIFICATE" | base64 --decode -o $CERTIFICATE_PATH
163+
security import $CERTIFICATE_PATH -P "$MACOS_CERTIFICATE_PWD" -k $KEYCHAIN_PATH -A -t cert -f pkcs12
164+
rm $CERTIFICATE_PATH
165+
166+
# Allow codesign to access keychain
167+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" $KEYCHAIN_PATH
168+
security list-keychain -d user -s $KEYCHAIN_PATH
169+
170+
# Extract identity name and export to environment
171+
IDENTITY=$(security find-identity -v -p codesigning $KEYCHAIN_PATH | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}')
172+
echo "APPLE_CODE_SIGN_IDENTITY_APP=$IDENTITY" >> $GITHUB_ENV
173+
174+
# -----------------------------------------------------------------------
175+
# Setup Notarization Credentials
176+
# -----------------------------------------------------------------------
177+
- name: Setup Notarization
178+
env:
179+
NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
180+
NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
181+
NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
182+
run: |
183+
xcrun notarytool store-credentials "notarize-profile" \
184+
--apple-id "$NOTARIZATION_APPLE_ID" \
185+
--password "$NOTARIZATION_PWD" \
186+
--team-id "$NOTARIZATION_TEAM_ID"
187+
echo "APPLE_NOTARIZE_KEYCHAIN_PROFILE=notarize-profile" >> $GITHUB_ENV
188+
189+
# -----------------------------------------------------------------------
190+
# Sign and Notarize
191+
# -----------------------------------------------------------------------
192+
- name: Sign and Notarize
193+
env:
194+
ENTITLEMENTS_FILE: ${{ github.workspace }}/app.entitlements
195+
run: |
196+
# Sign GUI app bundle (--deep handles all nested code)
197+
APP_PATH=$(find packages -name "*.app" -type d | head -1)
198+
if [[ -n "$APP_PATH" ]]; then
199+
./scripts/sign_and_notarize.sh "$APP_PATH" --notarize
200+
fi
201+
202+
# Sign CLI and its bundled liblsl
203+
CLI_PATH=$(find packages -name "LSLTemplateCLI" -type f | head -1)
204+
if [[ -n "$CLI_PATH" ]]; then
205+
CLI_DIR=$(dirname "$CLI_PATH")
206+
# Sign liblsl first (dependency must be signed before dependent)
207+
if [[ -f "$CLI_DIR/Frameworks/liblsl.dylib" ]]; then
208+
codesign --force --sign "$APPLE_CODE_SIGN_IDENTITY_APP" --options runtime \
209+
"$CLI_DIR/Frameworks/liblsl.dylib"
210+
fi
211+
./scripts/sign_and_notarize.sh "$CLI_PATH" --notarize
212+
fi
213+
214+
# -----------------------------------------------------------------------
215+
# Repackage
216+
# -----------------------------------------------------------------------
217+
- name: Repackage
218+
run: |
219+
cd packages
220+
# Remove original unsigned package
221+
rm -f *.tar.gz
222+
223+
# Get version from CMakeLists.txt
224+
VERSION=$(sed -n 's/.*VERSION \([0-9.]*\).*/\1/p' ../CMakeLists.txt | head -1)
225+
226+
# Create signed package with CLI and its Frameworks
227+
tar -czf "LSLTemplate-${VERSION}-macOS_arm64-signed.tar.gz" \
228+
LSLTemplate*.app LSLTemplateCLI Frameworks 2>/dev/null || true
229+
230+
- name: Upload Signed Package
231+
uses: actions/upload-artifact@v4
232+
with:
233+
name: package-macos-signed
234+
path: packages/*-signed.tar.gz
235+
236+
- name: Upload to Release
237+
if: github.event_name == 'release'
238+
uses: softprops/action-gh-release@v2
239+
with:
240+
files: packages/*-signed.tar.gz
241+
242+
# ===========================================================================
243+
# Upload unsigned packages to release
244+
# ===========================================================================
245+
release:
246+
name: Upload to Release
247+
needs: build
248+
if: github.event_name == 'release'
249+
runs-on: ubuntu-latest
250+
251+
steps:
252+
- name: Download All Artifacts
253+
uses: actions/download-artifact@v4
254+
with:
255+
path: artifacts
256+
257+
- name: Upload to Release
258+
uses: softprops/action-gh-release@v2
259+
with:
260+
files: |
261+
artifacts/**/*.zip
262+
artifacts/**/*.tar.gz
263+
artifacts/**/*.deb

.travis.yml

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

AppTemplate_cpp_qt.cfg

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

0 commit comments

Comments
 (0)