#!/bin/bash set -e APP="target/release/plc-touch.app" # Load env vars from .env if it exists if [ -f .env ]; then set -a source .env set +a fi # These must be set in .env or as env vars: # CODESIGN_IDENTITY="Apple Development: Your Name (XXXXXXXXXX)" # BUNDLE_ID="com.yourcompany.plc-touch" # TEAM_ID="XXXXXXXXXX" # # For release builds, also set: # DEVELOPER_ID="Developer ID Application: Your Name (XXXXXXXXXX)" # APPLE_ID="your@email.com" # NOTARIZE_PASSWORD="app-specific-password" BUNDLE_ID="${BUNDLE_ID:-com.example.plc-touch}" TEAM_ID="${TEAM_ID:-XXXXXXXXXX}" MODE="${1:-dev}" case "$MODE" in dev) IDENTITY="${CODESIGN_IDENTITY:?Set CODESIGN_IDENTITY in .env}" ;; release) IDENTITY="${DEVELOPER_ID:?Set DEVELOPER_ID in .env for release builds}" ;; *) echo "Usage: ./build.sh [dev|release]" echo " dev — Development build with provisioning profile (default)" echo " release — Developer ID build with notarization for distribution" exit 1 ;; esac echo "Building plc-touch ($MODE)..." KEYCHAIN_ACCESS_GROUP="${TEAM_ID}.${BUNDLE_ID}" cargo build --release # Create .app bundle rm -rf "$APP" mkdir -p "$APP/Contents/MacOS" cp target/release/plc-touch "$APP/Contents/MacOS/plc-touch" # Embed provisioning profile if [ "$MODE" = "dev" ] && [ -f embedded.provisionprofile ]; then cp embedded.provisionprofile "$APP/Contents/embedded.provisionprofile" elif [ "$MODE" = "release" ] && [ -f release.provisionprofile ]; then cp release.provisionprofile "$APP/Contents/embedded.provisionprofile" fi cat > "$APP/Contents/Info.plist" << EOF CFBundleIdentifier ${BUNDLE_ID} CFBundleName plc-touch CFBundleExecutable plc-touch CFBundleVersion 0.1.0 CFBundleShortVersionString 0.1.0 CFBundlePackageType APPL LSMinimumSystemVersion 13.0 EOF # Generate entitlements ENTITLEMENTS_FILE=$(mktemp) if [ "$MODE" = "release" ]; then # Developer ID with provisioning profile: includes application-identifier + keychain-access-groups cat > "$ENTITLEMENTS_FILE" << EOF com.apple.application-identifier ${TEAM_ID}.${BUNDLE_ID} keychain-access-groups ${TEAM_ID}.* EOF else # Dev: needs application-identifier for provisioning profile cat > "$ENTITLEMENTS_FILE" << EOF com.apple.application-identifier ${TEAM_ID}.${BUNDLE_ID} keychain-access-groups ${TEAM_ID}.* EOF fi if [ "$MODE" = "release" ]; then # Release: Developer ID signing with hardened runtime (required for notarization) codesign --force --sign "$IDENTITY" \ --options runtime \ --timestamp \ --entitlements "$ENTITLEMENTS_FILE" \ "$APP" rm -f "$ENTITLEMENTS_FILE" echo "✓ Signed with Developer ID" # Create zip for notarization ZIP="target/release/plc-touch.zip" rm -f "$ZIP" ditto -c -k --keepParent "$APP" "$ZIP" echo "Submitting for notarization..." APPLE_ID_ARG="${APPLE_ID:?Set APPLE_ID in .env for notarization}" PASS_ARG="${NOTARIZE_PASSWORD:?Set NOTARIZE_PASSWORD in .env (app-specific password)}" xcrun notarytool submit "$ZIP" \ --apple-id "$APPLE_ID_ARG" \ --team-id "$TEAM_ID" \ --password "$PASS_ARG" \ --wait # Staple the notarization ticket to the app xcrun stapler staple "$APP" # Re-create zip with stapled app rm -f "$ZIP" ditto -c -k --keepParent "$APP" "$ZIP" echo "" echo "✓ Built, signed, notarized, and stapled" echo " Distribute: $ZIP" echo " Run with: $APP/Contents/MacOS/plc-touch" else # Dev: Apple Development signing codesign --force --sign "$IDENTITY" \ --entitlements "$ENTITLEMENTS_FILE" \ "$APP" rm -f "$ENTITLEMENTS_FILE" echo "" echo "✓ Built and signed (dev)" echo " Run with: $APP/Contents/MacOS/plc-touch" fi