@@ -20,28 +20,26 @@ parameters:
2020 displayName : Build Type
2121 type : string
2222 default : commit
23- values :
24- - release
25- - beta
26- - commit
23+ values : [commit, beta, release]
2724
2825 - name : targetOS
2926 displayName : Target OS
3027 type : string
3128 default : all
32- values :
33- - windows
34- - linux
35- - macos
36- - all
29+ values : [all, windows, linux, macos]
30+
31+ - name : versionTag
32+ displayName : Version Tag
33+ type : string
34+ default : ' v0.0.0'
3735
3836# ##########################################
3937# WINDOWS BUILD JOB #
4038# ##########################################
4139
4240jobs :
4341- job : Windows
44- timeoutInMinutes : 120
42+ timeoutInMinutes : 30
4543 cancelTimeoutInMinutes : 1
4644 condition : |
4745 or(
@@ -84,18 +82,19 @@ jobs:
8482 arguments : ' -arch=x64'
8583 modifyEnvironment : true
8684 displayName : ' Initialize VS Environment'
85+ condition : succeeded()
8786
8887 - script : |
8988 cd /d "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
9089 cmake --preset=$(cmake_preset) $(cmake_additional_param)
9190 displayName: 'Configure CMake'
92- condition: and( succeeded(), eq(variables['Agent.OS'], 'Windows_NT') )
91+ condition: succeeded()
9392
9493 - script : |
9594 cd /d "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
9695 cmake --build --preset=$(cmake_preset) --parallel 8
9796 displayName: 'Build'
98- condition: and( succeeded(), eq(variables['Agent.OS'], 'Windows_NT') )
97+ condition: succeeded()
9998
10099 - powershell : |
101100 Write-Host "=== Running windeployqt ==="
@@ -106,7 +105,7 @@ jobs:
106105 & "C:/Qt/6.8.3/msvc2022_64/bin/windeployqt.exe" --dir "$OUTPUT_DIR" --release "$APP_EXE"
107106 Write-Host "=== windeployqt complete ==="
108107 displayName: 'Deploy app'
109- condition: and( succeeded(), eq(variables['Agent.OS'], 'Windows_NT') )
108+ condition: succeeded()
110109
111110 - powershell : |
112111 echo "=== Copying resources==="
@@ -119,7 +118,7 @@ jobs:
119118 Write-Host "Robocopy exited with exit code:" $LASTEXITCODE
120119 if ($LASTEXITCODE -eq 1) { exit 0 } else { exit 1 }
121120 displayName: 'Copy resources'
122- condition: and( succeeded(), eq(variables['Agent.OS'], 'Windows_NT') )
121+ condition: succeeded()
123122
124123 - powershell : |
125124 $root = "$(Pipeline.Workspace)\Arduino-Source\build\$(cmake_preset)"
@@ -130,7 +129,7 @@ jobs:
130129 Compress-Archive -Path $temp -DestinationPath "$root\$name.zip"
131130 Remove-Item $temp -Recurse -Force
132131 displayName: 'Archive Windows Output folder'
133- condition: and( succeeded(), eq(variables['Agent.OS'], 'Windows_NT') )
132+ condition: succeeded()
134133
135134 - task : PublishBuildArtifacts@1
136135 displayName : ' Publish SerialPrograms'
@@ -144,7 +143,7 @@ jobs:
144143# ##########################################
145144
146145- job : Linux
147- timeoutInMinutes : 120
146+ timeoutInMinutes : 30
148147 cancelTimeoutInMinutes : 1
149148 condition : |
150149 or(
@@ -188,14 +187,14 @@ jobs:
188187 cd "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
189188 cmake --preset=$(cmake_preset) $(cmake_additional_param)
190189 displayName: 'Configure CMake'
191- condition: and( succeeded(), eq(variables['Agent.OS'], 'Linux') )
190+ condition: succeeded()
192191
193192 - script : |
194193 export PATH="/opt/Qt/6.10.0/gcc_64/lib/cmake:$PATH"
195194 cd "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
196195 cmake --build --preset=$(cmake_preset) --parallel 6
197196 displayName: 'Build'
198- condition: and( succeeded(), eq(variables['Agent.OS'], 'Linux') )
197+ condition: succeeded()
199198
200199 - script : |
201200 set -e
@@ -262,13 +261,13 @@ jobs:
262261 echo "https://github.com/$(Build.Repository.Name)/commit/$(Build.SourceVersion)" > $(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/Output/version.txt
263262 echo "=== AppImage build complete ==="
264263 displayName: 'Deploy AppImage'
265- condition: and( succeeded(), eq(variables['Agent.OS'], 'Linux') )
264+ condition: succeeded()
266265
267266 - script : |
268267 cd "$(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/Output"
269268 tar -zcvf ../SerialPrograms-Linux-$(compiler)-$(architecture).tar.gz *
270269 displayName: 'Archive Linux Output folder'
271- condition: and( succeeded(), eq(variables['Agent.OS'], 'Linux') )
270+ condition: succeeded()
272271
273272 - task : PublishBuildArtifacts@1
274273 displayName : ' Publish SerialPrograms'
@@ -282,7 +281,7 @@ jobs:
282281# ##########################################
283282
284283- job : MacOS
285- timeoutInMinutes : 120
284+ timeoutInMinutes : 30
286285 cancelTimeoutInMinutes : 1
287286 condition : |
288287 or(
@@ -339,14 +338,14 @@ jobs:
339338 cd "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
340339 cmake --preset=$(cmake_preset) $(cmake_additional_param)
341340 displayName: 'Configure CMake'
342- condition: and( succeeded(), eq(variables['Agent.OS'], 'Darwin') )
341+ condition: succeeded()
343342
344343 - script : |
345344 export PATH=$(macos_path)
346345 cd "$(Pipeline.Workspace)/Arduino-Source/SerialPrograms"
347346 cmake --build --preset=$(cmake_preset)
348347 displayName: 'Build'
349- condition: and( succeeded(), eq(variables['Agent.OS'], 'Darwin') )
348+ condition: succeeded()
350349
351350 - script : |
352351 set -e
@@ -367,69 +366,128 @@ jobs:
367366 QT_BIN="$BREW_PREFIX/opt/qt/bin"
368367 fi
369368
370- echo "BREW_PREFIX=$BREW_PREFIX"
371- echo "QT_BIN=$QT_BIN"
372-
373- echo "=== Running macdeployqt ==="
374- install_name_tool -add_rpath $BREW_PREFIX/lib $MACOS_DIR/SerialPrograms
375- otool -l $MACOS_DIR/SerialPrograms | grep -A2 LC_RPATH
369+ echo "=== Running Macdeployqt ==="
376370 "$QT_BIN/macdeployqt" "$APP_DIR" -no-strip -verbose=2
371+ displayName: 'Run macdeployqt'
372+ condition: succeeded()
377373
378- echo "=== Copying additional dependencies ==="
379- cp "$BREW_PREFIX/opt/gcc/lib/gcc/current/libgcc_s.1.1.dylib" "$FW_DIR" || true
380- cp "$BREW_PREFIX/opt/protobuf/lib/libutf8_validity.dylib" "$FW_DIR" || true
381- cp "$BREW_PREFIX/opt/webp/lib/libsharpyuv.0.dylib" "$FW_DIR" || true
382- cp "$BREW_PREFIX/opt/jpeg-xl/lib/libjxl_cms.0.11.dylib" "$FW_DIR" || true
383-
384- cp $BREW_PREFIX/opt/vtk/lib/libvtkCommonComputationalGeometry-*.dylib "$FW_DIR" 2>/dev/null || true
385- cp $BREW_PREFIX/opt/vtk/lib/libvtkFiltersVerdict-*.dylib "$FW_DIR" 2>/dev/null || true
386- cp $BREW_PREFIX/opt/vtk/lib/libvtkfmt-*.dylib "$FW_DIR" 2>/dev/null || true
387- cp $BREW_PREFIX/opt/vtk/lib/libvtkFiltersGeometry-*.dylib "$FW_DIR" 2>/dev/null || true
388- cp $BREW_PREFIX/opt/vtk/lib/libvtkFiltersCore-*.dylib "$FW_DIR" 2>/dev/null || true
389- cp $BREW_PREFIX/opt/vtk/lib/libvtkCommonCore-*.dylib "$FW_DIR" 2>/dev/null || true
390- cp $BREW_PREFIX/opt/vtk/lib/libvtkCommonSystem-*.dylib "$FW_DIR" 2>/dev/null || true
391-
392- echo "=== Fixing install IDs in copied libs ==="
374+ - bash : |
375+ set -euo pipefail
376+ echo "=== Fixing the app bundle ==="
377+ export PATH=$(macos_path)
378+ APP_DIR="$(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/SerialPrograms.app"
379+ MACOS_DIR="$APP_DIR/Contents/MacOS"
380+ FW_DIR="$APP_DIR/Contents/Frameworks"
381+ BIN="$MACOS_DIR/SerialPrograms"
382+
383+ echo "=== Determining Homebrew prefix ==="
384+ if [ $(architecture) = "X64" ]; then
385+ echo "Using Intel Homebrew and Qt..."
386+ BREW_PREFIX=$(/usr/local/bin/brew --prefix)
387+ else
388+ echo "Using ARM64 Homebrew and Qt..."
389+ BREW_PREFIX=$(/opt/homebrew/bin/brew --prefix)
390+ fi
391+
392+ echo "Using BREW_PREFIX=$BREW_PREFIX"
393+
394+ collect_deps() {
395+ otool -L "$1" \
396+ | awk 'NR>1 {print $1}' \
397+ | grep -E "^$BREW_PREFIX|^/usr/local|^/opt/homebrew" \
398+ | grep -v "@rpath" \
399+ | grep -v "@executable_path" \
400+ | grep -v "@loader_path" || true
401+ }
402+
403+ echo "=== Collecting and copying dependent dylibs ==="
404+ copied=1
405+ while [ $copied -eq 1 ]; do
406+ copied=0
407+
408+ for dep in $(collect_deps "$BIN"); do
409+ base=$(basename "$dep")
410+ if [ ! -f "$FW_DIR/$base" ]; then
411+ echo "Copying $base"
412+ cp "$dep" "$FW_DIR/$base"
413+ chmod 755 "$FW_DIR/$base"
414+ copied=1
415+ fi
416+ done
417+
418+ for dylib in "$FW_DIR"/*.dylib; do
419+ [ -f "$dylib" ] || continue
420+ for dep in $(collect_deps "$dylib"); do
421+ base=$(basename "$dep")
422+ if [ ! -f "$FW_DIR/$base" ]; then
423+ echo "Copying $base"
424+ cp "$dep" "$FW_DIR/$base"
425+ chmod 755 "$FW_DIR/$base"
426+ copied=1
427+ fi
428+ done
429+ done
430+ done
431+
432+ echo "=== Fixing install IDs ==="
393433 for dylib in "$FW_DIR"/*.dylib; do
394- [ -f "$dylib" ] || continue
395434 base=$(basename "$dylib")
396435 install_name_tool -id "@executable_path/../Frameworks/$base" "$dylib"
397436 done
398437
399- echo "=== Rewriting internal dylib references ==="
400- for dylib in "$FW_DIR"/*.dylib; do
401- [ -f "$dylib" ] || continue
402- for linked in $(otool -L "$dylib" | awk 'NR>1 {print $1}' | grep "$BREW_PREFIX" || true); do
403- base=$(basename "$linked")
438+ rewrite_refs() {
439+ local target="$1"
440+ for dep in $(otool -L "$target" | awk 'NR>1 {print $1}'); do
441+ base=$(basename "$dep")
404442 if [ -f "$FW_DIR/$base" ]; then
405- install_name_tool -change "$linked" "@executable_path/../Frameworks/$base" "$dylib"
443+ install_name_tool -change "$dep" \
444+ "@executable_path/../Frameworks/$base" \
445+ "$target"
406446 fi
407447 done
448+ }
449+
450+ echo "=== Rewriting dylib references ==="
451+ rewrite_refs "$BIN"
452+ for dylib in "$FW_DIR"/*.dylib; do
453+ rewrite_refs "$dylib"
408454 done
409455
410- echo "=== Rewriting main executable references ==="
411- for linked in $(otool -L "$MACOS_DIR/SerialPrograms" | awk 'NR>1 {print $1}' | grep "$BREW_PREFIX" || true); do
412- base=$(basename "$linked")
413- if [ -f "$FW_DIR/$base" ]; then
414- install_name_tool -change "$linked" "@executable_path/../Frameworks/$base" "$MACOS_DIR/SerialPrograms"
456+ echo "=== Cleaning rpaths ==="
457+ get_rpaths() {
458+ otool -l "$1" \
459+ | awk '
460+ $1 == "cmd" && $2 == "LC_RPATH" {found=1}
461+ found && $1 == "path" {print $2; found=0}
462+ '
463+ }
464+
465+ for rpath in $(get_rpaths "$BIN"); do
466+ if [ "$rpath" != "@executable_path/../Frameworks" ]; then
467+ echo "Removing rpath: $rpath"
468+ install_name_tool -delete_rpath "$rpath" "$BIN"
415469 fi
416470 done
417471
472+ if ! get_rpaths "$BIN" | grep -q "^@executable_path/../Frameworks$"; then
473+ install_name_tool -add_rpath "@executable_path/../Frameworks" "$BIN"
474+ fi
475+
418476 echo "=== Codesigning ==="
419477 codesign --force --deep --sign - "$APP_DIR"
420478 echo "Deployment complete for $(architecture)"
421479
422480 echo "=== Copying app bundle to the output directory ==="
423481 rsync -a --delete "$(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/SerialPrograms.app" "$(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/Output/"
424482 echo "https://github.com/$(Build.Repository.Name)/commit/$(Build.SourceVersion)" > $(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/Output/version.txt
425- displayName: 'Deploy app'
426- condition: and( succeeded(), eq(variables['Agent.OS'], 'Darwin') )
483+ displayName: "Fix macOS app bundle"
484+ condition: succeeded()
427485
428486 - script : |
429487 cd "$(Pipeline.Workspace)/Arduino-Source/build/$(cmake_preset)/Output"
430488 tar -zcvf ../SerialPrograms-MacOS-$(compiler)-$(architecture).tar.gz *
431489 displayName: 'Archive MacOS Output folder'
432- condition: and( succeeded(), eq(variables['Agent.OS'], 'Darwin') )
490+ condition: succeeded()
433491
434492 - task : PublishBuildArtifacts@1
435493 displayName : ' Publish SerialPrograms'
0 commit comments