#!/bin/bash # # Assembles build/iPod Contacts and Calendar Sync.app from the SwiftPM executable. # # SwiftPM builds a bare binary; macOS needs it inside a bundle with an # Info.plist before Contacts and EventKit will even prompt for access, so the # bundle is put together here rather than by an Xcode target. # # ./Scripts/bundle.sh # native architecture # ./Scripts/bundle.sh --universal # arm64 + x86_64 # set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" APP_NAME="iPod Contacts and Calendar Sync" BUNDLE_ID="ca.unsupervised.ipodsync" VERSION="2.0" MIN_MACOS="14.0" BUILD_DIR="$ROOT/build" APP="$BUILD_DIR/$APP_NAME.app" # Bash 3.2 ships with macOS and treats an empty array as unbound under # `set -u`, hence the ${ARCH_FLAGS[@]+…} guard at each use site. ARCH_FLAGS=() if [ "${1:-}" = "--universal" ]; then ARCH_FLAGS=(--arch arm64 --arch x86_64) fi echo "Building…" swift build --package-path "$ROOT" -c release ${ARCH_FLAGS[@]+"${ARCH_FLAGS[@]}"} BIN_PATH="$(swift build --package-path "$ROOT" -c release ${ARCH_FLAGS[@]+"${ARCH_FLAGS[@]}"} --show-bin-path)" echo "Assembling $APP_NAME.app…" rm -rf "$APP" mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" cp "$BIN_PATH/iPodSyncApp" "$APP/Contents/MacOS/$APP_NAME" cat > "$APP/Contents/Info.plist" < CFBundleName $APP_NAME CFBundleDisplayName $APP_NAME CFBundleIdentifier $BUNDLE_ID CFBundleVersion $VERSION CFBundleShortVersionString $VERSION CFBundlePackageType APPL CFBundleExecutable $APP_NAME CFBundleInfoDictionaryVersion 6.0 LSMinimumSystemVersion $MIN_MACOS NSHighResolutionCapable NSSupportsAutomaticTermination NSContactsUsageDescription iPod Contacts and Calendar Sync reads your contacts so it can write one iPod-compatible vCard file per person. NSCalendarsFullAccessUsageDescription iPod Contacts and Calendar Sync reads your calendars so it can write iPod-compatible calendar files. NSCalendarsUsageDescription iPod Contacts and Calendar Sync reads your calendars so it can write iPod-compatible calendar files. PLIST echo "" >> "$APP/Contents/Info.plist" # Ad-hoc signature. Contacts and Calendars identify an app by its code # signature, so an unsigned bundle either re-prompts constantly or is denied # outright. This is not a Developer ID signature — Gatekeeper still requires # right-click → Open the first time. echo "Signing (ad-hoc)…" codesign --force --sign - --timestamp=none "$APP" >/dev/null 2>&1 echo "Built $APP"