Bash · 9154 bytes Raw Blame History
1 #!/bin/bash
2 # Complete library bundling script for Sniffly
3 # Handles all GTK4 dependencies properly
4
5 set -e
6
7 APP_BUNDLE="Sniffly.app"
8 FRAMEWORKS="${APP_BUNDLE}/Contents/Frameworks"
9 MACOS_BIN="${APP_BUNDLE}/Contents/MacOS/sniffly-bin"
10
11 echo "=== Sniffly Library Bundling ==="
12 echo ""
13
14 # Create frameworks directory
15 mkdir -p "$FRAMEWORKS"
16
17 echo "Step 1: Copying critical GTK4 libraries..."
18 # Main GTK4
19 cp -v /opt/homebrew/opt/gtk4/lib/libgtk-4.1.dylib "$FRAMEWORKS/" 2>/dev/null || echo " libgtk-4.1.dylib not found (may be bundled already)"
20
21 # GLib family
22 cp -v /opt/homebrew/opt/glib/lib/libglib-2.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
23 cp -v /opt/homebrew/opt/glib/lib/libgio-2.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
24 cp -v /opt/homebrew/opt/glib/lib/libgobject-2.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
25 cp -v /opt/homebrew/opt/glib/lib/libgmodule-2.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
26
27 # GTK-Fortran binding
28 cp -v /usr/local/lib/libgtk-4-fortran.4.8.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
29
30 # Pango
31 cp -v /opt/homebrew/opt/pango/lib/libpango-1.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
32 cp -v /opt/homebrew/opt/pango/lib/libpangocairo-1.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
33 cp -v /opt/homebrew/opt/pango/lib/libpangoft2-1.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
34
35 # GdkPixbuf
36 cp -v /opt/homebrew/opt/gdk-pixbuf/lib/libgdk_pixbuf-2.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
37
38 # Cairo
39 cp -v /opt/homebrew/opt/cairo/lib/libcairo.2.dylib "$FRAMEWORKS/" 2>/dev/null || true
40 cp -v /opt/homebrew/opt/cairo/lib/libcairo-gobject.2.dylib "$FRAMEWORKS/" 2>/dev/null || true
41
42 # HarfBuzz
43 cp -v /opt/homebrew/opt/harfbuzz/lib/libharfbuzz.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
44
45 # Graphene
46 cp -v /opt/homebrew/opt/graphene/lib/libgraphene-1.0.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
47
48 # Epoxy (OpenGL wrapper)
49 cp -v /opt/homebrew/opt/libepoxy/lib/libepoxy.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
50
51 # Gettext (internationalization)
52 cp -v /opt/homebrew/opt/gettext/lib/libintl.8.dylib "$FRAMEWORKS/" 2>/dev/null || true
53
54 # Additional dependencies
55 cp -v /opt/homebrew/opt/fribidi/lib/libfribidi.0.dylib "$FRAMEWORKS/" 2>/dev/null || true
56 cp -v /opt/homebrew/opt/fontconfig/lib/libfontconfig.1.dylib "$FRAMEWORKS/" 2>/dev/null || true
57 cp -v /opt/homebrew/opt/freetype/lib/libfreetype.6.dylib "$FRAMEWORKS/" 2>/dev/null || true
58
59 echo ""
60 echo "Step 2: Running dylibbundler for ALL dependencies..."
61 echo "Note: dylibbundler may fail on GFortran libraries due to Mach-O header limits."
62 echo " This is expected and non-fatal - the app will still work correctly."
63 echo ""
64
65 # Use -of to overwrite and fix ALL dylibs recursively
66 # The dylibbundler will fail on libgfortran.5.dylib due to insufficient Mach-O header padding,
67 # but this is non-fatal. The library will still be bundled and functional.
68 dylibbundler -of -b \
69 -x "$MACOS_BIN" \
70 -d "$FRAMEWORKS/" \
71 -p @executable_path/../Frameworks/ \
72 -s /usr/local/lib \
73 -s /opt/homebrew/lib \
74 -s /opt/homebrew/opt/gtk4/lib \
75 -s /opt/homebrew/opt/glib/lib \
76 -s /opt/homebrew/opt/pango/lib \
77 -s /opt/homebrew/opt/cairo/lib \
78 -s /opt/homebrew/opt/harfbuzz/lib \
79 -s /opt/homebrew/opt/gdk-pixbuf/lib \
80 -s /opt/homebrew/opt/graphene/lib \
81 -s /opt/homebrew/opt/libepoxy/lib \
82 -s /opt/homebrew/opt/gettext/lib \
83 -s /opt/homebrew/opt/fribidi/lib \
84 -s /opt/homebrew/opt/fontconfig/lib \
85 -s /opt/homebrew/opt/freetype/lib \
86 -s /opt/homebrew/opt/libpng/lib \
87 -s /opt/homebrew/opt/graphite2/lib \
88 -s /opt/homebrew/opt/pcre2/lib \
89 -s /opt/homebrew/opt/brotli/lib \
90 -s /opt/homebrew/opt/bzip2/lib \
91 -s /opt/homebrew/opt/zstd/lib 2>&1 || echo " (dylibbundler completed with warnings - this is expected)"
92
93 echo ""
94 echo "Step 2.5: Manually fixing GFortran and GTK-Fortran library references..."
95 # dylibbundler sometimes misses @rpath references, so we fix them manually
96
97 # Fix binary's reference to libgfortran
98 install_name_tool -change /opt/homebrew/opt/gcc/lib/gcc/current/libgfortran.5.dylib @executable_path/../Frameworks/libgfortran.5.dylib "$MACOS_BIN" 2>/dev/null || true
99 install_name_tool -change /usr/local/lib/gcc/current/libgfortran.5.dylib @executable_path/../Frameworks/libgfortran.5.dylib "$MACOS_BIN" 2>/dev/null || true
100
101 # Fix binary's @rpath reference to libgtk-4-fortran (CRITICAL FIX)
102 install_name_tool -change @rpath/libgtk-4-fortran.4.8.0.dylib @executable_path/../Frameworks/libgtk-4-fortran.4.8.0.dylib "$MACOS_BIN" 2>/dev/null || true
103 install_name_tool -change /usr/local/lib/libgtk-4-fortran.4.8.0.dylib @executable_path/../Frameworks/libgtk-4-fortran.4.8.0.dylib "$MACOS_BIN" 2>/dev/null || true
104
105 # Fix libgfortran's internal references (only if it exists and isn't fully fixed)
106 if [ -f "$FRAMEWORKS/libgfortran.5.dylib" ]; then
107 # Try to fix remaining references - these might fail if header is full, but that's OK
108 install_name_tool -change "@rpath/libgcc_s.1.1.dylib" "@executable_path/../Frameworks/libgcc_s.1.1.dylib" "$FRAMEWORKS/libgfortran.5.dylib" 2>/dev/null || true
109 install_name_tool -id "@executable_path/../Frameworks/libgfortran.5.dylib" "$FRAMEWORKS/libgfortran.5.dylib" 2>/dev/null || true
110 fi
111
112 echo ""
113 echo "Step 3: Fixing library interdependencies..."
114 # dylibbundler should have done this, but let's make sure all bundled libs reference each other correctly
115 for lib in "$FRAMEWORKS"/*.dylib; do
116 if [ -f "$lib" ]; then
117 # Fix any remaining /opt/homebrew references
118 install_name_tool -change /opt/homebrew/opt/glib/lib/libglib-2.0.0.dylib @executable_path/../Frameworks/libglib-2.0.0.dylib "$lib" 2>/dev/null || true
119 install_name_tool -change /opt/homebrew/opt/glib/lib/libgio-2.0.0.dylib @executable_path/../Frameworks/libgio-2.0.0.dylib "$lib" 2>/dev/null || true
120 install_name_tool -change /opt/homebrew/opt/glib/lib/libgobject-2.0.0.dylib @executable_path/../Frameworks/libgobject-2.0.0.dylib "$lib" 2>/dev/null || true
121 install_name_tool -change /opt/homebrew/opt/glib/lib/libgmodule-2.0.0.dylib @executable_path/../Frameworks/libgmodule-2.0.0.dylib "$lib" 2>/dev/null || true
122 install_name_tool -change /opt/homebrew/opt/cairo/lib/libcairo.2.dylib @executable_path/../Frameworks/libcairo.2.dylib "$lib" 2>/dev/null || true
123 install_name_tool -change /opt/homebrew/opt/cairo/lib/libcairo-gobject.2.dylib @executable_path/../Frameworks/libcairo-gobject.2.dylib "$lib" 2>/dev/null || true
124 install_name_tool -change /opt/homebrew/opt/pango/lib/libpango-1.0.0.dylib @executable_path/../Frameworks/libpango-1.0.0.dylib "$lib" 2>/dev/null || true
125 install_name_tool -change /opt/homebrew/opt/pango/lib/libpangocairo-1.0.0.dylib @executable_path/../Frameworks/libpangocairo-1.0.0.dylib "$lib" 2>/dev/null || true
126 install_name_tool -change /opt/homebrew/opt/gtk4/lib/libgtk-4.1.dylib @executable_path/../Frameworks/libgtk-4.1.dylib "$lib" 2>/dev/null || true
127 install_name_tool -change /opt/homebrew/opt/gettext/lib/libintl.8.dylib @executable_path/../Frameworks/libintl.8.dylib "$lib" 2>/dev/null || true
128 install_name_tool -change /opt/homebrew/opt/harfbuzz/lib/libharfbuzz.0.dylib @executable_path/../Frameworks/libharfbuzz.0.dylib "$lib" 2>/dev/null || true
129 install_name_tool -change /opt/homebrew/opt/fribidi/lib/libfribidi.0.dylib @executable_path/../Frameworks/libfribidi.0.dylib "$lib" 2>/dev/null || true
130 install_name_tool -change /opt/homebrew/opt/fontconfig/lib/libfontconfig.1.dylib @executable_path/../Frameworks/libfontconfig.1.dylib "$lib" 2>/dev/null || true
131 install_name_tool -change /opt/homebrew/opt/freetype/lib/libfreetype.6.dylib @executable_path/../Frameworks/libfreetype.6.dylib "$lib" 2>/dev/null || true
132 install_name_tool -change /opt/homebrew/opt/gdk-pixbuf/lib/libgdk_pixbuf-2.0.0.dylib @executable_path/../Frameworks/libgdk_pixbuf-2.0.0.dylib "$lib" 2>/dev/null || true
133 install_name_tool -change /opt/homebrew/opt/graphene/lib/libgraphene-1.0.0.dylib @executable_path/../Frameworks/libgraphene-1.0.0.dylib "$lib" 2>/dev/null || true
134 install_name_tool -change /opt/homebrew/opt/libepoxy/lib/libepoxy.0.dylib @executable_path/../Frameworks/libepoxy.0.dylib "$lib" 2>/dev/null || true
135 fi
136 done
137
138 echo " Fixing library ID names..."
139 # Also fix the library ID names themselves
140 for lib in "$FRAMEWORKS"/*.dylib; do
141 if [ -f "$lib" ]; then
142 libname=$(basename "$lib")
143 install_name_tool -id @executable_path/../Frameworks/"$libname" "$lib" 2>/dev/null || true
144 fi
145 done
146
147 echo ""
148 echo "Step 4: Verifying bundle..."
149 TOTAL_LIBS=$(ls -1 "$FRAMEWORKS" | wc -l | tr -d ' ')
150 echo "Total libraries bundled: $TOTAL_LIBS"
151
152 # Check for critical libraries
153 echo ""
154 echo "Critical libraries check:"
155 for lib in libgtk-4 libglib-2.0 libgtk-4-fortran libcairo libpango libgfortran; do
156 if ls "$FRAMEWORKS"/${lib}* 1> /dev/null 2>&1; then
157 echo " ✓ ${lib}"
158 else
159 echo " ✗ ${lib} MISSING!"
160 fi
161 done
162
163 echo ""
164 echo "Step 5: Checking binary dependencies..."
165 otool -L "$MACOS_BIN" | grep -E "(gtk|glib|cairo)" | head -5
166
167 echo ""
168 echo "=== Bundling Complete ==="