markdown · 12026 bytes Raw Blame History

Sniffly Packaging Guide

This document explains how to package Sniffly for distribution on macOS and Linux.

Current State

Sniffly is built using:

  • Meson build system
  • GTK4 for the GUI
  • gtk-fortran bindings
  • gfortran compiler (GCC Fortran)

The executable is currently located at build/sniffly after running meson compile -C build.


macOS Packaging (.dmg)

Overview

On macOS, applications are distributed as:

  1. .app bundles - Directory structure that looks like a single file
  2. .dmg files - Disk images containing the .app bundle

Steps to Create a macOS .app Bundle

1. Create the Bundle Structure

# Create the app bundle directories
mkdir -p Sniffly.app/Contents/MacOS
mkdir -p Sniffly.app/Contents/Resources
mkdir -p Sniffly.app/Contents/Frameworks

2. Copy the Executable

# Copy the compiled binary
cp build/sniffly Sniffly.app/Contents/MacOS/sniffly

3. Create Info.plist

Create Sniffly.app/Contents/Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>sniffly</string>
    <key>CFBundleIdentifier</key>
    <string>org.fortrangoingonforty.sniffly</string>
    <key>CFBundleName</key>
    <string>Sniffly</string>
    <key>CFBundleDisplayName</key>
    <string>Sniffly</string>
    <key>CFBundleVersion</key>
    <string>0.1.0</string>
    <key>CFBundleShortVersionString</key>
    <string>0.1.0</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleSignature</key>
    <string>SNIF</string>
    <key>CFBundleIconFile</key>
    <string>sniffly</string>
    <key>LSMinimumSystemVersion</key>
    <string>11.0</string>
    <key>NSHighResolutionCapable</key>
    <true/>
    <key>NSRequiresAquaSystemAppearance</key>
    <false/>
</dict>
</plist>

4. Create an Application Icon

You need a .icns file. Create one from a PNG using:

# Create iconset directory
mkdir sniffly.iconset

# Create different sizes (you'll need a source image)
# 16x16, 32x32, 128x128, 256x256, 512x512, 1024x1024
sips -z 16 16     icon-1024.png --out sniffly.iconset/icon_16x16.png
sips -z 32 32     icon-1024.png --out sniffly.iconset/icon_16x16@2x.png
sips -z 32 32     icon-1024.png --out sniffly.iconset/icon_32x32.png
sips -z 64 64     icon-1024.png --out sniffly.iconset/icon_32x32@2x.png
sips -z 128 128   icon-1024.png --out sniffly.iconset/icon_128x128.png
sips -z 256 256   icon-1024.png --out sniffly.iconset/icon_128x128@2x.png
sips -z 256 256   icon-1024.png --out sniffly.iconset/icon_256x256.png
sips -z 512 512   icon-1024.png --out sniffly.iconset/icon_256x256@2x.png
sips -z 512 512   icon-1024.png --out sniffly.iconset/icon_512x512.png
sips -z 1024 1024 icon-1024.png --out sniffly.iconset/icon_512x512@2x.png

# Convert to .icns
iconutil -c icns sniffly.iconset -o Sniffly.app/Contents/Resources/sniffly.icns

5. Bundle GTK4 Libraries

This is the tricky part! The app needs GTK4 libraries. You have two options:

Option A: Use Homebrew's GTK4 (requires user to have GTK4 installed)

# User must run: brew install gtk4
# Then the app will find libraries via dylib search paths

Option B: Bundle libraries (recommended for distribution)

# Copy GTK4 libraries into the bundle
cp -r /opt/homebrew/lib/libgtk-4*.dylib Sniffly.app/Contents/Frameworks/
cp -r /opt/homebrew/lib/libglib-2.0*.dylib Sniffly.app/Contents/Frameworks/
cp -r /opt/homebrew/lib/libgobject-2.0*.dylib Sniffly.app/Contents/Frameworks/
# ... and all other GTK4 dependencies

# Use install_name_tool to fix library paths
install_name_tool -change /opt/homebrew/lib/libgtk-4.dylib \
    @executable_path/../Frameworks/libgtk-4.dylib \
    Sniffly.app/Contents/MacOS/sniffly

Better Option: Use dylibbundler

# Install dylibbundler
brew install dylibbundler

# Automatically bundle all dependencies
dylibbundler -od -b \
    -x Sniffly.app/Contents/MacOS/sniffly \
    -d Sniffly.app/Contents/Frameworks/ \
    -p @executable_path/../Frameworks/

6. Create the .dmg

# Create a temporary directory for DMG contents
mkdir dmg_temp
cp -r Sniffly.app dmg_temp/

# Optional: Create a symbolic link to /Applications for easy drag-install
ln -s /Applications dmg_temp/Applications

# Create the DMG
hdiutil create -volname "Sniffly" \
    -srcfolder dmg_temp \
    -ov -format UDZO \
    Sniffly-0.1.0-macOS.dmg

# Clean up
rm -rf dmg_temp
# Sign the app (requires Apple Developer account)
codesign --deep --force --verify --verbose \
    --sign "Developer ID Application: Your Name" \
    Sniffly.app

# Notarize with Apple (required for distribution outside App Store)
xcrun notarytool submit Sniffly-0.1.0-macOS.dmg \
    --apple-id "your@email.com" \
    --password "app-specific-password" \
    --team-id "YOUR_TEAM_ID" \
    --wait

# Staple the notarization ticket
xcrun stapler staple Sniffly-0.1.0-macOS.dmg

Linux Packaging

AppImage is a universal package format that works across all Linux distributions.

Create AppImage Structure

# Create AppDir structure
mkdir -p Sniffly.AppDir/usr/bin
mkdir -p Sniffly.AppDir/usr/lib
mkdir -p Sniffly.AppDir/usr/share/applications
mkdir -p Sniffly.AppDir/usr/share/icons/hicolor/256x256/apps

# Copy executable
cp build/sniffly Sniffly.AppDir/usr/bin/

# Copy icon
cp assets/sniffly.png Sniffly.AppDir/usr/share/icons/hicolor/256x256/apps/sniffly.png
cp assets/sniffly.png Sniffly.AppDir/sniffly.png

# Create .desktop file
cat > Sniffly.AppDir/sniffly.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=Sniffly
Comment=Disk Space Analyzer
Exec=sniffly
Icon=sniffly
Categories=Utility;System;
Terminal=false
EOF

# Copy to required location
cp Sniffly.AppDir/sniffly.desktop Sniffly.AppDir/usr/share/applications/

# Create AppRun script
cat > Sniffly.AppDir/AppRun << 'EOF'
#!/bin/bash
SELF=$(readlink -f "$0")
HERE=${SELF%/*}
export PATH="${HERE}/usr/bin:${PATH}"
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
export XDG_DATA_DIRS="${HERE}/usr/share:${XDG_DATA_DIRS}"
exec "${HERE}/usr/bin/sniffly" "$@"
EOF

chmod +x Sniffly.AppDir/AppRun

# Download appimagetool
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage

# Build AppImage
./appimagetool-x86_64.AppImage Sniffly.AppDir Sniffly-0.1.0-x86_64.AppImage

Note: AppImage requires GTK4 to be installed on the system. For a fully self-contained AppImage, you'd need to bundle GTK4 libraries.

Option 2: Debian Package (.deb)

For Debian/Ubuntu users:

# Create package structure
mkdir -p sniffly-0.1.0/DEBIAN
mkdir -p sniffly-0.1.0/usr/bin
mkdir -p sniffly-0.1.0/usr/share/applications
mkdir -p sniffly-0.1.0/usr/share/icons/hicolor/256x256/apps

# Copy files
cp build/sniffly sniffly-0.1.0/usr/bin/
cp assets/sniffly.png sniffly-0.1.0/usr/share/icons/hicolor/256x256/apps/
cp assets/sniffly.desktop sniffly-0.1.0/usr/share/applications/

# Create control file
cat > sniffly-0.1.0/DEBIAN/control << 'EOF'
Package: sniffly
Version: 0.1.0
Section: utils
Priority: optional
Architecture: amd64
Depends: libgtk-4-1, libglib2.0-0
Maintainer: FortranGoingOnForty <your@email.com>
Description: Disk Space Analyzer
 A fast, beautiful disk space analyzer built with Fortran and GTK4.
 Visualizes disk usage with interactive treemaps.
EOF

# Build the package
dpkg-deb --build sniffly-0.1.0

Option 3: RPM Package (Fedora/RedHat)

# Create RPM build directories
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

# Create spec file
cat > ~/rpmbuild/SPECS/sniffly.spec << 'EOF'
Name:           sniffly
Version:        0.1.0
Release:        1%{?dist}
Summary:        Disk Space Analyzer
License:        MIT
URL:            https://github.com/FortranGoingOnForty/sniffly
Source0:        %{name}-%{version}.tar.gz

BuildRequires:  meson, gcc-gfortran, gtk4-devel
Requires:       gtk4

%description
A fast, beautiful disk space analyzer built with Fortran and GTK4.

%prep
%setup -q

%build
meson setup build
meson compile -C build

%install
install -Dm755 build/sniffly %{buildroot}%{_bindir}/sniffly
install -Dm644 assets/sniffly.desktop %{buildroot}%{_datadir}/applications/sniffly.desktop
install -Dm644 assets/sniffly.png %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/sniffly.png

%files
%{_bindir}/sniffly
%{_datadir}/applications/sniffly.desktop
%{_datadir}/icons/hicolor/256x256/apps/sniffly.png

%changelog
* Mon Jan 01 2024 Your Name <your@email.com> - 0.1.0-1
- Initial release
EOF

# Create source tarball
tar czf ~/rpmbuild/SOURCES/sniffly-0.1.0.tar.gz ../sniffly/

# Build RPM
rpmbuild -ba ~/rpmbuild/SPECS/sniffly.spec

Automated Packaging with CI/CD

GitHub Actions Example

Create .github/workflows/release.yml:

name: Release Build

on:
  push:
    tags:
      - 'v*'

jobs:
  build-macos:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: |
          brew install meson gtk4 gcc
      - name: Build
        run: |
          meson setup build
          meson compile -C build
      - name: Create DMG
        run: |
          # Add DMG creation steps here
      - name: Upload Release Asset
        uses: actions/upload-artifact@v3
        with:
          name: Sniffly-macOS.dmg
          path: Sniffly-*.dmg

  build-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y meson gfortran libgtk-4-dev
      - name: Build
        run: |
          meson setup build
          meson compile -C build
      - name: Create AppImage
        run: |
          # Add AppImage creation steps here
      - name: Upload Release Asset
        uses: actions/upload-artifact@v3
        with:
          name: Sniffly-Linux-x86_64.AppImage
          path: Sniffly-*.AppImage

Quick Start Summary

macOS

  1. Build the app: meson compile -C build
  2. Create .app bundle structure
  3. Use dylibbundler to bundle GTK4 libraries
  4. Create .dmg with hdiutil
  5. (Optional) Code sign and notarize

Result: Sniffly-0.1.0-macOS.dmg

Linux

  1. Build the app: meson compile -C build
  2. Create AppDir structure
  3. Use appimagetool to create AppImage
  4. Or create .deb/.rpm for specific distros

Result: Sniffly-0.1.0-x86_64.AppImage or .deb/.rpm


Distribution Checklist

  • Create application icon (1024x1024 PNG)
  • Create .desktop file for Linux
  • Test on clean system without development tools
  • Document system requirements (GTK4, etc.)
  • Add installation instructions to README
  • Create GitHub releases page
  • Consider Homebrew formula for macOS
  • Consider Flatpak for Linux (alternative to AppImage)

Notes on GTK4 Dependencies

Sniffly requires GTK4 at runtime. You have three options:

  1. User installation: Require users to install GTK4 (brew install gtk4 on macOS, apt install libgtk-4-1 on Debian)
  2. Bundle libraries: Include GTK4 in your app bundle (increases size ~100MB but works anywhere)
  3. Hybrid: Bundle on macOS, rely on system packages on Linux

For the best user experience, option 2 (bundling) is recommended for macOS, while option 1 (system packages) works well for Linux where GTK4 is commonly available.


Future Improvements

  • Flatpak: Cross-distro sandboxed app (like macOS .app)
  • Snap: Alternative Linux universal package
  • Homebrew Cask: Easy installation on macOS (brew install --cask sniffly)
  • AUR Package: For Arch Linux users
  • Windows: Cross-compile with MinGW-w64 (if desired)
View source
1 # Sniffly Packaging Guide
2
3 This document explains how to package Sniffly for distribution on macOS and Linux.
4
5 ## Current State
6
7 Sniffly is built using:
8 - **Meson** build system
9 - **GTK4** for the GUI
10 - **gtk-fortran** bindings
11 - **gfortran** compiler (GCC Fortran)
12
13 The executable is currently located at `build/sniffly` after running `meson compile -C build`.
14
15 ---
16
17 ## macOS Packaging (.dmg)
18
19 ### Overview
20 On macOS, applications are distributed as:
21 1. **.app bundles** - Directory structure that looks like a single file
22 2. **.dmg files** - Disk images containing the .app bundle
23
24 ### Steps to Create a macOS .app Bundle
25
26 #### 1. Create the Bundle Structure
27
28 ```bash
29 # Create the app bundle directories
30 mkdir -p Sniffly.app/Contents/MacOS
31 mkdir -p Sniffly.app/Contents/Resources
32 mkdir -p Sniffly.app/Contents/Frameworks
33 ```
34
35 #### 2. Copy the Executable
36
37 ```bash
38 # Copy the compiled binary
39 cp build/sniffly Sniffly.app/Contents/MacOS/sniffly
40 ```
41
42 #### 3. Create Info.plist
43
44 Create `Sniffly.app/Contents/Info.plist`:
45
46 ```xml
47 <?xml version="1.0" encoding="UTF-8"?>
48 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
49 <plist version="1.0">
50 <dict>
51 <key>CFBundleExecutable</key>
52 <string>sniffly</string>
53 <key>CFBundleIdentifier</key>
54 <string>org.fortrangoingonforty.sniffly</string>
55 <key>CFBundleName</key>
56 <string>Sniffly</string>
57 <key>CFBundleDisplayName</key>
58 <string>Sniffly</string>
59 <key>CFBundleVersion</key>
60 <string>0.1.0</string>
61 <key>CFBundleShortVersionString</key>
62 <string>0.1.0</string>
63 <key>CFBundlePackageType</key>
64 <string>APPL</string>
65 <key>CFBundleSignature</key>
66 <string>SNIF</string>
67 <key>CFBundleIconFile</key>
68 <string>sniffly</string>
69 <key>LSMinimumSystemVersion</key>
70 <string>11.0</string>
71 <key>NSHighResolutionCapable</key>
72 <true/>
73 <key>NSRequiresAquaSystemAppearance</key>
74 <false/>
75 </dict>
76 </plist>
77 ```
78
79 #### 4. Create an Application Icon
80
81 You need a `.icns` file. Create one from a PNG using:
82
83 ```bash
84 # Create iconset directory
85 mkdir sniffly.iconset
86
87 # Create different sizes (you'll need a source image)
88 # 16x16, 32x32, 128x128, 256x256, 512x512, 1024x1024
89 sips -z 16 16 icon-1024.png --out sniffly.iconset/icon_16x16.png
90 sips -z 32 32 icon-1024.png --out sniffly.iconset/icon_16x16@2x.png
91 sips -z 32 32 icon-1024.png --out sniffly.iconset/icon_32x32.png
92 sips -z 64 64 icon-1024.png --out sniffly.iconset/icon_32x32@2x.png
93 sips -z 128 128 icon-1024.png --out sniffly.iconset/icon_128x128.png
94 sips -z 256 256 icon-1024.png --out sniffly.iconset/icon_128x128@2x.png
95 sips -z 256 256 icon-1024.png --out sniffly.iconset/icon_256x256.png
96 sips -z 512 512 icon-1024.png --out sniffly.iconset/icon_256x256@2x.png
97 sips -z 512 512 icon-1024.png --out sniffly.iconset/icon_512x512.png
98 sips -z 1024 1024 icon-1024.png --out sniffly.iconset/icon_512x512@2x.png
99
100 # Convert to .icns
101 iconutil -c icns sniffly.iconset -o Sniffly.app/Contents/Resources/sniffly.icns
102 ```
103
104 #### 5. Bundle GTK4 Libraries
105
106 This is the tricky part! The app needs GTK4 libraries. You have two options:
107
108 **Option A: Use Homebrew's GTK4 (requires user to have GTK4 installed)**
109 ```bash
110 # User must run: brew install gtk4
111 # Then the app will find libraries via dylib search paths
112 ```
113
114 **Option B: Bundle libraries (recommended for distribution)**
115
116 ```bash
117 # Copy GTK4 libraries into the bundle
118 cp -r /opt/homebrew/lib/libgtk-4*.dylib Sniffly.app/Contents/Frameworks/
119 cp -r /opt/homebrew/lib/libglib-2.0*.dylib Sniffly.app/Contents/Frameworks/
120 cp -r /opt/homebrew/lib/libgobject-2.0*.dylib Sniffly.app/Contents/Frameworks/
121 # ... and all other GTK4 dependencies
122
123 # Use install_name_tool to fix library paths
124 install_name_tool -change /opt/homebrew/lib/libgtk-4.dylib \
125 @executable_path/../Frameworks/libgtk-4.dylib \
126 Sniffly.app/Contents/MacOS/sniffly
127 ```
128
129 **Better Option: Use `dylibbundler`**
130 ```bash
131 # Install dylibbundler
132 brew install dylibbundler
133
134 # Automatically bundle all dependencies
135 dylibbundler -od -b \
136 -x Sniffly.app/Contents/MacOS/sniffly \
137 -d Sniffly.app/Contents/Frameworks/ \
138 -p @executable_path/../Frameworks/
139 ```
140
141 #### 6. Create the .dmg
142
143 ```bash
144 # Create a temporary directory for DMG contents
145 mkdir dmg_temp
146 cp -r Sniffly.app dmg_temp/
147
148 # Optional: Create a symbolic link to /Applications for easy drag-install
149 ln -s /Applications dmg_temp/Applications
150
151 # Create the DMG
152 hdiutil create -volname "Sniffly" \
153 -srcfolder dmg_temp \
154 -ov -format UDZO \
155 Sniffly-0.1.0-macOS.dmg
156
157 # Clean up
158 rm -rf dmg_temp
159 ```
160
161 #### 7. Code Signing (Optional but Recommended)
162
163 ```bash
164 # Sign the app (requires Apple Developer account)
165 codesign --deep --force --verify --verbose \
166 --sign "Developer ID Application: Your Name" \
167 Sniffly.app
168
169 # Notarize with Apple (required for distribution outside App Store)
170 xcrun notarytool submit Sniffly-0.1.0-macOS.dmg \
171 --apple-id "your@email.com" \
172 --password "app-specific-password" \
173 --team-id "YOUR_TEAM_ID" \
174 --wait
175
176 # Staple the notarization ticket
177 xcrun stapler staple Sniffly-0.1.0-macOS.dmg
178 ```
179
180 ---
181
182 ## Linux Packaging
183
184 ### Option 1: AppImage (Recommended - Works on All Distros)
185
186 AppImage is a universal package format that works across all Linux distributions.
187
188 #### Create AppImage Structure
189
190 ```bash
191 # Create AppDir structure
192 mkdir -p Sniffly.AppDir/usr/bin
193 mkdir -p Sniffly.AppDir/usr/lib
194 mkdir -p Sniffly.AppDir/usr/share/applications
195 mkdir -p Sniffly.AppDir/usr/share/icons/hicolor/256x256/apps
196
197 # Copy executable
198 cp build/sniffly Sniffly.AppDir/usr/bin/
199
200 # Copy icon
201 cp assets/sniffly.png Sniffly.AppDir/usr/share/icons/hicolor/256x256/apps/sniffly.png
202 cp assets/sniffly.png Sniffly.AppDir/sniffly.png
203
204 # Create .desktop file
205 cat > Sniffly.AppDir/sniffly.desktop << 'EOF'
206 [Desktop Entry]
207 Type=Application
208 Name=Sniffly
209 Comment=Disk Space Analyzer
210 Exec=sniffly
211 Icon=sniffly
212 Categories=Utility;System;
213 Terminal=false
214 EOF
215
216 # Copy to required location
217 cp Sniffly.AppDir/sniffly.desktop Sniffly.AppDir/usr/share/applications/
218
219 # Create AppRun script
220 cat > Sniffly.AppDir/AppRun << 'EOF'
221 #!/bin/bash
222 SELF=$(readlink -f "$0")
223 HERE=${SELF%/*}
224 export PATH="${HERE}/usr/bin:${PATH}"
225 export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
226 export XDG_DATA_DIRS="${HERE}/usr/share:${XDG_DATA_DIRS}"
227 exec "${HERE}/usr/bin/sniffly" "$@"
228 EOF
229
230 chmod +x Sniffly.AppDir/AppRun
231
232 # Download appimagetool
233 wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
234 chmod +x appimagetool-x86_64.AppImage
235
236 # Build AppImage
237 ./appimagetool-x86_64.AppImage Sniffly.AppDir Sniffly-0.1.0-x86_64.AppImage
238 ```
239
240 **Note**: AppImage requires GTK4 to be installed on the system. For a fully self-contained AppImage, you'd need to bundle GTK4 libraries.
241
242 ### Option 2: Debian Package (.deb)
243
244 For Debian/Ubuntu users:
245
246 ```bash
247 # Create package structure
248 mkdir -p sniffly-0.1.0/DEBIAN
249 mkdir -p sniffly-0.1.0/usr/bin
250 mkdir -p sniffly-0.1.0/usr/share/applications
251 mkdir -p sniffly-0.1.0/usr/share/icons/hicolor/256x256/apps
252
253 # Copy files
254 cp build/sniffly sniffly-0.1.0/usr/bin/
255 cp assets/sniffly.png sniffly-0.1.0/usr/share/icons/hicolor/256x256/apps/
256 cp assets/sniffly.desktop sniffly-0.1.0/usr/share/applications/
257
258 # Create control file
259 cat > sniffly-0.1.0/DEBIAN/control << 'EOF'
260 Package: sniffly
261 Version: 0.1.0
262 Section: utils
263 Priority: optional
264 Architecture: amd64
265 Depends: libgtk-4-1, libglib2.0-0
266 Maintainer: FortranGoingOnForty <your@email.com>
267 Description: Disk Space Analyzer
268 A fast, beautiful disk space analyzer built with Fortran and GTK4.
269 Visualizes disk usage with interactive treemaps.
270 EOF
271
272 # Build the package
273 dpkg-deb --build sniffly-0.1.0
274 ```
275
276 ### Option 3: RPM Package (Fedora/RedHat)
277
278 ```bash
279 # Create RPM build directories
280 mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
281
282 # Create spec file
283 cat > ~/rpmbuild/SPECS/sniffly.spec << 'EOF'
284 Name: sniffly
285 Version: 0.1.0
286 Release: 1%{?dist}
287 Summary: Disk Space Analyzer
288 License: MIT
289 URL: https://github.com/FortranGoingOnForty/sniffly
290 Source0: %{name}-%{version}.tar.gz
291
292 BuildRequires: meson, gcc-gfortran, gtk4-devel
293 Requires: gtk4
294
295 %description
296 A fast, beautiful disk space analyzer built with Fortran and GTK4.
297
298 %prep
299 %setup -q
300
301 %build
302 meson setup build
303 meson compile -C build
304
305 %install
306 install -Dm755 build/sniffly %{buildroot}%{_bindir}/sniffly
307 install -Dm644 assets/sniffly.desktop %{buildroot}%{_datadir}/applications/sniffly.desktop
308 install -Dm644 assets/sniffly.png %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/sniffly.png
309
310 %files
311 %{_bindir}/sniffly
312 %{_datadir}/applications/sniffly.desktop
313 %{_datadir}/icons/hicolor/256x256/apps/sniffly.png
314
315 %changelog
316 * Mon Jan 01 2024 Your Name <your@email.com> - 0.1.0-1
317 - Initial release
318 EOF
319
320 # Create source tarball
321 tar czf ~/rpmbuild/SOURCES/sniffly-0.1.0.tar.gz ../sniffly/
322
323 # Build RPM
324 rpmbuild -ba ~/rpmbuild/SPECS/sniffly.spec
325 ```
326
327 ---
328
329 ## Automated Packaging with CI/CD
330
331 ### GitHub Actions Example
332
333 Create `.github/workflows/release.yml`:
334
335 ```yaml
336 name: Release Build
337
338 on:
339 push:
340 tags:
341 - 'v*'
342
343 jobs:
344 build-macos:
345 runs-on: macos-latest
346 steps:
347 - uses: actions/checkout@v3
348 - name: Install dependencies
349 run: |
350 brew install meson gtk4 gcc
351 - name: Build
352 run: |
353 meson setup build
354 meson compile -C build
355 - name: Create DMG
356 run: |
357 # Add DMG creation steps here
358 - name: Upload Release Asset
359 uses: actions/upload-artifact@v3
360 with:
361 name: Sniffly-macOS.dmg
362 path: Sniffly-*.dmg
363
364 build-linux:
365 runs-on: ubuntu-latest
366 steps:
367 - uses: actions/checkout@v3
368 - name: Install dependencies
369 run: |
370 sudo apt-get update
371 sudo apt-get install -y meson gfortran libgtk-4-dev
372 - name: Build
373 run: |
374 meson setup build
375 meson compile -C build
376 - name: Create AppImage
377 run: |
378 # Add AppImage creation steps here
379 - name: Upload Release Asset
380 uses: actions/upload-artifact@v3
381 with:
382 name: Sniffly-Linux-x86_64.AppImage
383 path: Sniffly-*.AppImage
384 ```
385
386 ---
387
388 ## Quick Start Summary
389
390 ### macOS
391 1. Build the app: `meson compile -C build`
392 2. Create .app bundle structure
393 3. Use `dylibbundler` to bundle GTK4 libraries
394 4. Create .dmg with `hdiutil`
395 5. (Optional) Code sign and notarize
396
397 **Result**: `Sniffly-0.1.0-macOS.dmg`
398
399 ### Linux
400 1. Build the app: `meson compile -C build`
401 2. Create AppDir structure
402 3. Use `appimagetool` to create AppImage
403 4. Or create .deb/.rpm for specific distros
404
405 **Result**: `Sniffly-0.1.0-x86_64.AppImage` or `.deb`/`.rpm`
406
407 ---
408
409 ## Distribution Checklist
410
411 - [ ] Create application icon (1024x1024 PNG)
412 - [ ] Create .desktop file for Linux
413 - [ ] Test on clean system without development tools
414 - [ ] Document system requirements (GTK4, etc.)
415 - [ ] Add installation instructions to README
416 - [ ] Create GitHub releases page
417 - [ ] Consider Homebrew formula for macOS
418 - [ ] Consider Flatpak for Linux (alternative to AppImage)
419
420 ---
421
422 ## Notes on GTK4 Dependencies
423
424 Sniffly requires GTK4 at runtime. You have three options:
425
426 1. **User installation**: Require users to install GTK4 (`brew install gtk4` on macOS, `apt install libgtk-4-1` on Debian)
427 2. **Bundle libraries**: Include GTK4 in your app bundle (increases size ~100MB but works anywhere)
428 3. **Hybrid**: Bundle on macOS, rely on system packages on Linux
429
430 For the best user experience, option 2 (bundling) is recommended for macOS, while option 1 (system packages) works well for Linux where GTK4 is commonly available.
431
432 ---
433
434 ## Future Improvements
435
436 - **Flatpak**: Cross-distro sandboxed app (like macOS .app)
437 - **Snap**: Alternative Linux universal package
438 - **Homebrew Cask**: Easy installation on macOS (`brew install --cask sniffly`)
439 - **AUR Package**: For Arch Linux users
440 - **Windows**: Cross-compile with MinGW-w64 (if desired)