#!/bin/bash # Builds audiotee, signs it with a stable identity, and installs it to a # fixed path. Both steps matter for Core Audio process tap / microphone TCC # permissions to survive across rebuilds — see CONTEXT.md §6.2 and §8: # # - SwiftPM ad-hoc-signs debug/release builds by default. Ad-hoc signatures # are keyed off the binary's own hash, so every rebuild looks like a new # app to TCC and permission has to be re-granted. # - TCC has also been observed keying on binary path, so builds are installed # to a fixed location outside .build/. # # Usage: # scripts/build-signed.sh # build, sign, install to ~/bin # scripts/build-signed.sh --reset-tcc # also reset TCC state for this # # binary, useful after changing # # Info.plist or the signing identity # # Requires a self-signed code-signing certificate in your keychain. If you # don't have one yet: # 1. Open Keychain Access # 2. Keychain Access menu > Certificate Assistant > Create a Certificate... # 3. Name it (e.g. "audiotee-dev"), Identity Type: Self Signed Root, # Certificate Type: Code Signing # 4. Create it, then in Keychain Access double-click it, expand "Trust", # and set "Code Signing" to "Always Trust" # Override auto-detection with: AUDIOTEE_SIGNING_IDENTITY="Your Cert Name" set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" BUNDLE_ID="com.stephanetailland.audiotee" INSTALL_DIR="${AUDIOTEE_INSTALL_DIR:-$HOME/bin}" INSTALL_PATH="$INSTALL_DIR/audiotee" RESET_TCC=false for arg in "$@"; do case "$arg" in --reset-tcc) RESET_TCC=true ;; *) echo "Unknown argument: $arg" >&2 exit 1 ;; esac done if [[ -n "${AUDIOTEE_SIGNING_IDENTITY:-}" ]]; then IDENTITY="$AUDIOTEE_SIGNING_IDENTITY" else # Real identity lines look like ` 1) "Name"`; the "N valid # identities found" summary line has no ")" and must not be counted. IDENTITY_LINES="$(security find-identity -v -p codesigning | grep '^ *[0-9]*)' || true)" IDENTITY_COUNT="$(printf '%s\n' "$IDENTITY_LINES" | grep -c . || true)" if [[ "$IDENTITY_COUNT" -eq 0 ]]; then echo "Error: no code-signing identity found in your keychain." >&2 echo "See the comment at the top of this script for how to create one." >&2 exit 1 elif [[ "$IDENTITY_COUNT" -gt 1 ]]; then echo "Error: multiple code-signing identities found. Set AUDIOTEE_SIGNING_IDENTITY" >&2 echo "to the one to use:" >&2 echo "$IDENTITY_LINES" >&2 exit 1 fi IDENTITY="$(printf '%s\n' "$IDENTITY_LINES" | sed -n 's/.*"\(.*\)"/\1/p')" fi echo "Building (release)..." swift build -c release BUILT_BINARY="$REPO_ROOT/.build/release/audiotee" echo "Signing with identity: $IDENTITY" codesign --force --sign "$IDENTITY" --identifier "$BUNDLE_ID" "$BUILT_BINARY" mkdir -p "$INSTALL_DIR" cp "$BUILT_BINARY" "$INSTALL_PATH" echo "Installed to $INSTALL_PATH" codesign -dvvv "$INSTALL_PATH" if [[ "$RESET_TCC" == true ]]; then echo "Resetting TCC state for $BUNDLE_ID..." tccutil reset SystemAudioCaptureRequests "$BUNDLE_ID" || true tccutil reset Microphone "$BUNDLE_ID" || true fi