Skip to content

Commit af1a9ad

Browse files
committed
drop macos intel build, add deb, exe and dmg
1 parent 4a6ed94 commit af1a9ad

2 files changed

Lines changed: 219 additions & 67 deletions

File tree

.github/workflows/build.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ jobs:
2323
include:
2424
- os: ubuntu-22.04
2525
label: linux-x86_64
26-
- os: macos-13
27-
label: macos-x86_64
26+
# macos-13 (Intel) is in GitHub's deprecation window — jobs sit in
27+
# the queue for hours. Apple Silicon only for now; x86_64 Mac users
28+
# build from source.
2829
- os: macos-14
2930
label: macos-arm64
3031
- os: windows-2022
@@ -72,9 +73,9 @@ jobs:
7273
sudo apt-get install -y --no-install-recommends librealsense2-dev librealsense2-utils
7374
7475
# -------------------------------------------------------------------
75-
# macOS (both x86_64 and arm64): Homebrew handles everything.
76-
# librealsense's arm64 brew bottle has been bumpy historically; if it
77-
# breaks here, the most likely cause is upstream brew formula state.
76+
# macOS (Apple Silicon, macos-14). Homebrew handles everything.
77+
# If librealsense's brew formula breaks here, the most likely cause
78+
# is upstream brew formula state.
7879
# -------------------------------------------------------------------
7980
- name: Install macOS dependencies
8081
if: runner.os == 'macOS'

.github/workflows/release.yml

Lines changed: 213 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ jobs:
1919
include:
2020
- os: ubuntu-22.04
2121
label: linux-x86_64
22-
- os: macos-13
23-
label: macos-x86_64
22+
# macos-13 (Intel) dropped — GitHub runner queue is unreliable.
2423
- os: macos-14
2524
label: macos-arm64
2625
- os: windows-2022
@@ -128,104 +127,256 @@ jobs:
128127
run: cmake --build build --config Release --parallel
129128

130129
# -----------------------------------------------------------------
131-
# Package: stage the binary plus its RealSense / OpenCV runtime
132-
# libraries into dist/, then tar/zip it.
130+
# Package: produce a platform-native installer.
131+
# Linux -> .deb (dpkg-deb, depends on system libgtk-3/libgl/libusb)
132+
# macOS -> .dmg containing a self-contained .app bundle
133+
# Windows -> NSIS .exe installer (Start menu shortcut, Add/Remove entry)
133134
# -----------------------------------------------------------------
134-
- name: Package (Linux)
135+
- name: Derive version from tag
136+
id: ver
137+
shell: bash
138+
run: |
139+
# ref_name on a tag push is "v1.2.3" — strip leading 'v' to get "1.2.3".
140+
VERSION="${GITHUB_REF_NAME#v}"
141+
# Releases triggered via workflow_dispatch / branch push won't have a v-tag;
142+
# use a 0.0.0+sha fallback so the packaging step still works.
143+
if [[ "$VERSION" == "$GITHUB_REF_NAME" && ! "$GITHUB_REF_NAME" =~ ^[0-9] ]]; then
144+
VERSION="0.0.0-${GITHUB_SHA::7}"
145+
fi
146+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
147+
echo "Resolved version: $VERSION"
148+
149+
- name: Package (Linux .deb)
135150
if: runner.os == 'Linux'
151+
env:
152+
VERSION: ${{ steps.ver.outputs.version }}
136153
run: |
137154
set -euxo pipefail
138-
STAGE="dist/ir-tracking-app-${{ matrix.label }}"
139-
mkdir -p "$STAGE/lib"
140-
cp build/ir-tracking-app "$STAGE/"
141-
142-
# Bundle every linked librealsense / libopencv .so. ldd reports a path
143-
# like "libfoo.so => /usr/lib/x86_64-linux-gnu/libfoo.so.1 (0x...)"
155+
PKG="ir-tracking-app"
156+
STAGE="$RUNNER_TEMP/deb-staging"
157+
rm -rf "$STAGE"
158+
mkdir -p "$STAGE/DEBIAN" "$STAGE/usr/bin" "$STAGE/usr/lib/$PKG" \
159+
"$STAGE/usr/share/applications" "$STAGE/usr/share/icons/hicolor/256x256/apps"
160+
161+
# Binary + bundled libs under /usr/lib/<pkg>/ with $ORIGIN rpath.
162+
cp build/ir-tracking-app "$STAGE/usr/lib/$PKG/"
144163
ldd build/ir-tracking-app \
145164
| awk '/(librealsense|libopencv|libtbb|libusb-1\.0)/ { print $3 }' \
146-
| grep -v '^$' \
147-
| sort -u \
148-
| while read -r lib; do
149-
cp -L "$lib" "$STAGE/lib/"
150-
done
165+
| grep -v '^$' | sort -u \
166+
| while read -r lib; do cp -L "$lib" "$STAGE/usr/lib/$PKG/"; done
167+
patchelf --set-rpath '$ORIGIN' "$STAGE/usr/lib/$PKG/ir-tracking-app"
151168
152-
patchelf --set-rpath '$ORIGIN/lib' "$STAGE/ir-tracking-app"
153-
154-
# Tiny launcher so users can double-click without worrying about
155-
# LD_LIBRARY_PATH or working directory.
156-
cat > "$STAGE/run.sh" <<'SH'
169+
# Launcher shim on PATH.
170+
cat > "$STAGE/usr/bin/$PKG" <<SH
157171
#!/usr/bin/env bash
158-
cd "$(dirname "$0")"
159-
exec ./ir-tracking-app "$@"
172+
exec /usr/lib/$PKG/ir-tracking-app "\$@"
160173
SH
161-
chmod +x "$STAGE/run.sh"
162-
163-
tar -czf "ir-tracking-app-${{ matrix.label }}.tar.gz" -C dist "ir-tracking-app-${{ matrix.label }}"
164-
ls -lh "ir-tracking-app-${{ matrix.label }}.tar.gz"
165-
166-
- name: Package (macOS)
174+
chmod 0755 "$STAGE/usr/bin/$PKG"
175+
176+
# Desktop entry so the app shows in app launchers.
177+
cat > "$STAGE/usr/share/applications/$PKG.desktop" <<EOF
178+
[Desktop Entry]
179+
Type=Application
180+
Name=IR Tracking App
181+
Comment=Intel RealSense IR retro-reflective marker tracking
182+
Exec=$PKG
183+
Icon=$PKG
184+
Categories=Science;Graphics;
185+
Terminal=false
186+
EOF
187+
188+
# dpkg control metadata. Depends covers the runtime system libs we
189+
# rely on (GTK for nfd, OpenGL, libusb for RealSense USB).
190+
INSTALLED_KB=$(du -sk "$STAGE" --exclude=DEBIAN | cut -f1)
191+
cat > "$STAGE/DEBIAN/control" <<EOF
192+
Package: $PKG
193+
Version: $VERSION
194+
Section: graphics
195+
Priority: optional
196+
Architecture: amd64
197+
Maintainer: Tianyu Song <tianyu@medivis.com>
198+
Homepage: https://github.com/stytim/RealSense-ToolTracker
199+
Depends: libgtk-3-0, libgl1, libusb-1.0-0
200+
Installed-Size: $INSTALLED_KB
201+
Description: Intel RealSense IR retro-reflective marker tool tracker
202+
Tracks passive IR sphere markers from an Intel RealSense camera and
203+
publishes the tool pose over UDP. See the GitHub README for usage.
204+
EOF
205+
206+
OUT="${PKG}_${VERSION}_amd64.deb"
207+
dpkg-deb --build --root-owner-group "$STAGE" "$OUT"
208+
ls -lh "$OUT"
209+
dpkg-deb -I "$OUT"
210+
211+
- name: Package (macOS .dmg)
167212
if: runner.os == 'macOS'
213+
env:
214+
VERSION: ${{ steps.ver.outputs.version }}
168215
run: |
169216
set -euxo pipefail
170-
STAGE="dist/ir-tracking-app-${{ matrix.label }}"
171-
mkdir -p "$STAGE"
172-
cp build/ir-tracking-app "$STAGE/"
173-
174-
# dylibbundler walks the binary's load commands recursively, copies
175-
# every non-system dylib into dist/libs and rewrites install names to
176-
# @executable_path/libs/. Avoids the per-dylib otool dance.
217+
APP_NAME="IR Tracking App"
218+
APP_DIR="$RUNNER_TEMP/$APP_NAME.app"
219+
rm -rf "$APP_DIR"
220+
mkdir -p "$APP_DIR/Contents/MacOS" \
221+
"$APP_DIR/Contents/Resources" \
222+
"$APP_DIR/Contents/Frameworks"
223+
224+
cp build/ir-tracking-app "$APP_DIR/Contents/MacOS/"
225+
cp resources/app_icon.icns "$APP_DIR/Contents/Resources/app_icon.icns"
226+
227+
# Bundle dylibs into Contents/Frameworks/, with install names rewritten
228+
# to @executable_path/../Frameworks/ so the .app is self-contained.
177229
dylibbundler -od -b \
178-
-x "$STAGE/ir-tracking-app" \
179-
-d "$STAGE/libs" \
180-
-p "@executable_path/libs/" \
230+
-x "$APP_DIR/Contents/MacOS/ir-tracking-app" \
231+
-d "$APP_DIR/Contents/Frameworks" \
232+
-p "@executable_path/../Frameworks/" \
181233
|| true
182234
183-
# Cosmetic launcher mirrors the Linux one.
184-
cat > "$STAGE/run.sh" <<'SH'
185-
#!/usr/bin/env bash
186-
cd "$(dirname "$0")"
187-
exec ./ir-tracking-app "$@"
188-
SH
189-
chmod +x "$STAGE/run.sh"
190-
191-
tar -czf "ir-tracking-app-${{ matrix.label }}.tar.gz" -C dist "ir-tracking-app-${{ matrix.label }}"
192-
ls -lh "ir-tracking-app-${{ matrix.label }}.tar.gz"
193-
194-
- name: Package (Windows)
235+
cat > "$APP_DIR/Contents/Info.plist" <<EOF
236+
<?xml version="1.0" encoding="UTF-8"?>
237+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
238+
<plist version="1.0">
239+
<dict>
240+
<key>CFBundleExecutable</key><string>ir-tracking-app</string>
241+
<key>CFBundleIdentifier</key><string>com.medivis.ir-tracking-app</string>
242+
<key>CFBundleName</key><string>$APP_NAME</string>
243+
<key>CFBundleDisplayName</key><string>$APP_NAME</string>
244+
<key>CFBundleVersion</key><string>$VERSION</string>
245+
<key>CFBundleShortVersionString</key><string>$VERSION</string>
246+
<key>CFBundlePackageType</key><string>APPL</string>
247+
<key>CFBundleIconFile</key><string>app_icon.icns</string>
248+
<key>LSMinimumSystemVersion</key><string>11.0</string>
249+
<key>NSHighResolutionCapable</key><true/>
250+
<key>NSCameraUsageDescription</key><string>Used to display the IR camera feed for tool tracking.</string>
251+
</dict>
252+
</plist>
253+
EOF
254+
255+
# Compose the DMG. UDZO = zlib-compressed read-only.
256+
DMG_NAME="ir-tracking-app-${VERSION}-${{ matrix.label }}.dmg"
257+
DMG_STAGING="$RUNNER_TEMP/dmg-staging"
258+
rm -rf "$DMG_STAGING"
259+
mkdir -p "$DMG_STAGING"
260+
cp -R "$APP_DIR" "$DMG_STAGING/"
261+
# Drag-to-/Applications affordance — a symlink the user can drop on.
262+
ln -s /Applications "$DMG_STAGING/Applications"
263+
264+
hdiutil create \
265+
-volname "$APP_NAME $VERSION" \
266+
-srcfolder "$DMG_STAGING" \
267+
-ov \
268+
-format UDZO \
269+
"$DMG_NAME"
270+
ls -lh "$DMG_NAME"
271+
272+
- name: Package (Windows .exe installer)
195273
if: runner.os == 'Windows'
196274
shell: pwsh
275+
env:
276+
VERSION: ${{ steps.ver.outputs.version }}
197277
run: |
198278
$ErrorActionPreference = 'Stop'
199-
$stage = "dist\ir-tracking-app-${{ matrix.label }}"
279+
280+
# Stage every file that needs to end up in C:\Program Files\<App>\
281+
$stage = "$env:RUNNER_TEMP\nsis-payload"
282+
if (Test-Path $stage) { Remove-Item -Recurse -Force $stage }
200283
New-Item -ItemType Directory -Force -Path $stage | Out-Null
201284
202-
# The CMake build output landed under build\Release\.
203285
$exe = "build\Release\ir-tracking-app.exe"
204-
if (-not (Test-Path $exe)) { $exe = "build\ir-tracking-app.exe" } # if generator differs
286+
if (-not (Test-Path $exe)) { $exe = "build\ir-tracking-app.exe" }
205287
Copy-Item $exe -Destination $stage
206288
207-
# RealSense runtime DLL.
208289
Copy-Item "C:\Program Files (x86)\Intel RealSense SDK 2.0\bin\x64\realsense2.dll" -Destination $stage
209-
210-
# OpenCV runtime DLL(s) — chocolatey 4.10 ships the 'world' variant.
211290
$opencvBin = Join-Path $env:OpenCV_DIR "x64\vc16\bin"
212291
Get-ChildItem -Path $opencvBin -Filter "opencv_world*.dll" `
213292
| Where-Object { $_.Name -notmatch "d\.dll$" } `
214293
| Copy-Item -Destination $stage
215294
216-
Compress-Archive -Path "$stage\*" -DestinationPath "ir-tracking-app-${{ matrix.label }}.zip" -Force
217-
Get-Item "ir-tracking-app-${{ matrix.label }}.zip" | Format-List Length, Name
295+
# NSIS comes preinstalled on windows-2022 runners under C:\Program Files (x86)\NSIS.
296+
$makensis = "C:\Program Files (x86)\NSIS\makensis.exe"
297+
if (-not (Test-Path $makensis)) {
298+
choco install nsis -y --no-progress
299+
}
300+
if (-not (Test-Path $makensis)) {
301+
throw "NSIS (makensis.exe) not found after install attempt."
302+
}
303+
304+
$version = $env:VERSION
305+
$outFile = "ir-tracking-app-$version-${{ matrix.label }}-setup.exe"
306+
$nsiPath = "$env:RUNNER_TEMP\installer.nsi"
307+
$stageNsi = $stage.Replace('\','\\')
308+
309+
# NSIS script — install to Program Files\IR Tracking App, Start Menu
310+
# shortcut + uninstaller + Add/Remove Programs entry.
311+
$nsi = @"
312+
!define APPNAME "IR Tracking App"
313+
!define APPID "ir-tracking-app"
314+
!define VERSION "$version"
315+
!define COMPANY "Medivis"
316+
!define DESCRIPTION "Intel RealSense IR retro-reflective marker tool tracker"
317+
!define REGKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APPID}"
318+
319+
Name "`${APPNAME} `${VERSION}"
320+
OutFile "$outFile"
321+
Unicode true
322+
InstallDir "`$PROGRAMFILES64\`${APPNAME}"
323+
InstallDirRegKey HKLM "Software\`${APPNAME}" "InstallDir"
324+
RequestExecutionLevel admin
325+
ShowInstDetails show
326+
ShowUninstDetails show
327+
328+
Page directory
329+
Page instfiles
330+
UninstPage uninstConfirm
331+
UninstPage instfiles
332+
333+
Section "Install"
334+
SetOutPath "`$INSTDIR"
335+
File /r "$stageNsi\\*"
336+
337+
CreateDirectory "`$SMPROGRAMS\`${APPNAME}"
338+
CreateShortcut "`$SMPROGRAMS\`${APPNAME}\`${APPNAME}.lnk" "`$INSTDIR\ir-tracking-app.exe"
339+
CreateShortcut "`$SMPROGRAMS\`${APPNAME}\Uninstall.lnk" "`$INSTDIR\Uninstall.exe"
340+
341+
WriteUninstaller "`$INSTDIR\Uninstall.exe"
342+
343+
WriteRegStr HKLM "Software\`${APPNAME}" "InstallDir" "`$INSTDIR"
344+
WriteRegStr HKLM "`${REGKEY}" "DisplayName" "`${APPNAME}"
345+
WriteRegStr HKLM "`${REGKEY}" "DisplayVersion" "`${VERSION}"
346+
WriteRegStr HKLM "`${REGKEY}" "Publisher" "`${COMPANY}"
347+
WriteRegStr HKLM "`${REGKEY}" "DisplayIcon" '"`$INSTDIR\ir-tracking-app.exe"'
348+
WriteRegStr HKLM "`${REGKEY}" "UninstallString" '"`$INSTDIR\Uninstall.exe"'
349+
WriteRegDWORD HKLM "`${REGKEY}" "NoModify" 1
350+
WriteRegDWORD HKLM "`${REGKEY}" "NoRepair" 1
351+
SectionEnd
352+
353+
Section "Uninstall"
354+
Delete "`$INSTDIR\Uninstall.exe"
355+
RMDir /r "`$INSTDIR"
356+
Delete "`$SMPROGRAMS\`${APPNAME}\`${APPNAME}.lnk"
357+
Delete "`$SMPROGRAMS\`${APPNAME}\Uninstall.lnk"
358+
RMDir "`$SMPROGRAMS\`${APPNAME}"
359+
DeleteRegKey HKLM "`${REGKEY}"
360+
DeleteRegKey HKLM "Software\`${APPNAME}"
361+
SectionEnd
362+
"@
363+
364+
Set-Content -Path $nsiPath -Value $nsi -Encoding UTF8
365+
& $makensis $nsiPath
366+
if ($LASTEXITCODE -ne 0) { throw "makensis failed (exit $LASTEXITCODE)." }
367+
Get-Item $outFile | Format-List Length, Name
218368
219369
# -----------------------------------------------------------------
220-
# Hand the archive off to the release job.
370+
# Upload the installer for the release job to collect.
221371
# -----------------------------------------------------------------
222372
- name: Upload artifact
223373
uses: actions/upload-artifact@v4
224374
with:
225375
name: ir-tracking-app-${{ matrix.label }}
226376
path: |
227-
ir-tracking-app-${{ matrix.label }}.tar.gz
228-
ir-tracking-app-${{ matrix.label }}.zip
377+
*.deb
378+
*.dmg
379+
*-setup.exe
229380
if-no-files-found: error
230381
retention-days: 7
231382

0 commit comments

Comments
 (0)