-
Notifications
You must be signed in to change notification settings - Fork 61
454 lines (393 loc) · 17.6 KB
/
_MacOS.yml
File metadata and controls
454 lines (393 loc) · 17.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
name: _MacOs
on:
workflow_call:
secrets:
APPLE_ID:
required: true
APPLE_TEAM_ID:
required: true
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD:
required: true
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64:
required: true
APPLE_KEYCHAIN_PASSWORD:
required: true
APPLE_APPLICATION_SPECIFIC_PASSWORD:
required: true
jobs:
macos_arm64_dmg:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install Rosetta
run: |
sudo softwareupdate --install-rosetta --agree-to-license
- name: Set the environment for macOS 11 compatibility # 10.13 is a minimum, 10.9 does not work.
run: |
echo "MACOSX_DEPLOYMENT_TARGET=11" >> $GITHUB_ENV
echo "CFLAGS=-mmacosx-version-min=11" >> $GITHUB_ENV
echo "LDFLAGS=-mmacosx-version-min=11" >> $GITHUB_ENV
- name: Download all artifacts
uses: actions/download-artifact@v6
with:
name: macos-latest-wheels
path: wheels
- name: Install dependencies
run: |
pip install "setuptools<80"
pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/psutil-5.9.6-cp312-abi3-macosx_10_9_universal2.whl
pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/Pillow-10.1.0-cp312-cp312-macosx_11_0_universal2.whl
pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl
pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/contourpy-1.2.0-cp312-cp312-macosx_11_0_universal2.whl
pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_universal2.whl
pip install numpy==2.2.6
pip install h5py
pip install cycler==0.12.1
pip install fonttools==4.45.1
pip install packaging==23.2
pip install pyparsing==3.1.1
pip install python_dateutil==2.8.2
pip install matplotlib==3.10.5
pip install hdf5plugin
pip install PySide6==6.7.3
pip install lxml==4.9.3
pip install fisx
pip install silx==2.2.2
pip install fabio
pip install PyOpenGL
pip install ipython
pip install qtconsole==5.6.1
pip install PyInstaller==6.15.0
pip install Cython
pip install wheel
pip install wheels/*cp312*.whl
pip install git+https://github.com/vasole/bcflight.git
pip install ipywidgets
- name: Build the application for arm64
run: |
arch -arm64 python build-pyinstaller_github.py
ls dist
find dist/ -type f -perm +111 | while read -r file; do
version=$(otool -l "$file" 2>/dev/null | awk '/LC_VERSION_MIN_MACOSX/ {show=1} show && /version / {print $2; show=0}' | head -n 1)
if [ -n "$version" ]; then
echo "$version <- $file"
fi
done | sort
- name: Set app name
run: echo "APP_NAME=$(basename dist/*.app)" >> $GITHUB_ENV
- name: Test the app
run: |
set -e
arch -arm64 "dist/$APP_NAME/Contents/MacOS/PyMcaMain" --test
- name: Upload artifacts
uses: actions/upload-artifact@v5
with:
name: macos-arm64-dmg
path: dist/*.dmg
retention-days: 1
macos_x86_64_dmg:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install Rosetta
run: |
sudo softwareupdate --install-rosetta --agree-to-license
- name: Set environment for 11 compatibility #10.13 is a minimum - setting 10.9 do not actually work
run: |
echo "MACOSX_DEPLOYMENT_TARGET=11" >> $GITHUB_ENV
echo "CFLAGS=-mmacosx-version-min=11" >> $GITHUB_ENV
echo "LDFLAGS=-mmacosx-version-min=11" >> $GITHUB_ENV
# Remove arm64 from the Python interpreter to force x86_64 usage.
- name: Setup macOS x86_64 Python
run: |
arch -x86_64 python -m venv venv-x86_64
lipo venv-x86_64/bin/python -remove arm64 -output venv-x86_64/bin/python_x86
sudo mv venv-x86_64/bin/python_x86 venv-x86_64/bin/python
chmod +x venv-x86_64/bin/python
file venv-x86_64/bin/python
source venv-x86_64/bin/activate
- name: Download all artifacts
uses: actions/download-artifact@v6
with:
name: macos-latest-wheels
path: wheels
- name: Install dependencies
run: |
source venv-x86_64/bin/activate
arch -x86_64 pip install "setuptools<81"
arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/psutil-5.9.6-cp312-abi3-macosx_10_9_universal2.whl
arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/Pillow-10.1.0-cp312-cp312-macosx_11_0_universal2.whl
arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl
arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/contourpy-1.2.0-cp312-cp312-macosx_11_0_universal2.whl
arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_universal2.whl
arch -x86_64 pip install numpy==2.2.6
arch -x86_64 pip install h5py
arch -x86_64 pip install cycler==0.12.1
arch -x86_64 pip install fonttools==4.45.1
arch -x86_64 pip install packaging==23.2
arch -x86_64 pip install pyparsing==3.1.1
arch -x86_64 pip install python_dateutil==2.8.2
arch -x86_64 pip install matplotlib==3.10.5
arch -x86_64 pip install hdf5plugin
arch -x86_64 pip install PySide6==6.7.3
arch -x86_64 pip install lxml==4.9.3
arch -x86_64 pip install fisx
arch -x86_64 pip install silx==2.2.2
arch -x86_64 pip install fabio
arch -x86_64 pip install PyOpenGL
arch -x86_64 pip install ipython
arch -x86_64 pip install qtconsole==5.6.1
arch -x86_64 pip install PyInstaller==6.15.0
arch -x86_64 pip install Cython
arch -x86_64 pip install wheel
arch -x86_64 pip install wheels/*cp312*.whl
arch -x86_64 pip install git+https://github.com/vasole/bcflight.git
arch -x86_64 pip install ipywidgets
# arch -x86_64 pip install PySide6==6.6.0
# arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/numpy-1.26.2-cp312-cp312-macosx_10_9_universal2.whl
# arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/h5py-3.10.0-cp312-cp312-macosx_11_0_universal2.whl
# arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/matplotlib-3.8.2-cp312-cp312-macosx_11_0_universal2.whl
# arch -x86_64 pip install --no-cache --trusted-host www.silx.org http://www.silx.org/pub/wheelhouse/universal2/fabio-2023.10.0-cp312-cp312-macosx_10_9_universal2.whl
- name: Build the application for x86_64
run: |
source venv-x86_64/bin/activate
arch -x86_64 python build-pyinstaller_github.py
ls dist
find dist/ -type f -perm +111 | while read -r file; do
version=$(otool -l "$file" 2>/dev/null | awk '/LC_VERSION_MIN_MACOSX/ {show=1} show && /version / {print $2; show=0}' | head -n 1)
if [ -n "$version" ]; then
echo "$version <- $file"
fi
done | sort
- name: Set app name
run: echo "APP_NAME=$(basename dist/*.app)" >> $GITHUB_ENV
- name: Test the app
run: |
set -e
arch -x86_64 "dist/$APP_NAME/Contents/MacOS/PyMcaMain" --test
- name: Upload artifacts
uses: actions/upload-artifact@v5
with:
name: macos-x86_64-dmg
path: dist/*.dmg
retention-days: 1
macos_universal2_dmg:
runs-on: macos-latest
needs:
- macos_arm64_dmg
- macos_x86_64_dmg
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install Rosetta
run: |
sudo softwareupdate --install-rosetta --agree-to-license
- name: Download the arm64 artifact
uses: actions/download-artifact@v6
with:
name: macos-arm64-dmg
path: dist/tmp/arm64
- name: Download the x86_64 artifact
uses: actions/download-artifact@v6
with:
name: macos-x86_64-dmg
path: dist/tmp/x86_64
- name: Create output directories
run: |
mkdir -p dist/arm64 dist/x86_64
- name: Attach the arm64 DMG and copy the app
run: |
ARM_DMG=$(find dist/tmp/arm64 -name "*.dmg" | head -n 1)
hdiutil attach "$ARM_DMG" -mountpoint /Volumes/arm64
cp -R /Volumes/arm64/* dist/arm64/
hdiutil detach /Volumes/arm64
- name: Attach the x86_64 DMG and copy the app
run: |
X86_DMG=$(find dist/tmp/x86_64 -name "*.dmg" | head -n 1)
hdiutil attach "$X86_DMG" -mountpoint /Volumes/x86_64
cp -R /Volumes/x86_64/* dist/x86_64
hdiutil detach /Volumes/x86_64
- name: Set the app name variable
run: |
APP_NAME=$(find dist/arm64 -maxdepth 1 -name '*.app' | head -n 1 | xargs -n 1 basename)
echo "APP_NAME=$APP_NAME" >> $GITHUB_ENV
- name: Merge into universal2 app
run: |
echo "Merging universal2 .app: $APP_NAME"
ARM64_APP="dist/arm64/$APP_NAME"
X86_64_APP="dist/x86_64/$APP_NAME"
UNIVERSAL2_APP="dist/universal2/$APP_NAME"
# Copy arm64 app as base
mkdir -p dist/universal2
cp -R "$ARM64_APP" "$UNIVERSAL2_APP"
echo "Merging executables in Contents/MacOS..."
for exe in "$ARM64_APP/Contents/MacOS/"*; do
exe_name=$(basename "$exe")
echo " -> $exe_name"
lipo -create \
"$ARM64_APP/Contents/MacOS/$exe_name" \
"$X86_64_APP/Contents/MacOS/$exe_name" \
-output "$UNIVERSAL2_APP/Contents/MacOS/$exe_name"
done
# Extract all architectures as sorted strings.
get_archs() {
echo "$1" | grep -oE 'arm64|x86_64' | sort | tr '\n' ' '
}
# Check if arch list1 contains all archs in list2.
contains_all_archs() {
local container=($1)
local contained=($2)
for arch in "${contained[@]}"; do
local found=0
for c in "${container[@]}"; do
if [ "$arch" = "$c" ]; then
found=1
break
fi
done
if [ $found -eq 0 ]; then
return 1
fi
done
return 0
}
echo "Merging Mach-O (.so, .dylib, etc.) files in Frameworks and Resources..."
for section in Frameworks Resources; do
find "$ARM64_APP/Contents/$section" -type f | while read -r arm64_file; do
if ! file "$arm64_file" | grep -q 'Mach-O'; then
continue
fi
rel_path="${arm64_file#$ARM64_APP/}"
x86_64_file="$X86_64_APP/$rel_path"
out_file="$UNIVERSAL2_APP/$rel_path"
if [ -f "$x86_64_file" ]; then
arch_arm64=$(lipo -info "$arm64_file" 2>&1)
arch_x86_64=$(lipo -info "$x86_64_file" 2>&1)
archs_arm64=$(get_archs "$arch_arm64")
archs_x86_64=$(get_archs "$arch_x86_64")
is_arm64_universal2=false
is_x86_64_universal2=false
if [[ "$archs_arm64" == *"arm64"* && "$archs_arm64" == *"x86_64"* ]]; then
is_arm64_universal2=true
fi
if [[ "$archs_x86_64" == *"arm64"* && "$archs_x86_64" == *"x86_64"* ]]; then
is_x86_64_universal2=true
fi
if [ "$is_arm64_universal2" = true ] && [ "$is_x86_64_universal2" = false ]; then
echo " -> $rel_path"
echo " arm64_file is universal2; copying arm64_file."
cp "$arm64_file" "$out_file"
elif [ "$is_x86_64_universal2" = true ] && [ "$is_arm64_universal2" = false ]; then
echo " -> $rel_path"
echo " x86_64_file is universal2; copying x86_64_file."
cp "$x86_64_file" "$out_file"
else
# If both universal2 or both not universal2, check if arch sets match exactly
if contains_all_archs "$archs_arm64" "$archs_x86_64" && contains_all_archs "$archs_x86_64" "$archs_arm64"; then
if [ "$is_arm64_universal2" = false ]; then
echo " -> $rel_path"
echo " Archs arm64_file: $arch_arm64"
echo " Archs x86_64_file: $arch_x86_64"
echo " Both files have identical architectures. Copying x86_64 file."
cp "$x86_64_file" "$out_file"
fi
else
lipo -create "$arm64_file" "$x86_64_file" -output "$out_file"
fi
fi
else
echo " Warning: x86_64 file not found for $rel_path. Skipping."
fi
done
done
echo "Universal2 app built at $UNIVERSAL2_APP"
- name: Make main binary executable
run: chmod +x dist/universal2/$APP_NAME/Contents/MacOS/PyMcaMain
- name: Test the app for both architectures
run: |
set -e
arch -arm64 "dist/universal2/$APP_NAME/Contents/MacOS/PyMcaMain" --test
arch -x86_64 "dist/universal2/$APP_NAME/Contents/MacOS/PyMcaMain" --test
- name: Upload universal .app artifact
uses: actions/upload-artifact@v5
with:
name: ${{ env.APP_NAME }}-universal-app
path: dist/universal2/*
retention-days: 1
- name: Set app base name (without .app)
run: |
APP_BASE_NAME="${APP_NAME%.app}"
echo "APP_BASE_NAME=$APP_BASE_NAME" >> $GITHUB_ENV
- name: Sign, create, and staple the universal2 DMG
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CERTIFICATE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD }}
CERTIFICATE_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APPLICATION_SPECIFIC_PASSWORD }}
run: |
# Copy the application to location expected by the packaging scripts.
mkdir -p package/pyinstaller/dist
cp -a dist/universal2/$APP_NAME package/pyinstaller/dist/PyMca.app
cd package/pyinstaller
# Remove unnecessary packages.
rm -fr dist/PyMca.app/Contents/Frameworks/pkg_resources/tests
mkdir -p artifacts
./codesign.sh
./create-dmg.sh
./notarize.sh
VERSION=${APP_NAME#PyMca}; VERSION=${VERSION%.app}
mv artifacts/PyMca.dmg ../../dist/PyMca${VERSION}.dmg
cd ../..
rm -fr package/pyinstaller/dist
rm -fr package/pyinstaller/artifacts
- name: Mount the DMG
run: |
set -e
DMG_NAME="${{ env.APP_BASE_NAME }}.dmg"
MOUNT_POINT="/Volumes/${{ env.APP_BASE_NAME }}"
echo "Mounting DMG $DMG_NAME at $MOUNT_POINT"
hdiutil attach "dist/$DMG_NAME" -mountpoint "$MOUNT_POINT"
- name: Copy .app to /Applications
run: |
set -e
APP_PATH="/Volumes/${{ env.APP_BASE_NAME }}/PyMca.app"
sudo cp -R "$APP_PATH" /Applications/
- name: Make main binary executable
run: chmod +x /Applications/PyMca.app/Contents/MacOS/PyMcaMain
- name: Run the x86_64 tests
run: |
set -e
arch -x86_64 /Applications/PyMca.app/Contents/MacOS/PyMcaMain --test
- name: Run the arm64 tests
run: |
set -e
arch -arm64 /Applications/PyMca.app/Contents/MacOS/PyMcaMain --test
- name: Unmount the DMG
if: always()
run: |
set -e
MOUNT_POINT="/Volumes/${{ env.APP_BASE_NAME }}"
echo "Unmounting DMG at $MOUNT_POINT"
hdiutil detach "$MOUNT_POINT"
- name: Upload the universal2 DMG artifact
uses: actions/upload-artifact@v5
with:
name: macos-universal2-dmg
path: dist/*.dmg
retention-days: 1