Skip to content

Commit d0a606f

Browse files
authored
Mac binary fixes (#48)
- Make sure all `.dylibs` needed are recursively bundled into the binary - `glfw`, `spdlog`, `fmt` are statically linked on mac - All the rest including all `ffmpeg` dependencies dynamically linked, excluding Vulkan (loaded by [`volk`](https://github.com/zeux/volk)) - Should only require Vulkan to be installed Fixes #47 as the Mac binary didn't link everything before
1 parent 5990029 commit d0a606f

File tree

7 files changed

+227
-36
lines changed

7 files changed

+227
-36
lines changed

.github/workflows/linux-docker-ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
- main
77
- master
88
paths-ignore:
9+
- 'scripts/**'
910
- '**.md'
1011
- 'LICENSE'
1112
- '.gitignore'
@@ -14,6 +15,7 @@ on:
1415
branches:
1516
- main
1617
paths-ignore:
18+
- 'scripts/**'
1719
- '**.md'
1820
- 'LICENSE'
1921
- '.gitignore'

.github/workflows/linux-smoke-tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ on:
44
push:
55
branches: [main, master]
66
paths-ignore:
7+
- 'scripts/**'
78
- '**.md'
89
- 'LICENSE'
910
- '.gitignore'
1011
- '.github/workflows/release.yml'
1112
pull_request:
1213
paths-ignore:
14+
- 'scripts/**'
1315
- '**.md'
1416
- 'LICENSE'
1517
- '.gitignore'

.github/workflows/macos-ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
- main
77
- master
88
paths-ignore:
9+
- 'scripts/**'
910
- '**.md'
1011
- 'LICENSE'
1112
- '.gitignore'
@@ -14,6 +15,7 @@ on:
1415
branches:
1516
- main
1617
paths-ignore:
18+
- 'scripts/**'
1719
- '**.md'
1820
- 'LICENSE'
1921
- '.gitignore'

.github/workflows/nix-flake-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches: [main, master]
66
paths-ignore:
7+
- 'scripts/**'
78
- '**.md'
89
- 'LICENSE'
910
- '.gitignore'

.github/workflows/release.yml

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
tags:
66
- 'v*'
77
branches:
8-
- 'release-binaries-04'
8+
- 'mac-binary-02'
99
workflow_dispatch:
1010

1111
jobs:
@@ -240,76 +240,106 @@ jobs:
240240
# Copy the binary
241241
cp build/vsdf release/macos/
242242
243-
# Find and copy all non-system dylibs
244-
echo "Bundling dynamic libraries..."
243+
echo "📋 Libraries linked BEFORE bundling:"
244+
otool -L build/vsdf
245+
echo ""
245246
246-
# Get list of dynamic libraries (excluding system ones)
247-
DYLIBS=$(otool -L build/vsdf | grep -E "(glslang|spirv-tools|ffmpeg|libav)" | awk '{print $1}')
247+
# Recursively find and copy all non-system dylibs
248+
echo "🔍 Finding and bundling dynamic libraries..."
248249
249-
for lib in $DYLIBS; do
250+
# Function to copy a library and its dependencies
251+
copy_lib_recursive() {
252+
local lib="$1"
253+
local libname=$(basename "$lib")
254+
255+
# Skip if already copied
256+
if [ -f "release/macos/libs/$libname" ]; then
257+
return
258+
fi
259+
260+
# Skip system libraries
261+
if [[ "$lib" == /System/* ]] || [[ "$lib" == /usr/lib/* ]] || [[ "$lib" == /Library/Apple/* ]]; then
262+
return
263+
fi
264+
265+
# Copy the library
250266
if [ -f "$lib" ]; then
251-
libname=$(basename "$lib")
252-
if [ -f "release/macos/libs/$libname" ]; then
253-
echo "Already copied $libname"
254-
else
255-
echo "Copying $libname"
256-
cp "$lib" release/macos/libs/
257-
fi
258-
259-
# Also copy any dependencies of this library
260-
SUB_DYLIBS=$(otool -L "$lib" | grep -E "(glslang|spirv-tools|ffmpeg|libav)" | awk '{print $1}')
261-
for sublib in $SUB_DYLIBS; do
262-
if [ -f "$sublib" ]; then
263-
sublibname=$(basename "$sublib")
264-
if [ ! -f "release/macos/libs/$sublibname" ]; then
265-
echo "Copying dependency $sublibname"
266-
cp "$sublib" release/macos/libs/
267-
fi
267+
echo " → Copying $libname"
268+
cp "$lib" release/macos/libs/
269+
270+
# Recursively copy dependencies of this library
271+
otool -L "$lib" | tail -n +2 | awk '{print $1}' | while read -r dep; do
272+
if [ -f "$dep" ]; then
273+
copy_lib_recursive "$dep"
268274
fi
269275
done
270276
fi
277+
}
278+
279+
# Get initial list of libraries from the binary
280+
otool -L build/vsdf | tail -n +2 | awk '{print $1}' | while read -r lib; do
281+
if [ -f "$lib" ]; then
282+
copy_lib_recursive "$lib"
283+
fi
271284
done
272285
286+
BUNDLED_COUNT=$(ls release/macos/libs/*.dylib 2>/dev/null | wc -l | xargs)
287+
echo ""
288+
echo "Total libraries bundled: $BUNDLED_COUNT"
289+
echo ""
290+
273291
# Fix all library paths to use @rpath
274-
echo "Fixing library paths..."
292+
echo "🔧 Fixing library paths..."
275293
276-
# Set rpath on the binary to look next to the executable
277-
install_name_tool -add_rpath "@executable_path" release/macos/vsdf
294+
# Set rpath on the binary to look in libs/ folder next to the executable
295+
# Only add if it doesn't already exist
296+
if ! otool -l release/macos/vsdf | grep -q "@executable_path/libs"; then
297+
echo " Adding @executable_path/libs to rpath"
298+
install_name_tool -add_rpath "@executable_path/libs" release/macos/vsdf
299+
else
300+
echo " @executable_path/libs already in rpath"
301+
fi
278302
279303
# Fix paths in the main binary
280304
for lib in release/macos/libs/*.dylib; do
281305
libname=$(basename "$lib")
282306
# Find the original path in the binary
283307
ORIG_PATH=$(otool -L release/macos/vsdf | grep "$libname" | awk '{print $1}')
284308
if [ ! -z "$ORIG_PATH" ]; then
285-
echo "Fixing $libname in vsdf"
286-
install_name_tool -change "$ORIG_PATH" "@rpath/libs/$libname" release/macos/vsdf
309+
echo " Fixing $libname in vsdf: $ORIG_PATH -> @rpath/$libname"
310+
install_name_tool -change "$ORIG_PATH" "@rpath/$libname" release/macos/vsdf
287311
fi
288312
done
289313
290314
# Fix inter-library dependencies
291315
for lib in release/macos/libs/*.dylib; do
292316
libname=$(basename "$lib")
293-
echo "Fixing paths in $libname"
294317
295318
# Fix the library's own id
296-
install_name_tool -id "@rpath/libs/$libname" "$lib"
319+
install_name_tool -id "@rpath/$libname" "$lib"
297320
298321
# Fix references to other bundled libraries
299322
for otherlib in release/macos/libs/*.dylib; do
300323
othername=$(basename "$otherlib")
301324
ORIG_PATH=$(otool -L "$lib" | grep "$othername" | awk '{print $1}')
302-
if [ ! -z "$ORIG_PATH" ] && [ "$ORIG_PATH" != "@rpath/libs/$othername" ]; then
303-
install_name_tool -change "$ORIG_PATH" "@rpath/libs/$othername" "$lib"
325+
if [ ! -z "$ORIG_PATH" ] && [ "$ORIG_PATH" != "@rpath/$othername" ]; then
326+
echo " Fixing $othername in $libname: $ORIG_PATH -> @rpath/$othername"
327+
install_name_tool -change "$ORIG_PATH" "@rpath/$othername" "$lib"
304328
fi
305329
done
306330
done
307331
308-
echo "Bundle complete!"
309-
echo "Bundled libraries:"
332+
echo ""
333+
echo "✓ Bundling complete"
334+
echo ""
335+
echo "📦 Binary info:"
336+
file release/macos/vsdf
337+
ls -lh release/macos/vsdf
338+
echo ""
339+
echo "📚 Bundled libraries:"
310340
ls -lh release/macos/libs/
311-
312-
echo "Binary dependencies after fixing:"
341+
echo ""
342+
echo "🔗 Binary dependencies after fixing:"
313343
otool -L release/macos/vsdf
314344
315345
- name: Code sign binaries

.github/workflows/windows-build-test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
- main
77
- master
88
paths-ignore:
9+
- 'scripts/**'
910
- '**.md'
1011
- 'LICENSE'
1112
- '.gitignore'
@@ -14,6 +15,7 @@ on:
1415
branches:
1516
- main
1617
paths-ignore:
18+
- 'scripts/**'
1719
- '**.md'
1820
- 'LICENSE'
1921
- '.gitignore'

scripts/bundle_macos.sh

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# macOS bundling script - replicates the GitHub Actions workflow logic
5+
# Usage: ./scripts/bundle_macos.sh [build_dir] [release_dir]
6+
7+
BUILD_DIR="${1:-build}"
8+
RELEASE_DIR="${2:-release/macos}"
9+
10+
echo "📦 macOS Binary Bundling Script"
11+
echo "================================"
12+
echo "Build directory: $BUILD_DIR"
13+
echo "Release directory: $RELEASE_DIR"
14+
echo ""
15+
16+
# Check if binary exists
17+
if [ ! -f "$BUILD_DIR/vsdf" ]; then
18+
echo "❌ Error: $BUILD_DIR/vsdf not found"
19+
echo "Please build the project first with: cmake -B build -DCMAKE_BUILD_TYPE=Release . && cmake --build build"
20+
exit 1
21+
fi
22+
23+
# Create libs directory
24+
mkdir -p "$RELEASE_DIR/libs"
25+
26+
# Copy the binary
27+
cp "$BUILD_DIR/vsdf" "$RELEASE_DIR/"
28+
29+
echo "📋 Libraries linked BEFORE bundling:"
30+
otool -L "$BUILD_DIR/vsdf"
31+
echo ""
32+
33+
# Recursively find and copy all non-system dylibs
34+
echo "🔍 Finding and bundling dynamic libraries..."
35+
36+
# Function to copy a library and its dependencies
37+
copy_lib_recursive() {
38+
local lib="$1"
39+
local libname=$(basename "$lib")
40+
41+
# Skip if already copied
42+
if [ -f "$RELEASE_DIR/libs/$libname" ]; then
43+
return
44+
fi
45+
46+
# Skip system libraries
47+
if [[ "$lib" == /System/* ]] || [[ "$lib" == /usr/lib/* ]] || [[ "$lib" == /Library/Apple/* ]]; then
48+
return
49+
fi
50+
51+
# Copy the library
52+
if [ -f "$lib" ]; then
53+
echo " → Copying $libname"
54+
cp "$lib" "$RELEASE_DIR/libs/"
55+
56+
# Recursively copy dependencies of this library
57+
otool -L "$lib" | tail -n +2 | awk '{print $1}' | while read -r dep; do
58+
if [ -f "$dep" ]; then
59+
copy_lib_recursive "$dep"
60+
fi
61+
done
62+
fi
63+
}
64+
65+
# Get initial list of libraries from the binary
66+
otool -L "$BUILD_DIR/vsdf" | tail -n +2 | awk '{print $1}' | while read -r lib; do
67+
if [ -f "$lib" ]; then
68+
copy_lib_recursive "$lib"
69+
fi
70+
done
71+
72+
BUNDLED_COUNT=$(ls "$RELEASE_DIR/libs"/*.dylib 2>/dev/null | wc -l | xargs)
73+
echo ""
74+
echo "Total libraries bundled: $BUNDLED_COUNT"
75+
echo ""
76+
77+
# Fix all library paths to use @rpath
78+
echo "🔧 Fixing library paths..."
79+
80+
# Set rpath on the binary to look in libs/ folder next to the executable
81+
# Only add if it doesn't already exist
82+
if ! otool -l "$RELEASE_DIR/vsdf" | grep -q "@executable_path/libs"; then
83+
echo " Adding @executable_path/libs to rpath"
84+
install_name_tool -add_rpath "@executable_path/libs" "$RELEASE_DIR/vsdf"
85+
else
86+
echo " @executable_path/libs already in rpath"
87+
fi
88+
89+
# Fix paths in the main binary
90+
for lib in "$RELEASE_DIR/libs"/*.dylib; do
91+
libname=$(basename "$lib")
92+
# Find the original path in the binary
93+
ORIG_PATH=$(otool -L "$RELEASE_DIR/vsdf" | grep "$libname" | awk '{print $1}')
94+
if [ ! -z "$ORIG_PATH" ]; then
95+
echo " Fixing $libname in vsdf: $ORIG_PATH -> @rpath/$libname"
96+
install_name_tool -change "$ORIG_PATH" "@rpath/$libname" "$RELEASE_DIR/vsdf"
97+
fi
98+
done
99+
100+
# Fix inter-library dependencies
101+
for lib in "$RELEASE_DIR/libs"/*.dylib; do
102+
libname=$(basename "$lib")
103+
104+
# Fix the library's own id
105+
install_name_tool -id "@rpath/$libname" "$lib"
106+
107+
# Fix references to other bundled libraries
108+
for otherlib in "$RELEASE_DIR/libs"/*.dylib; do
109+
othername=$(basename "$otherlib")
110+
ORIG_PATH=$(otool -L "$lib" | grep "$othername" | awk '{print $1}')
111+
if [ ! -z "$ORIG_PATH" ] && [ "$ORIG_PATH" != "@rpath/$othername" ]; then
112+
echo " Fixing $othername in $libname: $ORIG_PATH -> @rpath/$othername"
113+
install_name_tool -change "$ORIG_PATH" "@rpath/$othername" "$lib"
114+
fi
115+
done
116+
done
117+
118+
echo "Ad-hoc signing binary and libraries..."
119+
# Ad-hoc sign all libraries
120+
for lib in release/macos/libs/*.dylib; do
121+
echo "Signing $(basename "$lib")"
122+
codesign --force --sign - "$lib"
123+
done
124+
125+
# Ad-hoc sign the main binary
126+
echo "Signing vsdf"
127+
codesign --force --sign - release/macos/vsdf
128+
129+
echo "Verifying signatures..."
130+
codesign -v release/macos/vsdf
131+
for lib in release/macos/libs/*.dylib; do
132+
codesign -v "$lib"
133+
done
134+
135+
echo ""
136+
echo "✓ Bundling complete"
137+
echo ""
138+
echo "📦 Binary info:"
139+
file "$RELEASE_DIR/vsdf"
140+
ls -lh "$RELEASE_DIR/vsdf"
141+
echo ""
142+
echo "📚 Bundled libraries:"
143+
ls -lh "$RELEASE_DIR/libs/"
144+
echo ""
145+
echo "🔗 Binary dependencies after fixing:"
146+
otool -L "$RELEASE_DIR/vsdf"
147+
148+
echo ""
149+
echo "🎉 Done! To package the release:"
150+
echo " cp -r shaders $RELEASE_DIR/"
151+
echo " cp README.md LICENSE $RELEASE_DIR/"
152+
echo " cd release && tar -czf vsdf-macos-$(uname -m).tar.gz macos/"

0 commit comments

Comments
 (0)