Packaging & Distribution
ChimpStackr uses PyInstaller to create native packages for all platforms. Builds are automated via GitHub Actions but can also be done locally.
Quick Reference
| Platform | Build command | Output |
|---|---|---|
| macOS | ./scripts/build_macos.sh |
dist/ChimpStackr-macOS.dmg |
| Windows | .\scripts\build_windows.ps1 |
dist/ChimpStackr-Windows.zip |
| Linux (AppImage) | ./scripts/build_linux.sh |
dist/ChimpStackr-Linux-x86_64.AppImage |
| Linux (Flatpak) | ./scripts/build_flatpak.sh |
Flatpak install (local) |
Prerequisites
- Python 3.9-3.13
- All dependencies from
requirements.txt - PyInstaller (
pip install pyinstaller) - Platform-specific:
- macOS: Xcode command line tools (
xcode-select --install) - Windows: Inno Setup 6 (optional, for installer)
- Linux: FUSE (
sudo apt install libfuse2)
- macOS: Xcode command line tools (
Local Build
# Quick build (all platforms)
pip install pyinstaller
pyinstaller chimpstackr.spec --noconfirm
# Output:
# dist/chimpstackr/ -- directory with both executables
# dist/chimpstackr/chimpstackr -- GUI executable
# dist/chimpstackr/chimpstackr-cli -- CLI executable
# dist/ChimpStackr.app/ -- macOS .app bundle (macOS only)
Verify the build
# Test CLI
dist/chimpstackr/chimpstackr-cli --help
dist/chimpstackr/chimpstackr-cli -i /path/to/images/*.jpg -o /tmp/test.jpg
# Test GUI
open dist/ChimpStackr.app # macOS
dist/chimpstackr/chimpstackr # Linux
dist\chimpstackr\chimpstackr.exe # Windows
CI/CD (GitHub Actions)
The build workflow (.github/workflows/build.yml) triggers on:
- Tag push (
v*): builds all platforms and creates a draft GitHub Release - Manual dispatch: from the Actions tab, with optional release creation
Triggering a release
# Tag and push
git tag v0.1.0
git push origin v0.1.0
This runs:
- Test on all 3 platforms (Python 3.11)
- Build macOS – PyInstaller, optional code signing, DMG creation
- Build Windows – PyInstaller, ZIP archive
- Build Linux (AppImage) – PyInstaller, AppImage creation
- Build Linux (Flatpak) – flatpak-builder,
.flatpakbundle - Release – GitHub Release with all artifacts
GitHub Secrets (optional)
For macOS code signing and notarization, set these repository secrets:
| Secret | Description |
|---|---|
MACOS_CODESIGN_IDENTITY |
Developer ID Application: Your Name (TEAMID) |
APPLE_ID |
Your Apple ID email |
APPLE_TEAM_ID |
Apple Developer Team ID |
APPLE_APP_PASSWORD |
App-specific password from appleid.apple.com |
Without these, the macOS build still works but produces an unsigned DMG (users will need to right-click > Open on first launch).
Architecture
Dual executables
The .spec file creates two executables from shared libraries:
- chimpstackr (GUI):
console=False– no terminal window - chimpstackr-cli (CLI):
console=True– headless terminal mode
Both share the same _internal/ directory with all dependencies, so they’re only bundled once.
macOS .app bundle
On macOS, PyInstaller also creates a ChimpStackr.app bundle with:
- Proper
Info.plist(bundle ID, version, dark mode support, file associations) .icnsicon- Both executables in
Contents/MacOS/
Linux AppImage
The build script wraps the PyInstaller output in an AppImage:
AppRunscript detects--cliflag or binary name to dispatch to GUI or CLI- Desktop entry and icons included for desktop integration
- Works on most distros with glibc 2.31+
Linux Flatpak
Flatpak packaging files are in packaging/flatpak/. The Flatpak build uses the KDE 6.9 runtime with the PySide BaseApp (provides PySide6 bindings linked against the runtime’s Qt6).
App ID: io.github.noah_peeters.ChimpStackr
Files:
| File | Purpose |
|---|---|
packaging/flatpak/io.github.noah_peeters.ChimpStackr.yml |
Flatpak manifest |
packaging/flatpak/io.github.noah_peeters.ChimpStackr.desktop |
Desktop entry |
packaging/flatpak/io.github.noah_peeters.ChimpStackr.metainfo.xml |
AppStream metadata for software centers |
Local build:
# Install prerequisites
sudo apt install flatpak flatpak-builder
flatpak install flathub org.kde.Platform//6.9 org.kde.Sdk//6.9 io.qt.PySide.BaseApp//6.9
# Build and install locally
./scripts/build_flatpak.sh
# Run
flatpak run io.github.noah_peeters.ChimpStackr
# Create a redistributable .flatpak bundle
./scripts/build_flatpak.sh --bundle
Native dependencies (built from source in the manifest):
- FFTW3 (float + double precision) – required by pyFFTW
- LibRaw – required by rawpy
The CI workflow uses flatpak/flatpak-github-actions with the ghcr.io/flathub-infra/flatpak-github-actions:kde-6.9 container image to build and produce a .flatpak bundle attached to each release.
Heavy dependencies
These need special handling in the .spec file:
| Dependency | Issue | Solution |
|---|---|---|
| numba/llvmlite | Native JIT compiler libs often missed | collect_all('numba') |
| pyfftw | FFTW3 C libraries | collect_all('pyfftw') |
| rawpy | libraw native lib | collect_all('rawpy') |
| imageio | Package metadata needed at runtime | collect_all('imageio') |
| scipy | Many submodules with C extensions | collect_all('scipy') |
macOS entitlements
The packaging/entitlements.plist grants these hardened runtime exceptions:
allow-jit– required for Numba JIT compilationallow-unsigned-executable-memory– required for NumPy/SciPy C extensionsdisable-library-validation– required for loading bundled.dylibfiles
Troubleshooting
“No module named X” at runtime
Add it to hiddenimports or use collect_all('X') in the .spec file, rebuild.
macOS “app is damaged” / “unidentified developer”
Unsigned builds trigger Gatekeeper. Users can: right-click > Open, or run:
xattr -cr /Applications/ChimpStackr.app
Linux AppImage won’t run
Install FUSE: sudo apt install libfuse2
Windows antivirus flags the exe
This is common with PyInstaller. Options:
- Sign the exe with a code-signing certificate
- Submit to antivirus vendors as false positive
- Don’t use UPX compression (already disabled in our spec)
Build is too large
The ~450MB uncompressed size is normal for NumPy + SciPy + Numba + PySide6. The DMG compresses to ~200MB. To reduce:
- Use
--exclude-modulefor unused scipy submodules - Consider Nuitka for 20-30% smaller binaries (future optimization)