diff --git a/cspell.json b/cspell.json index 03a577500ee48..c3427217a9476 100644 --- a/cspell.json +++ b/cspell.json @@ -138,6 +138,7 @@ "cocoapods", "Codat", "codegen", + "codesign", "codeshare", "Codice", "Combustors", diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index 36ca04fe34a9b..36d9085e496ed 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -375,6 +375,7 @@ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 498240F82C49553900C15857 /* Run Fullstory Asset Uploader */, 5124824122A346BD617AD428 /* [CP] Embed Pods Frameworks */, + 87174A5CC3CF40CC94B76870 /* Strip Debug Symbols */, D687A4E020266C9380167930 /* [CP] Copy Pods Resources */, 072FAC2AE1685E6A5862C00A /* [CP-User] [RNFB] Core Configuration */, ); @@ -585,6 +586,25 @@ shellPath = /bin/sh; shellScript = "if [ \"$CONFIGURATION\" != \"DebugDevelopment\" ]; then\n \"${PODS_ROOT}/FullStory/tools/FullStoryCommandLine\" \"${CONFIGURATION_BUILD_DIR}/${WRAPPER_NAME}\"\nelse\n echo \"Skipping FullStory Asset Uploader phase for DebugDevelopment scheme.\"\nfi\n"; }; + 87174A5CC3CF40CC94B76870 /* Strip Debug Symbols */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Strip Debug Symbols"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "bash \"${PROJECT_DIR}/../scripts/strip-ios-debug-symbols.sh\"\n"; + }; 5124824122A346BD617AD428 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/scripts/strip-ios-debug-symbols.sh b/scripts/strip-ios-debug-symbols.sh new file mode 100755 index 0000000000000..08baac2d0bfe9 --- /dev/null +++ b/scripts/strip-ios-debug-symbols.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Strips debug symbols from the app binary and embedded frameworks for non-Debug builds. +# This reduces the IPA size by ~22MB without affecting crash symbolication, because Xcode +# generates dSYMs from the unstripped binary before this phase runs. +# +# Expected Xcode environment variables: +# CONFIGURATION, BUILT_PRODUCTS_DIR, EXECUTABLE_FOLDER_PATH, EXECUTABLE_NAME, +# EXPANDED_CODE_SIGN_IDENTITY + +set -e + +case "$CONFIGURATION" in + Debug*) + echo "Skipping symbol stripping for $CONFIGURATION build." + exit 0 + ;; +esac + +APP_DIR_PATH="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}" + +echo "Stripping main binary: ${APP_DIR_PATH}/${EXECUTABLE_NAME}" +strip -rSTx "${APP_DIR_PATH}/${EXECUTABLE_NAME}" + +APP_FRAMEWORKS_DIR="${APP_DIR_PATH}/Frameworks" +if [ -d "$APP_FRAMEWORKS_DIR" ]; then + find "$APP_FRAMEWORKS_DIR" -name "*.framework" -maxdepth 1 -type d | while read -r framework_dir; do + framework_name=$(basename "$framework_dir" .framework) + framework_binary="$framework_dir/$framework_name" + if [ ! -f "$framework_binary" ]; then + continue + fi + if codesign -v -R="anchor apple" "$framework_binary" &> /dev/null; then + echo "Skipping Apple-signed: $framework_name" + continue + fi + echo "Stripping framework: $framework_name" + strip -rSTx "$framework_binary" + codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY:--}" --preserve-metadata=identifier,entitlements "$framework_dir" + done +else + echo "No Frameworks directory found at $APP_FRAMEWORKS_DIR" +fi + +echo "Symbol stripping complete."