Strip Binary Symbols (iOS)

🚧

Stripping symbols may cause issues with crash symbolication

Binary symbols are used to symbolicate crash reports. Stripping symbols is only recommended if you are uploading DSYMs to a crash reporter.

Swift binaries include large amounts of symbols in a segment of the binary used by the dynamic linker. These are generally not needed in production builds. If you build your app with bitcode these symbols will automatically be stripped out. However, Xcode 14 deprecated bitcode by default and Apple will remove the ability to build with bitcode in a future Xcode release. Here's the command to strip symbols for a particular binary:

strip -rSTx AppBinary -o AppBinaryStripped

The T flag tells strip to remove Swift symbols, the other flags remove debugging and local symbols. Symbol stripping can be done automatically by adding a custom "Run Script" build phase at the very end of building.

Here is a sample script that may require adjustments for your particular project. This script will strip your main app binary along with any binaries it finds in the /Frameworks directory.

#!/bin/bash
set -e

echo "Starting the symbol stripping process..."

if [ "Release" = "${CONFIGURATION}" ]; then
  echo "Configuration is Release."
  
  # Path to the app directory
  APP_DIR_PATH="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}"
  echo "App directory path: ${APP_DIR_PATH}"

  # Strip main binary
  echo "Stripping main binary: ${APP_DIR_PATH}/${EXECUTABLE_NAME}"
  strip -rSTx "${APP_DIR_PATH}/${EXECUTABLE_NAME}"
  if [ $? -eq 0 ]; then
    echo "Successfully stripped main binary."
  else
    echo "Failed to strip main binary." >&2
  fi

  # Path to the Frameworks directory
  APP_FRAMEWORKS_DIR="${APP_DIR_PATH}/Frameworks"
  echo "Frameworks directory path: ${APP_FRAMEWORKS_DIR}"

  # Strip symbols from frameworks, if Frameworks/ exists at all
  # ... as long as the framework is NOT signed by Apple
  if [ -d "${APP_FRAMEWORKS_DIR}" ]; then
    echo "Frameworks directory exists. Proceeding to strip symbols from frameworks."
    find "${APP_FRAMEWORKS_DIR}" -type f -perm +111 -maxdepth 2 -mindepth 2 -exec bash -c '
    codesign -v -R="anchor apple" "{}" &> /dev/null ||
    (
        echo "Stripping {}" &&
        if [ -w "{}" ]; then
            strip -rSTx "{}"
            if [ $? -eq 0 ]; then
                echo "Successfully stripped {}"
            else
                echo "Failed to strip {}" >&2
            fi
        else
            echo "Warning: No write permission for {}"
        fi
    )
    ' \;
    if [ $? -eq 0 ]; then
        echo "Successfully stripped symbols from frameworks."
    else
        echo "Failed to strip symbols from some frameworks." >&2
    fi
  else
    echo "Frameworks directory does not exist. Skipping framework stripping."
  fi
else
  echo "Configuration is not Release. Skipping symbol stripping."
fi

echo "Symbol stripping process completed."

📘

Script Input Files

Xcode may execute build steps in parallel if they have no dependencies on each other. Make sure to configure the Input File for the script as described below.

Since we are stripping symbols from the binaries themselves, as mentioned earlier you must instead upload dSYM files to your crash reporting service.

However, since Xcode generates dSYM files from your binaries, the resulting dSYM file will be empty if the binary has already been stripped. This means we need to tell Xcode to wait and run our script only once dSYM files have been generated.

To do so, add ${DWARF_DSYM_FOLDER_PATH}/${EXECUTABLE_NAME}.app.dSYM/Contents/Resources/DWARF/${EXECUTABLE_NAME} as an Input File: