From 5359de1287d659c439bd86bf0220d5c6b1ee9cce Mon Sep 17 00:00:00 2001 From: Max Topolsky <30879163+mtopo27@users.noreply.github.com> Date: Tue, 24 Mar 2026 10:31:09 -0700 Subject: [PATCH 1/2] docs(apple): Add swift_ast stripping guide for iOS dSYM uploads Add shared include with explainer and script to zero out __swift_ast sections in dSYMs before uploading. This section is only used for LLDB debugging and can account for the majority of dSYM size with DWARF v5. Include is referenced from both the Size Analysis and Build Distribution pages under a new "Uploading Best Practices" section. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../guides/ios/build-distribution/index.mdx | 6 + .../apple/guides/ios/size-analysis/index.mdx | 6 + includes/size-analysis/strip-swift-ast.mdx | 149 ++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 includes/size-analysis/strip-swift-ast.mdx diff --git a/docs/platforms/apple/guides/ios/build-distribution/index.mdx b/docs/platforms/apple/guides/ios/build-distribution/index.mdx index 158819756c10c..65849752e728c 100644 --- a/docs/platforms/apple/guides/ios/build-distribution/index.mdx +++ b/docs/platforms/apple/guides/ios/build-distribution/index.mdx @@ -38,4 +38,10 @@ Streamline your distribution workflow with automated uploads from CI. +## Uploading Best Practices + +### Strip Swift AST + + + diff --git a/docs/platforms/apple/guides/ios/size-analysis/index.mdx b/docs/platforms/apple/guides/ios/size-analysis/index.mdx index 74daf09bea3b4..d1eb4c0872133 100644 --- a/docs/platforms/apple/guides/ios/size-analysis/index.mdx +++ b/docs/platforms/apple/guides/ios/size-analysis/index.mdx @@ -54,6 +54,12 @@ new: true +## Uploading Best Practices + +### Strip Swift AST + + + ## What's Next? We strongly recommend integrating Size Analysis into your CI pipeline. Follow our guide on [getting set up in CI](/product/size-analysis/integrating-into-ci/). diff --git a/includes/size-analysis/strip-swift-ast.mdx b/includes/size-analysis/strip-swift-ast.mdx new file mode 100644 index 0000000000000..2b3be1df9b95f --- /dev/null +++ b/includes/size-analysis/strip-swift-ast.mdx @@ -0,0 +1,149 @@ +For optimal processing speeds, strip `__swift_ast` from your dSYMs before uploading to Sentry. This section of the binary is a copy of your code's swiftmodule file and is only used for runtime debugging with LLDB. It is not required for symbolication, Size Analysis, or Build Distribution. + +The script below can be used to strip `__swift_ast` from your dSYMs. The xcarchive is modified in-place. Back up first if needed. + +```bash +#!/bin/bash +set -euo pipefail + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +XCARCHIVE="$1" +DSYMS_DIR="$XCARCHIVE/dSYMs" + +if [[ ! -d "$DSYMS_DIR" ]]; then + echo "Error: No dSYMs directory found at $DSYMS_DIR" >&2 + exit 1 +fi + +TOTAL_ZEROED=0 +STRIPPED_COUNT=0 + +# Zero out __swift_ast in a single-arch Mach-O binary. +# Prints the number of bytes zeroed (0 if section not found). +strip_thin_binary() { + local binary="$1" + + local ast_info + ast_info=$(xcrun otool -l "$binary" 2>/dev/null | awk ' + /sectname __swift_ast/ { found = 1 } + found && /^[[:space:]]+size / { + cmd = "printf \"%d\" " $2 + cmd | getline dec_size + close(cmd) + } + found && /^[[:space:]]+offset / { + print dec_size " " $2 + found = 0 + } + ') + + if [[ -z "$ast_info" ]]; then + echo "0" + return + fi + + local ast_size ast_offset + ast_size=$(echo "$ast_info" | awk '{print $1}') + ast_offset=$(echo "$ast_info" | awk '{print $2}') + + if [[ "$ast_size" -eq 0 ]]; then + echo "0" + return + fi + + # Skip if already zeroed + local already_zeroed + already_zeroed=$(/usr/bin/python3 -c " +import sys +with open(sys.argv[1], 'rb') as f: + f.seek(int(sys.argv[2])) + print('1' if f.read(int(sys.argv[3])) == b'\0' * int(sys.argv[3]) else '0') +" "$binary" "$ast_offset" "$ast_size") + + if [[ "$already_zeroed" == "1" ]]; then + echo "0" + return + fi + + chmod u+w "$binary" 2>/dev/null || true + /usr/bin/python3 -c " +import sys +with open(sys.argv[1], 'r+b') as f: + f.seek(int(sys.argv[2])) + f.write(b'\0' * int(sys.argv[3])) +" "$binary" "$ast_offset" "$ast_size" + + echo "$ast_size" +} + +# Handle both fat (multi-arch) and thin (single-arch) binaries. +strip_binary() { + local binary="$1" + + local lipo_info + lipo_info=$(xcrun lipo -info "$binary" 2>/dev/null) || true + + if echo "$lipo_info" | grep -q "Architectures in the fat file"; then + local archs + archs=$(echo "$lipo_info" | sed 's/.*: //') + + local tmp_dir + tmp_dir=$(mktemp -d) + local thin_files=() + local saved=0 + + for arch in $archs; do + local thin_file="$tmp_dir/$arch" + xcrun lipo "$binary" -thin "$arch" -output "$thin_file" + + local bytes_str + bytes_str=$(strip_thin_binary "$thin_file") + saved=$((saved + bytes_str)) + + thin_files+=("$thin_file") + done + + if [[ $saved -gt 0 ]]; then + chmod u+w "$binary" 2>/dev/null || true + xcrun lipo -create "${thin_files[@]}" -output "$binary" + fi + + rm -rf "$tmp_dir" + echo "$saved" + else + strip_thin_binary "$binary" + fi +} + +echo "Zeroing __swift_ast in dSYMs in: $DSYMS_DIR" +echo "" + +while IFS= read -r dsym_bundle; do + dsym_name=$(basename "$dsym_bundle") + dwarf_dir="$dsym_bundle/Contents/Resources/DWARF" + + if [[ ! -d "$dwarf_dir" ]]; then + continue + fi + + for binary in "$dwarf_dir"/*; do + [[ -f "$binary" ]] || continue + + zeroed=$(strip_binary "$binary") + if [[ "$zeroed" -gt 0 ]]; then + zeroed_mb=$(echo "scale=1; $zeroed / 1048576" | bc) + echo " $dsym_name — zeroed ${zeroed_mb} MB" + TOTAL_ZEROED=$((TOTAL_ZEROED + zeroed)) + STRIPPED_COUNT=$((STRIPPED_COUNT + 1)) + fi + done +done < <(find "$DSYMS_DIR" -name "*.dSYM" -type d) + +TOTAL_MB=$(echo "scale=1; $TOTAL_ZEROED / 1048576" | bc) +echo "" +echo "Done. Processed $STRIPPED_COUNT dSYM(s), zeroed ${TOTAL_MB} MB of __swift_ast data." +``` From 7418f99af3a484c0f5518194ef1787529d84cab3 Mon Sep 17 00:00:00 2001 From: Max Topolsky <30879163+mtopo27@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:21:45 -0700 Subject: [PATCH 2/2] fix mb calculation + add prereqs --- includes/size-analysis/strip-swift-ast.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/size-analysis/strip-swift-ast.mdx b/includes/size-analysis/strip-swift-ast.mdx index 2b3be1df9b95f..7c2658f13f7c2 100644 --- a/includes/size-analysis/strip-swift-ast.mdx +++ b/includes/size-analysis/strip-swift-ast.mdx @@ -2,6 +2,8 @@ For optimal processing speeds, strip `__swift_ast` from your dSYMs before upload The script below can be used to strip `__swift_ast` from your dSYMs. The xcarchive is modified in-place. Back up first if needed. +**Prerequisites**: Xcode command line tools (otool, lipo), Python 3 + ```bash #!/bin/bash set -euo pipefail @@ -143,7 +145,7 @@ while IFS= read -r dsym_bundle; do done done < <(find "$DSYMS_DIR" -name "*.dSYM" -type d) -TOTAL_MB=$(echo "scale=1; $TOTAL_ZEROED / 1048576" | bc) +TOTAL_MB=$(echo "scale=1; $TOTAL_ZEROED / 1000000" | bc) echo "" echo "Done. Processed $STRIPPED_COUNT dSYM(s), zeroed ${TOTAL_MB} MB of __swift_ast data." ```