Building Binaries¶
Guide for building standalone binaries of Devo CLI using PyInstaller.
Overview¶
Devo CLI can be distributed as standalone binaries that don't require Python installation. This is done using PyInstaller to bundle Python, dependencies, and the CLI into a single executable.
Prerequisites¶
- Python 3.12+
- Virtual environment activated
- Development dependencies installed
# Setup development environment (see Development Setup for details)
make venv && source venv/bin/activate && make install
Quick Build¶
Build for Current Platform¶
This creates a binary in dist/ directory:
- Linux:
dist/devo(single file) - macOS:
dist/devo/(directory with executable) - Windows:
dist/devo/(directory with executable)
Build with Platform-Specific Naming¶
Creates binaries with platform identifiers:
- Linux AMD64:
dist/devo(single file) - macOS Intel:
release/vX.Y.Z/devo-darwin-amd64.tar.gz(tarball) - macOS Apple Silicon:
release/vX.Y.Z/devo-darwin-arm64.tar.gz(tarball) - Windows:
release/vX.Y.Z/devo-windows-amd64.zip(zip archive)
Manual Build¶
Using PyInstaller Directly¶
# Activate virtual environment
source venv/bin/activate
# Build binary
pyinstaller --onefile \
--name devo \
--add-data "cli_tool:cli_tool" \
cli_tool/cli.py
Custom Build Options¶
# With console window (default)
pyinstaller --onefile --name devo cli_tool/cli.py
# Without console window (Windows GUI)
pyinstaller --onefile --noconsole --name devo cli_tool/cli.py
# With icon
pyinstaller --onefile --icon=icon.ico --name devo cli_tool/cli.py
# With additional data files
pyinstaller --onefile \
--add-data "config:config" \
--add-data "templates:templates" \
--name devo cli_tool/cli.py
Platform-Specific Builds¶
Output: dist/devo/devo (directory with executable and dependencies)
Note
macOS uses onedir mode (directory with executable) for faster startup. Linux uses onefile mode (single binary) for easier distribution.
Cross-Platform Building¶
PyInstaller cannot cross-compile. To build for multiple platforms:
- Use CI/CD: GitHub Actions builds for all platforms automatically
- Use VMs: Build on each platform separately
- Use Docker: Build Linux binaries in containers
GitHub Actions (Recommended)¶
The project includes GitHub Actions workflow that builds for all platforms:
# .github/workflows/release.yml
- Build on ubuntu-latest → Linux binary
- Build on macos-latest → macOS Intel binary
- Build on macos-14 → macOS ARM binary
- Build on windows-latest → Windows binary
See CI/CD Overview for details.
Build Configuration¶
PyInstaller Spec File¶
For advanced configuration, create a .spec file:
# Generate spec file
pyi-makespec --onefile --name devo cli_tool/cli.py
# Edit devo.spec as needed
# Build from spec
pyinstaller devo.spec
Example devo.spec:
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['cli_tool/cli.py'],
pathex=[],
binaries=[],
datas=[('cli_tool', 'cli_tool')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='devo',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
Optimization¶
Reduce Binary Size¶
# Use UPX compression
pyinstaller --onefile --upx-dir=/path/to/upx cli_tool/cli.py
# Exclude unnecessary modules
pyinstaller --onefile \
--exclude-module tkinter \
--exclude-module matplotlib \
cli_tool/cli.py
# Strip debug symbols (Linux/macOS)
strip dist/devo
Improve Startup Time¶
# Use --onedir instead of --onefile (faster startup, multiple files)
pyinstaller --onedir cli_tool/cli.py
# Note: macOS and Windows builds use onedir by default for performance
# Linux uses onefile for easier distribution
Performance comparison:
- onefile (Linux): Single binary, 2-5s startup overhead due to extraction
- onedir (macOS/Windows): Directory with files, ~0.1-0.3s startup (no extraction)
Testing Binaries¶
Basic Tests¶
Comprehensive Tests¶
# Run test suite against binary
export DEVO_BINARY=./dist/devo
pytest tests/
# Manual testing
./dist/devo commit --help
./dist/devo code-reviewer --help
./dist/devo config show
Distribution¶
Create Release Package¶
Generate Checksums¶
Upload to GitHub Releases¶
Automated via GitHub Actions, or manually:
# Using GitHub CLI
gh release create v1.0.0 \
dist/devo-linux-amd64 \
dist/devo-darwin-amd64 \
dist/devo-darwin-arm64 \
dist/devo-windows-amd64.exe \
dist/SHA256SUMS
Troubleshooting¶
Import Errors¶
If binary fails with import errors:
# Add hidden imports
pyinstaller --onefile \
--hidden-import=pkg_resources \
--hidden-import=boto3 \
cli_tool/cli.py
Missing Data Files¶
If binary can't find data files:
# Add data files
pyinstaller --onefile \
--add-data "cli_tool:cli_tool" \
--add-data "config:config" \
cli_tool/cli.py
Large Binary Size¶
# Check what's included
pyinstaller --onefile --log-level=DEBUG cli_tool/cli.py
# Exclude unnecessary modules
pyinstaller --onefile \
--exclude-module tkinter \
--exclude-module test \
cli_tool/cli.py
Antivirus False Positives¶
Some antivirus software flags PyInstaller binaries:
- Submit binary to antivirus vendors for whitelisting
- Sign binary with code signing certificate
- Build from source instead of using binary
Code Signing¶
Makefile Targets¶
Available make targets for building:
make build-binary # Build for current platform
make build-all # Build with platform naming
make clean # Remove build artifacts
make dist-clean # Remove dist directory
See Also¶
- Development Setup - Development environment setup
- CI/CD Overview - Automated builds
- Contributing - Contributing guidelines