Skip to content

Commit 433ef82

Browse files
committed
Merge remote-tracking branch 'upstream/cboulay/apple_framework' into feature/apple_framework
2 parents 4c44aaa + 22cae13 commit 433ef82

17 files changed

+1681
-74
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: 'Install Apple Certificates'
2+
description: 'Installs Apple signing and notarization certificates and sets up the keychain'
3+
inputs:
4+
MACOS_CERTIFICATE_APP:
5+
required: true
6+
MACOS_CERTIFICATE_INST:
7+
required: true
8+
MACOS_CERTIFICATE_PWD:
9+
required: true
10+
MACOS_CI_KEYCHAIN_PWD:
11+
required: true
12+
runs:
13+
using: "composite"
14+
steps:
15+
- name: Install certificates and provisioning profiles
16+
shell: bash
17+
run: |
18+
# Create temporary keychain
19+
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
20+
security create-keychain -p "${{ inputs.MACOS_CI_KEYCHAIN_PWD }}" $KEYCHAIN_PATH
21+
security default-keychain -s $KEYCHAIN_PATH
22+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
23+
security unlock-keychain -p "${{ inputs.MACOS_CI_KEYCHAIN_PWD }}" $KEYCHAIN_PATH
24+
25+
# Import certificates from secrets ...
26+
CERTIFICATE_PATH_APP=$RUNNER_TEMP/build_certificate_app.p12
27+
CERTIFICATE_PATH_INST=$RUNNER_TEMP/build_certificate_inst.p12
28+
echo -n "${{ inputs.MACOS_CERTIFICATE_APP }}" | base64 --decode -o $CERTIFICATE_PATH_APP
29+
echo -n "${{ inputs.MACOS_CERTIFICATE_INST }}" | base64 --decode -o $CERTIFICATE_PATH_INST
30+
# ... to keychain
31+
security import $CERTIFICATE_PATH_APP -P "${{ inputs.MACOS_CERTIFICATE_PWD }}" -k $KEYCHAIN_PATH -A -t cert -f pkcs12
32+
security import $CERTIFICATE_PATH_INST -P "${{ inputs.MACOS_CERTIFICATE_PWD }}" -k $KEYCHAIN_PATH -A -t cert -f pkcs12
33+
34+
# Set trusted partitions (groups of applications) that can access the keychain items
35+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${{ inputs.MACOS_CI_KEYCHAIN_PWD }}" $KEYCHAIN_PATH
36+
security list-keychain -d user -s $KEYCHAIN_PATH
37+
38+
# Get certificate identities into environment variables
39+
CERT_IDENTITY_APP=$(security find-identity -v -p codesigning $KEYCHAIN_PATH | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}')
40+
echo "APPLE_CODE_SIGN_IDENTITY_APP=$CERT_IDENTITY_APP" >> $GITHUB_ENV
41+
CERT_IDENTITY_INST=$(security find-identity -v -p basic $KEYCHAIN_PATH | grep "Developer ID Installer" | head -1 | awk -F'"' '{print $2}')
42+
echo "APPLE_CODE_SIGN_IDENTITY_INST=$CERT_IDENTITY_INST" >> $GITHUB_ENV

.github/workflows/apple.yml

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
name: Apple CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
tags: ['*']
9+
paths:
10+
- '**'
11+
- '!docs/**'
12+
- '!.github/**'
13+
- '.github/workflows/apple.yml'
14+
pull_request:
15+
release:
16+
types: ['created']
17+
workflow_dispatch:
18+
inputs:
19+
cmakeextra:
20+
description: 'Extra CMake options'
21+
required: false
22+
default: ''
23+
24+
concurrency:
25+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
26+
cancel-in-progress: true
27+
28+
defaults:
29+
run:
30+
shell: bash
31+
32+
jobs:
33+
build:
34+
name: ${{ matrix.config.name }}
35+
runs-on: ${{ matrix.config.os }}
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
config:
40+
- {name: "macOS-latest", os: "macOS-latest", cmake_extra: "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DLSL_UNITTESTS=ON -DLSL_BENCHMARKS=ON -DCMAKE_OSX_ARCHITECTURES=\"x86_64;arm64\"" }
41+
- {name: "iOS", os: "macOS-latest", cmake_extra: "-DCMAKE_TOOLCHAIN_FILE=cmake/ios.toolchain.cmake -DPLATFORM=OS64" }
42+
- {name: "iOS Simulator", os: "macOS-latest", cmake_extra: "-DCMAKE_TOOLCHAIN_FILE=cmake/ios.toolchain.cmake -DPLATFORM=SIMULATOR64COMBINED -G Xcode" }
43+
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Install certificates and provisioning profiles
48+
uses: ./.github/actions/install-apple-certs
49+
with:
50+
MACOS_CERTIFICATE_APP: ${{ secrets.PROD_MACOS_CERTIFICATE }}
51+
MACOS_CERTIFICATE_INST: ${{ secrets.PROD_MACOS_CERTIFICATE_INST }}
52+
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
53+
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
54+
55+
- name: Configure CMake
56+
env:
57+
APPLE_DEVELOPMENT_TEAM: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
58+
run: |
59+
cmake --version
60+
cmake -S . -B build \
61+
-DCMAKE_BUILD_TYPE=Release \
62+
-DCMAKE_INSTALL_PREFIX=${PWD}/install \
63+
-DCPACK_PACKAGE_DIRECTORY=${PWD}/package \
64+
-DLSL_FRAMEWORK=ON \
65+
-Dlslgitrevision=${{ github.sha }} \
66+
-Dlslgitbranch=${{ github.ref }} \
67+
${{ matrix.config.cmake_extra }} \
68+
${{ github.event.inputs.cmakeextra }}
69+
echo ${PWD}
70+
71+
- name: make
72+
run: cmake --build build --config Release -j
73+
74+
- name: make install
75+
run: cmake --build build --config Release --target install
76+
77+
- name: test install using examples
78+
if: matrix.config.name == 'macOS-latest'
79+
run: |
80+
# Test that the in-tree install was successful by building the examples
81+
cmake -S examples -B examples/build \
82+
-DLSL_INSTALL_ROOT=${PWD}/install \
83+
-DCMAKE_INSTALL_PREFIX=examples/build/install \
84+
-DLSL_COMFY_DEFAULTS=ON \
85+
${{ matrix.config.cmake_extra }} \
86+
${{ github.event.inputs.cmakeextra }}
87+
cmake --build examples/build --target install --config Release -j
88+
./examples/build/install/bin/HandleMetaData
89+
90+
- name: Codesign
91+
run: |
92+
if [[ "${{ matrix.config.name }}" == "macOS-latest" ]]; then
93+
codesign -vvv --force --deep --sign "$APPLE_CODE_SIGN_IDENTITY_APP" \
94+
--entitlements lsl.entitlements --options runtime \
95+
install/Frameworks/lsl.framework/Versions/A/lsl
96+
codesign -vvv --verify --deep --strict install/Frameworks/lsl.framework/Versions/A/lsl
97+
elif [[ "${{ matrix.config.name }}" == "iOS" || "${{ matrix.config.name }}" == "iOS Simulator" ]]; then
98+
codesign -vvv --force --deep --sign "$APPLE_CODE_SIGN_IDENTITY_APP" \
99+
install/Frameworks/lsl.framework/lsl
100+
codesign -vvv --verify --deep --strict install/Frameworks/lsl.framework/lsl
101+
fi
102+
codesign -vvv --force --deep --sign "$APPLE_CODE_SIGN_IDENTITY_APP" \
103+
--entitlements lsl.entitlements --options runtime \
104+
install/Frameworks/lsl.framework
105+
codesign -vvv --verify --deep --strict install/Frameworks/lsl.framework
106+
107+
# run internal tests
108+
- name: unit tests
109+
if: matrix.config.name == 'macOS-latest'
110+
run: |
111+
mkdir -p dumps
112+
install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
113+
install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
114+
timeout-minutes: 10
115+
116+
- name: Package and Notarize macOS Installer
117+
if: matrix.config.name == 'macOS-latest'
118+
env:
119+
APPLE_DEVELOPMENT_TEAM: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
120+
APPLE_NOTARIZE_USERNAME: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
121+
APPLE_NOTARIZE_PASSWORD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
122+
run: |
123+
# Get the version number from the framework's Info.plist
124+
LSL_VERSION=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" install/Frameworks/lsl.framework/Versions/A/Resources/Info.plist)
125+
echo "LSL_VERSION=$LSL_VERSION" >> $GITHUB_ENV
126+
echo "Debug: LSL_VERSION=$LSL_VERSION"
127+
128+
mkdir -p package
129+
productbuild --sign "$APPLE_CODE_SIGN_IDENTITY_INST" \
130+
--component install/Frameworks/lsl.framework \
131+
/Library/Frameworks package/liblsl-${LSL_VERSION}-Darwin-universal.pkg
132+
# Notarize the package
133+
xcrun notarytool submit package/liblsl-${LSL_VERSION}-Darwin-universal.pkg \
134+
--apple-id "$APPLE_NOTARIZE_USERNAME" \
135+
--password "$APPLE_NOTARIZE_PASSWORD" \
136+
--team-id "$APPLE_DEVELOPMENT_TEAM" \
137+
--wait
138+
# Staple the notarization ticket to the package
139+
xcrun stapler staple package/liblsl-${LSL_VERSION}-Darwin-universal.pkg
140+
141+
- name: upload dump
142+
if: failure()
143+
uses: actions/upload-artifact@v4
144+
with:
145+
name: dumps-${{ matrix.config.name }}
146+
path: dumps
147+
148+
- name: Zip LSL Framework
149+
run: |
150+
cd install/Frameworks
151+
zip -ry lsl.framework.zip lsl.framework
152+
cd ../..
153+
154+
- name: Upload macOS Package and Framework
155+
if: matrix.config.name == 'macOS-latest'
156+
uses: actions/upload-artifact@v4
157+
with:
158+
name: build-macOS-latest
159+
path: |
160+
package/*.pkg
161+
install/Frameworks/lsl.framework.zip
162+
# Note: the artifact will preserve the folder structure up to the common root, in this case all.
163+
164+
- name: Upload iOS Framework
165+
if: matrix.config.name == 'iOS'
166+
uses: actions/upload-artifact@v4
167+
with:
168+
name: build-iOS
169+
path: install/Frameworks/lsl.framework.zip
170+
# Note: the artifact drops the folder structure and only keeps the zip.
171+
172+
- name: Upload iOS Simulator Framework
173+
if: matrix.config.name == 'iOS Simulator'
174+
uses: actions/upload-artifact@v4
175+
with:
176+
name: build-iOS-Simulator
177+
path: install/Frameworks/lsl.framework.zip
178+
179+
xcframework_and_deploy:
180+
name: XCFramework and Deploy
181+
needs: build
182+
runs-on: macOS-latest
183+
steps:
184+
- uses: actions/checkout@v4
185+
- uses: actions/download-artifact@v4
186+
with:
187+
name: build-macOS-latest
188+
path: build-macOS-latest
189+
- uses: actions/download-artifact@v4
190+
with:
191+
name: build-iOS
192+
path: build-iOS
193+
- uses: actions/download-artifact@v4
194+
with:
195+
name: build-iOS-Simulator
196+
path: build-iOS-Simulator
197+
198+
- name: Unzip macOS Framework
199+
run: |
200+
unzip build-macOS-latest/install/Frameworks/lsl.framework.zip -d build-macOS-latest/Frameworks
201+
202+
- name: Unzip iOS Framework
203+
run: |
204+
unzip build-iOS/lsl.framework.zip -d build-iOS/Frameworks
205+
206+
- name: Unzip iOS Simulator Framework
207+
run: |
208+
unzip build-iOS-Simulator/lsl.framework.zip -d build-iOS-Simulator/Frameworks
209+
210+
- name: Install certificates and provisioning profiles
211+
uses: ./.github/actions/install-apple-certs
212+
with:
213+
MACOS_CERTIFICATE_APP: ${{ secrets.PROD_MACOS_CERTIFICATE }}
214+
MACOS_CERTIFICATE_INST: ${{ secrets.PROD_MACOS_CERTIFICATE_INST }}
215+
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
216+
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
217+
218+
- name: Create and Sign XCFramework
219+
run: |
220+
xcodebuild -create-xcframework \
221+
-framework build-macOS-latest/Frameworks/lsl.framework \
222+
-framework build-iOS/Frameworks/lsl.framework \
223+
-framework build-iOS-Simulator/Frameworks/lsl.framework \
224+
-output lsl.xcframework
225+
226+
codesign -vvv --force --deep --sign "$APPLE_CODE_SIGN_IDENTITY_APP" lsl.xcframework
227+
echo "✅ Verifying binary signatures in XCFramework..."
228+
codesign -vvv --verify --deep --strict lsl.xcframework
229+
230+
ditto -c -k --sequesterRsrc --keepParent lsl.xcframework lsl.xcframework.$LSL_VERSION.zip
231+
232+
- name: upload artifacts
233+
uses: actions/upload-artifact@v4
234+
with:
235+
name: mac-packages
236+
path: |
237+
lsl.xcframework.*.zip
238+
package/
239+
240+
- name: upload to release page
241+
if: github.event_name == 'release'
242+
env:
243+
TOKEN: "token ${{ secrets.GITHUB_TOKEN }}"
244+
TAG: ${{ github.event.release.tag_name }}
245+
UPLOAD_URL: ${{ github.event.release.upload_url }}
246+
run: |
247+
UPLOAD_URL=${UPLOAD_URL%\{*} # remove "{name,label}" suffix
248+
for pkg in lsl.xcframework.zip package/*.*; do
249+
NAME=$(basename $pkg)
250+
MIME=$(file --mime-type $pkg|cut -d ' ' -f2)
251+
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: $TOKEN" -H "Content-Type: $MIME" --data-binary @$pkg $UPLOAD_URL?name=$NAME
252+
done

.github/workflows/cppcmake.yml

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ name: C/C++ CI
22

33
on:
44
push:
5-
branches: ['*']
5+
branches:
6+
- main
7+
- dev
68
tags: ['*']
79
paths:
810
- '**'
@@ -39,18 +41,10 @@ jobs:
3941
- {name: "ubuntu-24.04", os: "ubuntu-24.04", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
4042
- {name: "windows-x64", os: "windows-latest", cmake_extra: "-T v142,host=x86"}
4143
- {name: "windows-32", os: "windows-latest", cmake_extra: "-T v142,host=x86 -A Win32"}
42-
- {name: "macOS-latest", os: "macOS-latest"}
43-
44-
# runs all steps in the container configured in config.docker or as subprocesses when empty
45-
container: ${{ matrix.config.docker }}
44+
4645
steps:
4746
- uses: actions/checkout@v4
48-
- name: set up build environment in container
49-
run: |
50-
set -x
51-
apt update
52-
apt install -y --no-install-recommends g++ git ninja-build file dpkg-dev lsb-release sudo curl cmake libpugixml-dev
53-
if: ${{ matrix.config.docker }}
47+
5448
- name: Configure CMake
5549
run: |
5650
if [[ "${{ matrix.config.name }}" = ubuntu-2* ]]; then
@@ -67,9 +61,13 @@ jobs:
6761
-Dlslgitbranch=${{ github.ref }} \
6862
${{ matrix.config.cmake_extra }} \
6963
${{ github.event.inputs.cmakeextra }}
70-
echo ${PWD}
64+
echo ${PWD}
65+
7166
- name: make
72-
run: cmake --build build --target install --config Release -j
67+
run: cmake --build build --config Release -j
68+
69+
- name: make install
70+
run: cmake --build build --config Release --target install
7371

7472
- name: test install using examples
7573
run: |
@@ -82,7 +80,7 @@ jobs:
8280
${{ github.event.inputs.cmakeextra }}
8381
cmake --build examples/build --target install --config Release -j
8482
./examples/build/install/bin/HandleMetaData
85-
83+
8684
- name: package
8785
run: |
8886
echo $GITHUB_REF
@@ -101,6 +99,7 @@ jobs:
10199
fi
102100
cmake -E remove_directory package/_CPack_Packages
103101
cp testing/lslcfgs/default.cfg .
102+
104103
- name: upload install dir
105104
uses: actions/upload-artifact@master
106105
with:
@@ -112,6 +111,7 @@ jobs:
112111
with:
113112
name: pkg-${{ matrix.config.name }}
114113
path: package
114+
115115
- name: print network config
116116
run: |
117117
which ifconfig && ifconfig
@@ -121,24 +121,26 @@ jobs:
121121
ip route
122122
ip -6 route
123123
fi
124-
125-
# run internal tests, ignore test failures on docker (missing IPv6 connectivity)
124+
125+
# run internal tests
126126
- name: unit tests
127127
run: |
128128
if [[ "${{ matrix.config.name }}" = ubuntu-2* ]]; then
129129
ulimit -c unlimited
130130
echo "$PWD/dumps/corefile-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
131131
fi
132132
mkdir -p dumps
133-
install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes || test ! -z "${{ matrix.config.docker }}"
133+
install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes
134134
install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
135135
timeout-minutes: 10
136+
136137
- name: upload dump
137138
if: failure()
138139
uses: actions/upload-artifact@master
139140
with:
140141
name: dumps-${{ matrix.config.name }}
141142
path: dumps
143+
142144
- name: upload to release page
143145
if: github.event_name == 'release'
144146
env:

0 commit comments

Comments
 (0)