Skip to content

Commit a114634

Browse files
mtopo27claude
andauthored
docs(apple): Add swift_ast stripping guide for dSYM uploads (#17105)
## DESCRIBE YOUR PR Add documentation for stripping `__swift_ast` sections from dSYMs before uploading to Sentry. This section is only used for LLDB debugging and can make up the majority of dSYM size with DWARF v5. - Add shared MDX include with explainer text and a bash script to zero out `__swift_ast` - Include the guide in both the Size Analysis and Build Distribution pages under "Uploading Best Practices" ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. - [ ] Urgent deadline (GA date, etc.): - [ ] Other deadline: - [x] None: Not urgent, can wait up to 1 week+ ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it. Thanks in advance for your help! ## PRE-MERGE CHECKLIST *Make sure you've checked the following before merging your changes:* - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6dda6d1 commit a114634

3 files changed

Lines changed: 163 additions & 0 deletions

File tree

docs/platforms/apple/guides/ios/build-distribution/index.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,10 @@ Streamline your distribution workflow with automated uploads from CI.
3838

3939
<Include name="size-analysis/build-configuration-ios" />
4040

41+
## Uploading Best Practices
42+
43+
### Strip Swift AST
44+
45+
<Include name="size-analysis/strip-swift-ast" />
46+
4147
<PageGrid />

docs/platforms/apple/guides/ios/size-analysis/index.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ new: true
5454

5555
<Include name="size-analysis/app-store-connect-file-sizes" />
5656

57+
## Uploading Best Practices
58+
59+
### Strip Swift AST
60+
61+
<Include name="size-analysis/strip-swift-ast" />
62+
5763
## What's Next?
5864

5965
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/).
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
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.
2+
3+
The script below can be used to strip `__swift_ast` from your dSYMs. The xcarchive is modified in-place. Back up first if needed.
4+
5+
**Prerequisites**: Xcode command line tools (otool, lipo), Python 3
6+
7+
```bash
8+
#!/bin/bash
9+
set -euo pipefail
10+
11+
if [[ $# -ne 1 ]]; then
12+
echo "Usage: $0 <path-to-xcarchive>" >&2
13+
exit 1
14+
fi
15+
16+
XCARCHIVE="$1"
17+
DSYMS_DIR="$XCARCHIVE/dSYMs"
18+
19+
if [[ ! -d "$DSYMS_DIR" ]]; then
20+
echo "Error: No dSYMs directory found at $DSYMS_DIR" >&2
21+
exit 1
22+
fi
23+
24+
TOTAL_ZEROED=0
25+
STRIPPED_COUNT=0
26+
27+
# Zero out __swift_ast in a single-arch Mach-O binary.
28+
# Prints the number of bytes zeroed (0 if section not found).
29+
strip_thin_binary() {
30+
local binary="$1"
31+
32+
local ast_info
33+
ast_info=$(xcrun otool -l "$binary" 2>/dev/null | awk '
34+
/sectname __swift_ast/ { found = 1 }
35+
found && /^[[:space:]]+size / {
36+
cmd = "printf \"%d\" " $2
37+
cmd | getline dec_size
38+
close(cmd)
39+
}
40+
found && /^[[:space:]]+offset / {
41+
print dec_size " " $2
42+
found = 0
43+
}
44+
')
45+
46+
if [[ -z "$ast_info" ]]; then
47+
echo "0"
48+
return
49+
fi
50+
51+
local ast_size ast_offset
52+
ast_size=$(echo "$ast_info" | awk '{print $1}')
53+
ast_offset=$(echo "$ast_info" | awk '{print $2}')
54+
55+
if [[ "$ast_size" -eq 0 ]]; then
56+
echo "0"
57+
return
58+
fi
59+
60+
# Skip if already zeroed
61+
local already_zeroed
62+
already_zeroed=$(/usr/bin/python3 -c "
63+
import sys
64+
with open(sys.argv[1], 'rb') as f:
65+
f.seek(int(sys.argv[2]))
66+
print('1' if f.read(int(sys.argv[3])) == b'\0' * int(sys.argv[3]) else '0')
67+
" "$binary" "$ast_offset" "$ast_size")
68+
69+
if [[ "$already_zeroed" == "1" ]]; then
70+
echo "0"
71+
return
72+
fi
73+
74+
chmod u+w "$binary" 2>/dev/null || true
75+
/usr/bin/python3 -c "
76+
import sys
77+
with open(sys.argv[1], 'r+b') as f:
78+
f.seek(int(sys.argv[2]))
79+
f.write(b'\0' * int(sys.argv[3]))
80+
" "$binary" "$ast_offset" "$ast_size"
81+
82+
echo "$ast_size"
83+
}
84+
85+
# Handle both fat (multi-arch) and thin (single-arch) binaries.
86+
strip_binary() {
87+
local binary="$1"
88+
89+
local lipo_info
90+
lipo_info=$(xcrun lipo -info "$binary" 2>/dev/null) || true
91+
92+
if echo "$lipo_info" | grep -q "Architectures in the fat file"; then
93+
local archs
94+
archs=$(echo "$lipo_info" | sed 's/.*: //')
95+
96+
local tmp_dir
97+
tmp_dir=$(mktemp -d)
98+
local thin_files=()
99+
local saved=0
100+
101+
for arch in $archs; do
102+
local thin_file="$tmp_dir/$arch"
103+
xcrun lipo "$binary" -thin "$arch" -output "$thin_file"
104+
105+
local bytes_str
106+
bytes_str=$(strip_thin_binary "$thin_file")
107+
saved=$((saved + bytes_str))
108+
109+
thin_files+=("$thin_file")
110+
done
111+
112+
if [[ $saved -gt 0 ]]; then
113+
chmod u+w "$binary" 2>/dev/null || true
114+
xcrun lipo -create "${thin_files[@]}" -output "$binary"
115+
fi
116+
117+
rm -rf "$tmp_dir"
118+
echo "$saved"
119+
else
120+
strip_thin_binary "$binary"
121+
fi
122+
}
123+
124+
echo "Zeroing __swift_ast in dSYMs in: $DSYMS_DIR"
125+
echo ""
126+
127+
while IFS= read -r dsym_bundle; do
128+
dsym_name=$(basename "$dsym_bundle")
129+
dwarf_dir="$dsym_bundle/Contents/Resources/DWARF"
130+
131+
if [[ ! -d "$dwarf_dir" ]]; then
132+
continue
133+
fi
134+
135+
for binary in "$dwarf_dir"/*; do
136+
[[ -f "$binary" ]] || continue
137+
138+
zeroed=$(strip_binary "$binary")
139+
if [[ "$zeroed" -gt 0 ]]; then
140+
zeroed_mb=$(echo "scale=1; $zeroed / 1048576" | bc)
141+
echo " $dsym_name — zeroed ${zeroed_mb} MB"
142+
TOTAL_ZEROED=$((TOTAL_ZEROED + zeroed))
143+
STRIPPED_COUNT=$((STRIPPED_COUNT + 1))
144+
fi
145+
done
146+
done < <(find "$DSYMS_DIR" -name "*.dSYM" -type d)
147+
148+
TOTAL_MB=$(echo "scale=1; $TOTAL_ZEROED / 1000000" | bc)
149+
echo ""
150+
echo "Done. Processed $STRIPPED_COUNT dSYM(s), zeroed ${TOTAL_MB} MB of __swift_ast data."
151+
```

0 commit comments

Comments
 (0)