132 lines
3.8 KiB
Bash
Executable File
132 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Build script for Path Juggler
|
|
# Creates a standalone macOS .app bundle using Nuitka
|
|
# Uses PySide6 (Qt) for GUI - fully bundleable, no system dependencies
|
|
#
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
APP_NAME="Path Juggler"
|
|
BUNDLE_ID="com.pathjuggler.app"
|
|
VENV_DIR="$SCRIPT_DIR/.build_venv"
|
|
DIST_DIR="$SCRIPT_DIR/dist"
|
|
|
|
echo "=== Path Juggler - Build Script ==="
|
|
echo "Using Nuitka + PySide6 for a fully self-contained build"
|
|
echo ""
|
|
|
|
# Check for uv
|
|
if ! command -v uv &> /dev/null; then
|
|
echo "Error: uv is required but not found"
|
|
echo ""
|
|
echo "Install uv with:"
|
|
echo " curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
echo " or: brew install uv"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using uv version: $(uv --version)"
|
|
echo ""
|
|
|
|
# Create virtual environment with Python 3.11 (good compatibility)
|
|
echo "=== Creating virtual environment ==="
|
|
if [ -d "$VENV_DIR" ]; then
|
|
echo "Removing existing build environment..."
|
|
rm -rf "$VENV_DIR"
|
|
fi
|
|
|
|
uv venv "$VENV_DIR" --python 3.11
|
|
source "$VENV_DIR/bin/activate"
|
|
|
|
PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
|
echo "Python version: $PYTHON_VERSION"
|
|
|
|
# Install build dependencies
|
|
echo ""
|
|
echo "=== Installing build dependencies ==="
|
|
uv pip install --quiet PySide6 watchdog nuitka ordered-set zstandard
|
|
|
|
echo "Installed packages:"
|
|
uv pip list | grep -iE "(pyside6|watchdog|nuitka)" || true
|
|
|
|
# Build with Nuitka
|
|
echo ""
|
|
echo "=== Building application with Nuitka ==="
|
|
|
|
# Clean previous build
|
|
rm -rf "$DIST_DIR/$APP_NAME.app" 2>/dev/null || true
|
|
rm -rf "$DIST_DIR"/*.build 2>/dev/null || true
|
|
rm -rf "$DIST_DIR"/*.dist 2>/dev/null || true
|
|
|
|
python -m nuitka \
|
|
--standalone \
|
|
--macos-create-app-bundle \
|
|
--macos-app-name="$APP_NAME" \
|
|
--product-name="$APP_NAME" \
|
|
--product-version="1.0.0" \
|
|
--company-name="PathJuggler" \
|
|
--file-description="File organization utility" \
|
|
--enable-plugin=pyside6 \
|
|
--include-module=watchdog.observers \
|
|
--include-module=watchdog.observers.fsevents \
|
|
--include-module=watchdog.events \
|
|
--output-dir="$DIST_DIR" \
|
|
--remove-output \
|
|
--assume-yes-for-downloads \
|
|
path_juggler_gui.py
|
|
|
|
# Find the generated app
|
|
APP_PATH="$DIST_DIR/path_juggler_gui.app"
|
|
FINAL_APP_PATH="$DIST_DIR/$APP_NAME.app"
|
|
|
|
if [ -d "$APP_PATH" ]; then
|
|
# Rename to proper name
|
|
rm -rf "$FINAL_APP_PATH" 2>/dev/null || true
|
|
mv "$APP_PATH" "$FINAL_APP_PATH"
|
|
|
|
# Update Info.plist with proper bundle ID
|
|
PLIST="$FINAL_APP_PATH/Contents/Info.plist"
|
|
if [ -f "$PLIST" ]; then
|
|
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$PLIST" 2>/dev/null || true
|
|
/usr/libexec/PlistBuddy -c "Set :CFBundleName $APP_NAME" "$PLIST" 2>/dev/null || true
|
|
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $APP_NAME" "$PLIST" 2>/dev/null || true
|
|
fi
|
|
|
|
# Sign the app
|
|
echo ""
|
|
echo "=== Signing application (ad-hoc) ==="
|
|
codesign --remove-signature "$FINAL_APP_PATH" 2>/dev/null || true
|
|
codesign --force --deep --sign - "$FINAL_APP_PATH"
|
|
|
|
echo "Signature applied"
|
|
codesign -dv "$FINAL_APP_PATH" 2>&1 | head -5
|
|
else
|
|
echo "Error: App bundle not found"
|
|
echo "Looking for: $APP_PATH"
|
|
ls -la "$DIST_DIR/"
|
|
exit 1
|
|
fi
|
|
|
|
# Clean up
|
|
echo ""
|
|
echo "=== Cleaning up ==="
|
|
rm -rf "$DIST_DIR"/*.build 2>/dev/null || true
|
|
rm -rf "$DIST_DIR"/*.dist 2>/dev/null || true
|
|
rm -rf "$DIST_DIR"/*.onefile-build 2>/dev/null || true
|
|
deactivate
|
|
rm -rf "$VENV_DIR"
|
|
|
|
echo ""
|
|
echo "=== Build complete ==="
|
|
echo ""
|
|
echo "Application created at:"
|
|
echo " $FINAL_APP_PATH"
|
|
echo ""
|
|
echo "To install, drag the app to your Applications folder:"
|
|
echo " open \"$DIST_DIR\""
|
|
echo ""
|
|
echo "Note: On first launch, you may need to right-click and select 'Open'"
|
|
echo "to bypass Gatekeeper since this is a self-signed app."
|