#!/bin/bash set -euo pipefail # Xcode Run Script Phase (Pre) for Archive obfuscation. # Add this as an early Build Phase (before Compile Sources). # It only runs on Archive + Release, and obfuscates source in-place, # then the post phase restores original files from backup. if [[ "${ACTION:-}" != "install" || "${CONFIGURATION:-}" != "Release" ]]; then echo "[obf-pre] Skip: ACTION=${ACTION:-}, CONFIGURATION=${CONFIGURATION:-}" exit 0 fi # Allow external driver (CI/script) to opt-out of running this phase if [[ "${SKIP_OBF_PHASE:-}" = "1" ]]; then echo "[obf-pre] SKIP_OBF_PHASE=1 set; skipping pre-archive obfuscation phase." exit 0 fi ROOT="${SRCROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}" DERIVED_DIR="${DERIVED_FILE_DIR:-/tmp}" STAMP="$(date +%Y%m%d_%H%M%S)" BACKUP_DIR="${DERIVED_DIR}/rd_obf_backup_${STAMP}" MARKER_FILE="${DERIVED_DIR}/rd_obf_marker_${TARGET_NAME:-app}.env" MAP_DIR="${ROOT}/obfuscation_maps" MAP_PATH="${MAP_DIR}/${TARGET_NAME:-app}_${STAMP}.json" METHOD_MAP_PATH="${MAP_DIR}/method_map_${TARGET_NAME:-app}_${STAMP}.json" PRE_SUCCESS=0 restore_from_backup_dir() { local backup_dir="$1" if [[ ! -d "${backup_dir}" ]]; then return 0 fi while IFS= read -r file; do rel="${file#${backup_dir}/}" mkdir -p "$(dirname "${ROOT}/$rel")" cp -f "$file" "${ROOT}/$rel" done < <(find "${backup_dir}" -type f) rm -rf "${backup_dir}" } restore_stale_backup_if_needed() { if [[ ! -f "${MARKER_FILE}" ]]; then return 0 fi echo "[obf-pre] Detected stale marker from previous build, restoring workspace first..." # shellcheck disable=SC1090 source "${MARKER_FILE}" if [[ -n "${BACKUP_DIR:-}" && -n "${ROOT:-}" ]]; then restore_from_backup_dir "${BACKUP_DIR}" fi rm -f "${MARKER_FILE}" } restore_on_error() { local exit_code=$? if [[ ${PRE_SUCCESS} -eq 1 ]]; then return 0 fi echo "[obf-pre] Failed (exit=${exit_code}), restoring source files from backup..." restore_from_backup_dir "${BACKUP_DIR}" rm -f "${MARKER_FILE}" echo "[obf-pre] Restore complete." exit ${exit_code} } # Run repository self-check to ensure no residual obfuscated tokens remain. trap restore_on_error EXIT INT TERM cd "${ROOT}" restore_stale_backup_if_needed echo "[obf-pre] Running repository self-check" # Self-check must run before creating backups to avoid restoring a pre-check backup on failure. bash "${ROOT}/AutoPacking/obfuscation/scripts/obfuscation_self_check.sh" "${ROOT}" echo "[obf-pre] Generating dylib whitelist with HMAC" python3 "${ROOT}/AutoPacking/obfuscation/generate_image_whitelist.py" mkdir -p "${BACKUP_DIR}" "${MAP_DIR}" echo "[obf-pre] Backing up source files to ${BACKUP_DIR}" # Backup all source files that may be touched by obfuscation. Keep this for rollback safety. while IFS= read -r file; do rel="${file#./}" mkdir -p "${BACKUP_DIR}/$(dirname "$rel")" cp "$file" "${BACKUP_DIR}/$rel" done < <( find . \ \( -path './Pods' -o -path './Pods/*' -o -path './.git' -o -path './.git/*' -o -path './build_output' -o -path './build_output/*' -o -path './DerivedData' -o -path './DerivedData/*' -o -path './readoorTests' -o -path './readoorTests/*' -o -name '*.framework' -o -name '*.xcframework' \) -prune -o \ -type f \( -name '*.swift' -o -name '*.m' -o -name '*.mm' -o -name '*.h' -o -name '*.pch' \) -print ) echo "[obf-pre] Running obfuscation in archive mode (auto apply + type/method maps)..." OBF_TIMESTAMP="${STAMP}" python3 "${ROOT}/AutoPacking/obfuscation/obfuscate_symbols.py" --archive-mode echo "BACKUP_DIR=${BACKUP_DIR}" > "${MARKER_FILE}" echo "ROOT=${ROOT}" >> "${MARKER_FILE}" PRE_SUCCESS=1 trap - EXIT INT TERM echo "[obf-pre] Done. map=${MAP_PATH} method_map=${METHOD_MAP_PATH} marker=${MARKER_FILE}"