Packaging a Castella App¶
This guide covers packaging Castella applications for distribution.
Desktop Applications¶
ux¶
ux is a Rust-based Python app bundler that leverages uv to create single distributable executables. End users don't need Python or uv installed to run the bundled app.
Features:
- Single executable distribution
- Cross-platform compilation
- macOS app bundles with code signing and notarization
- DMG packaging for macOS distribution
Installation:
Basic usage:
Configuration in pyproject.toml:
[tool.ux]
entry = "your_app"
include = ["assets/"]
[tool.ux.macos]
icon = "assets/icon.png"
bundle_identifier = "com.example.yourapp"
bundle_name = "Your App"
macOS app bundle with code signing:
# Create signed .app bundle
ux bundle --format app --codesign --output ./dist/
# Create signed .app and DMG
ux bundle --format app --codesign --dmg --output ./dist/
# With notarization (for distribution)
ux bundle --format app --codesign --notarize --dmg --output ./dist/
Cross-compilation:
# Build for Linux
ux bundle --target linux-x86_64 --output ./dist/
# Build for Windows
ux bundle --target windows-x86_64 --output ./dist/
Supported targets:
| Target | PyPI | Notes |
|---|---|---|
| darwin-x86_64 | Yes | Intel Mac |
| darwin-aarch64 | Yes | Apple Silicon Mac |
| linux-x86_64 | Yes | |
| linux-aarch64 | GitHub | ARM64 Linux |
| windows-x86_64 | Yes |
PyInstaller¶
PyInstaller packages your app as a standalone executable:
# With uv (recommended)
uv add --dev pyinstaller
uv run pyinstaller --onefile --windowed your_app.py
# With pip
pip install pyinstaller
pyinstaller --onefile --windowed your_app.py
Options:
--onefile: Create a single executable file--windowed: Hide the console window (for GUI apps)--name: Set the output executable name
Example with custom options:
Nuitka¶
Nuitka compiles Python to native code for better performance:
# With uv (recommended)
uv add --dev nuitka
uv run nuitka --standalone --onefile your_app.py
# With pip
pip install nuitka
nuitka --standalone --onefile your_app.py
For GUI applications:
# With uv
uv run nuitka --standalone --onefile --disable-console your_app.py
# With pip
nuitka --standalone --onefile --disable-console your_app.py
Platform-Specific Notes¶
Windows¶
- Include SDL2/GLFW DLLs if using those backends
- Set
PYSDL2_DLL_PATHenvironment variable if needed - Consider code signing for distribution
SDL2 DLL handling:
macOS¶
For proper macOS app bundles:
# Using PyInstaller
pyinstaller --onefile --windowed \
--osx-bundle-identifier com.yourname.yourapp \
your_app.py
Notes:
- Sign your app for distribution
- Create a proper
.appbundle - Test on different macOS versions
Linux¶
AppImage (recommended for distribution):
- Build with PyInstaller
- Package as AppImage for portable distribution
System packages:
Ensure system libraries are available:
iOS Applications¶
Castella iOS apps are packaged using BeeWare Briefcase.
Prerequisites¶
- macOS with Xcode
- Rust toolchain with iOS targets
- Briefcase:
pip install briefcase
Quick Start¶
Use the unified build script:
# Build and run on iOS Simulator
./tools/build_ios.sh examples/ios_test_app
# With auto-download of dependencies
AUTO_DOWNLOAD_DEPS=1 ./tools/build_ios.sh examples/ios_test_app
Manual Process¶
cd your_ios_app
# Create iOS project
uvx briefcase create iOS
# Build
uvx briefcase build iOS
# Run on Simulator
uvx briefcase run iOS
Project Structure¶
your_ios_app/
├── pyproject.toml # Briefcase configuration
├── src/
│ └── your_app/
│ ├── __init__.py # Entry point
│ ├── __main__.py # Required for iOS
│ └── app.py # Your Castella app
└── build_ios.sh # Optional convenience script
Dependencies¶
iOS requires pre-built native libraries. Download them:
# Auto-download during build
AUTO_DOWNLOAD_DEPS=1 ./tools/build_ios.sh your_app
# Or download manually
./tools/download_ios_deps.sh
App Store Submission¶
Not Yet Tested
App Store submission has not been tested. Physical device deployment requires an Apple Developer account for code signing.
For more details, see iOS Documentation.
Web Deployment¶
For PyScript/Pyodide web applications, see Getting Started - Web Browsers.
Basic Web Deployment¶
- Create your HTML file with PyScript setup
- Include your Python source
- Deploy to any static file server
Example project structure:
Hosting Options¶
- GitHub Pages (free)
- Netlify (free tier)
- Any static file hosting
Handling Dependencies¶
Data Files¶
Include data files (images, fonts, etc.):
PyInstaller:
In your code:
import sys
import os
if getattr(sys, 'frozen', False):
# Running as compiled
base_path = sys._MEIPASS
else:
# Running as script
base_path = os.path.dirname(__file__)
asset_path = os.path.join(base_path, 'assets', 'image.png')
Hidden Imports¶
If PyInstaller misses some imports:
Best Practices¶
-
Test the packaged app on a clean system without Python installed
-
Include all backends you might use, or specify the exact one
-
Document system requirements for your users
-
Version your releases with clear changelogs
-
Consider installer tools like NSIS (Windows) or create-dmg (macOS) for professional distribution