Skip to content

Commit c8c6a52

Browse files
committed
Try to replace hard-coded dep copy for app bundle
1 parent 03be7b7 commit c8c6a52

File tree

2 files changed

+129
-62
lines changed

2 files changed

+129
-62
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ if(WIN32 AND QT_DEPLOY_FILES)
119119
REQUIRED
120120
)
121121
else()
122-
find_package(Qt${QT_MAJOR} COMPONENTS Widgets SerialPort Multimedia MultimediaWidgets REQUIRED)
122+
if (CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
123+
find_package(Qt${QT_MAJOR} COMPONENTS Widgets SerialPort Multimedia MultimediaWidgets DBus REQUIRED)
124+
else()
125+
find_package(Qt${QT_MAJOR} COMPONENTS Widgets SerialPort Multimedia MultimediaWidgets REQUIRED)
126+
endif()
123127
endif()
124128

125129
# disable deprecated Qt APIs
@@ -178,7 +182,12 @@ endif()
178182
# Function to apply common properties to both library and executable targets
179183
function(apply_common_target_properties target_name)
180184
set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX)
181-
target_link_libraries(${target_name} PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::SerialPort Qt${QT_MAJOR}::Multimedia Qt${QT_MAJOR}::MultimediaWidgets)
185+
if (CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
186+
target_link_libraries(${target_name} PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::SerialPort Qt${QT_MAJOR}::Multimedia Qt${QT_MAJOR}::MultimediaWidgets Qt${QT_MAJOR}::DBus)
187+
else ()
188+
target_link_libraries(${target_name} PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::SerialPort Qt${QT_MAJOR}::Multimedia Qt${QT_MAJOR}::MultimediaWidgets)
189+
endif()
190+
182191
target_link_libraries(${target_name} PRIVATE Threads::Threads)
183192

184193
#add defines
@@ -491,7 +500,7 @@ else() # macOS and Linux
491500
target_compile_options(SerialProgramsLib PRIVATE -Wall -Wextra -Wpedantic -Werror -fno-strict-aliasing)
492501
endif()
493502

494-
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
503+
if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
495504
# Arm CPU
496505
# Run-time ISA dispatching
497506
message(STATUS "Setting compile definitions for ARM64 CPU")

SerialPrograms/azure-pipelines.yml

Lines changed: 117 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4240
jobs:
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

Comments
 (0)