Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cdb16ce
ref: scaffold migration from PrivateSentrySDKOnly to SentryObjCSDK.in…
jamescrosswell Jul 20, 2026
e532a2f
ref: generate SentryObjC bindings alongside PrivateSentrySDKOnly (#5331)
jamescrosswell Jul 20, 2026
cada275
ref: migrate Cocoa wrappers to SentryObjCSDK.internal (#5331)
jamescrosswell Jul 20, 2026
4f49f46
ci: pin Xcode 26.6 for .NET iOS 26.5 workload
jamescrosswell Jul 20, 2026
4216c80
ci: align codeql-action/analyze to v4.37.1 to match init
jamescrosswell Jul 20, 2026
1ce2ca8
Merge remote-tracking branch 'origin/fix/5406-pin-xcode-26.6' into mi…
jamescrosswell Jul 21, 2026
cc9c9db
fix: strip embedded Frameworks from SentryObjC xcframeworks (#5331)
jamescrosswell Jul 21, 2026
e6bf220
fix: copy immutable profile payload before mutating (#5331)
jamescrosswell Jul 21, 2026
11bf362
Merge remote-tracking branch 'origin/main' into migrate-private-sentr…
jamescrosswell Jul 22, 2026
2050c34
fix: expect SentryObjC debug symbols in iOS symbol-upload test (#5331)
jamescrosswell Jul 22, 2026
55ff0b8
ref: remove the PrivateSentrySDKOnly binding (#5331)
jamescrosswell Jul 22, 2026
4689d20
Make code comments more concise
jamescrosswell Jul 22, 2026
e9dad16
Apply suggestion from @jamescrosswell
jamescrosswell Jul 22, 2026
9c07677
Merge remote-tracking branch 'origin/main' into migrate-private-sentr…
jamescrosswell Jul 22, 2026
93a5885
Merge branch 'migrate-private-sentrysdk-only-5331' of github.com:gets…
jamescrosswell Jul 22, 2026
1cd8cdb
docs: clarify that NativeReference order is not load-bearing (#5331)
jamescrosswell Jul 22, 2026
ba5e065
Removed redundant comments
jamescrosswell Jul 22, 2026
6da0063
fix: repair unterminated XML comment in Sentry.Bindings.Cocoa.csproj
jamescrosswell Jul 22, 2026
5f06ee9
fix: move comment out of the sharpie backtick continuation
jamescrosswell Jul 22, 2026
5025efe
ref: remove the pre-built Cocoa SDK download path (#5331)
jamescrosswell Jul 23, 2026
a6dbf0b
fix: scope Hot Restart simulator-strip to this package's frameworks (…
jamescrosswell Jul 23, 2026
df02fb7
Apply suggestion from @jamescrosswell
jamescrosswell Jul 23, 2026
1e8b02a
ref: run the missing-submodule check before the Cocoa build targets
jamescrosswell Jul 23, 2026
ee0728f
Merge branch 'migrate-private-sentrysdk-only-5331' of github.com:gets…
jamescrosswell Jul 23, 2026
247a9f0
ref: drop unused SentryObjC enums from the generated bindings (#5331)
jamescrosswell Jul 23, 2026
1163b23
fix: include the build script's hash in the Cocoa build stamp (#5331)
jamescrosswell Jul 23, 2026
6e57539
ref: simplify Hot Restart strip regex; document submodule-ref staging
jamescrosswell Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .generated.NoMobile.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
</Folder>
<Folder Name="/integration-test/net4-console/" />
<Folder Name="/modules/">
<File Path="modules/sentry-cocoa.properties" />
<Project Path="modules/perfview/src/FastSerialization/FastSerialization.csproj" />
<Project Path="modules/perfview/src/TraceEvent/TraceEvent.csproj" />
</Folder>
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/device-tests-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ on:
- 'lib/sentry-android-supplemental/**'
- 'modules/sentry-native/**'
- 'modules/sentry-cocoa/**'
- 'modules/sentry-cocoa.properties'
# Build configuration (affects all builds)
- 'global.json'
- 'Directory.Build.props'
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/device-tests-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ on:
- 'lib/sentry-android-supplemental/**'
- 'modules/sentry-native/**'
- 'modules/sentry-cocoa/**'
- 'modules/sentry-cocoa.properties'
# Build configuration (affects all builds)
- 'global.json'
- 'Directory.Build.props'
Expand Down
33 changes: 16 additions & 17 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,27 +194,26 @@ should be updated from the main branch and the `modules/make-internal.sh` script
should reference the most recent commit on the `internal` branch of Ben.Demystifier then (functionally identical to the
main branch - the only difference being the changes to member visibility).

## Local Sentry Cocoa SDK checkout
## Sentry Cocoa SDK checkout

By default, `Sentry.Bindings.Cocoa` downloads a pre-built Sentry Cocoa SDK from
GitHub Releases. The version is specified in `modules/sentry-cocoa.properties`.
`Sentry.Bindings.Cocoa` always builds the Sentry Cocoa SDK from source, from the
[getsentry/sentry-cocoa](https://github.com/getsentry/sentry-cocoa/) submodule at
`modules/sentry-cocoa` (`scripts/build-sentry-cocoa.sh`, invoked automatically by
the build). Pre-built release artifacts can't be used: the `SentryObjC` hybrid-API
frameworks are only published as self-contained bundles that would embed a second
copy of the SDK alongside `Sentry.framework` (see
[#5331](https://github.com/getsentry/sentry-dotnet/issues/5331)).

If you want to build an unreleased Sentry Cocoa SDK version from source instead,
replace the pre-built SDK with [getsentry/sentry-cocoa](https://github.com/getsentry/sentry-cocoa/)
by cloning it into the `modules/sentry-cocoa` directory:
To build against a different Cocoa SDK version, check out the desired ref in the
submodule **and stage it** — the solution build automatically runs
`git submodule update` (see `before.Sentry.sln.targets`), which reverts the
submodule to the pinned commit unless the index already records your ref:

```sh
$ rm -rf modules/sentry-cocoa
$ gh repo clone getsentry/sentry-cocoa modules/sentry-cocoa
$ dotnet build ... # uses modules/sentry-cocoa as is
```

To switch back to the pre-built SDK, delete the `modules/sentry-cocoa` directory
and let the next build download the pre-built SDK again:

```sh
$ rm -rf modules/sentry-cocoa
$ dotnet build ... # downloads pre-built Cocoa SDK into modules/sentry-cocoa
$ git -C modules/sentry-cocoa fetch origin
$ git -C modules/sentry-cocoa checkout <tag-or-sha>
$ git add modules/sentry-cocoa # otherwise the build restores the pinned commit
$ dotnet build ... # rebuilds the Cocoa SDK from the new ref
```

## Local Sentry Android SDK checkout
Expand Down
1 change: 0 additions & 1 deletion Sentry.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
</Folder>
<Folder Name="/integration-test/net4-console/" />
<Folder Name="/modules/">
<File Path="modules/sentry-cocoa.properties" />
<Project Path="modules/perfview/src/FastSerialization/FastSerialization.csproj" />
<Project Path="modules/perfview/src/TraceEvent/TraceEvent.csproj" />
</Folder>
Expand Down
4 changes: 3 additions & 1 deletion integration-test/cli.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ Describe 'MAUI (<framework>)' -ForEach @(
'Microsoft.Maui.Essentials.pdb',
'Microsoft.Maui.Graphics.pdb',
'Microsoft.Maui.pdb',
'Sentry'
'Sentry',
'SentryObjC',
'SentryObjCCompat'
)
# The specific number of debug information files seems to change with different SDK - so we just check for non-zero
$nonZeroNumberRegex = '[1-9][0-9]*';
Expand Down
69 changes: 66 additions & 3 deletions scripts/build-sentry-cocoa.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#!/bin/bash
set -euo pipefail

# Include this script's own hash in the build stamp so cached output is rebuilt whenever the
# recipe changes (e.g. when new frameworks are added to the build), not just when the
# sentry-cocoa submodule moves. Mirrors the cache key used for sentry-native in CI.
script_checksum=$(shasum -a 256 "$0" | cut -d ' ' -f 1)

pushd "$(dirname "$0")" >/dev/null
cd ../modules/sentry-cocoa

Expand All @@ -24,8 +29,8 @@ while ! ln "$TMP_FILE" "$PID_FILE" 2>/dev/null; do
done
rm -f "$TMP_FILE"

current_sha=$(git rev-parse HEAD)
if [[ -f Carthage/.built-from-sha ]] && [[ "$(cat Carthage/.built-from-sha)" == "$current_sha" ]]; then
build_stamp="$(git rev-parse HEAD) $script_checksum"
if [[ -f Carthage/.built-from-sha ]] && [[ "$(cat Carthage/.built-from-sha)" == "$build_stamp" ]]; then
popd >/dev/null
exit 0
fi
Expand Down Expand Up @@ -67,6 +72,38 @@ xcodebuild -create-xcframework \
-output ./Carthage/Build-ios/Sentry.xcframework
echo "::endgroup::"

# The SentryObjC scheme adds the structured hybrid API (SentryObjCSDK.internal), which the .NET
Comment thread
cursor[bot] marked this conversation as resolved.
# bindings use in place of the deprecated PrivateSentrySDKOnly. It produces two thin frameworks -
# SentryObjC and SentryObjCCompat - that dynamically link the Sentry.framework built above (they do
# not embed their own copy of the SDK), so we bundle them alongside Sentry.xcframework. We build
# these from source rather than downloading the pre-built SentryObjC-Dynamic.xcframework because
# that release artifact is self-contained (it embeds the whole SDK) and would duplicate Sentry.
echo "::group::Building SentryObjC for iOS and iOS simulator"
xcodebuild archive -project Sentry.xcodeproj \
-scheme SentryObjC \
-configuration Release \
-sdk "$ios_sdk" \
-archivePath ./Carthage/output-objc-ios.xcarchive \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
GCC_PREPROCESSOR_DEFINITIONS='$(inherited) SENTRY_CRASH_MANAGED_RUNTIME=1'
./scripts/remove-architectures.sh ./Carthage/output-objc-ios.xcarchive arm64e
xcodebuild archive -project Sentry.xcodeproj \
-scheme SentryObjC \
-configuration Release \
-sdk "$ios_simulator_sdk" \
-archivePath ./Carthage/output-objc-iossimulator.xcarchive \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
GCC_PREPROCESSOR_DEFINITIONS='$(inherited) SENTRY_CRASH_MANAGED_RUNTIME=1'
for fw in SentryObjC SentryObjCCompat; do
xcodebuild -create-xcframework \
-framework "./Carthage/output-objc-ios.xcarchive/Products/Library/Frameworks/$fw.framework" \
-framework "./Carthage/output-objc-iossimulator.xcarchive/Products/Library/Frameworks/$fw.framework" \
-output "./Carthage/Build-ios/$fw.xcframework"
done
echo "::endgroup::"

# Separately, build for Mac Catalyst
echo "::group::Building sentry-cocoa for Mac Catalyst"
xcodebuild archive -project Sentry.xcodeproj \
Expand All @@ -83,15 +120,41 @@ xcodebuild -create-xcframework \
-output ./Carthage/Build-maccatalyst/Sentry.xcframework
echo "::endgroup::"

echo "::group::Building SentryObjC for Mac Catalyst"
xcodebuild archive -project Sentry.xcodeproj \
-scheme SentryObjC \
-configuration Release \
-destination 'generic/platform=macOS,variant=Mac Catalyst' \
-archivePath ./Carthage/output-objc-maccatalyst.xcarchive \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
GCC_PREPROCESSOR_DEFINITIONS='$(inherited) SENTRY_CRASH_MANAGED_RUNTIME=1'
./scripts/remove-architectures.sh ./Carthage/output-objc-maccatalyst.xcarchive arm64e
for fw in SentryObjC SentryObjCCompat; do
xcodebuild -create-xcframework \
-framework "./Carthage/output-objc-maccatalyst.xcarchive/Products/Library/Frameworks/$fw.framework" \
-output "./Carthage/Build-maccatalyst/$fw.xcframework"
done
echo "::endgroup::"

# Xcode embeds each framework's dynamic dependencies under <Framework>.framework/Frameworks/ (e.g.
# SentryObjC.framework/Frameworks/SentryObjCCompat.framework/Frameworks/Sentry.framework). We bundle
# Sentry, SentryObjCCompat and SentryObjC as separate NativeReferences - each embedded into the
# consuming app - so those nested copies are redundant, and their deep paths blow past NuGet's path
# length limit (NU5123). To fix that, we strip them. The frameworks resolve each other via @rpath at the app level instead/anyway.
find Carthage/Build-*/SentryObjC*.xcframework -type d -name Frameworks -prune -exec rm -rf {} +

# Copy headers - used for generating bindings
mkdir Carthage/Headers
find Carthage/Build-ios/Sentry.xcframework/ios-arm64 -name '*.h' -exec cp {} Carthage/Headers \;
find Carthage/Build-ios/SentryObjC.xcframework/ios-arm64 -name '*.h' -exec cp {} Carthage/Headers \;
find Carthage/Build-ios/SentryObjCCompat.xcframework/ios-arm64 -name '*.h' -exec cp {} Carthage/Headers \;

# Remove anything we don't want to bundle in the nuget package.
find Carthage/Build* \( -name Headers -o -name PrivateHeaders -o -name Modules \) -exec rm -rf {} +
rm -rf Carthage/output-*

echo "$current_sha" > Carthage/.built-from-sha
echo "$build_stamp" > Carthage/.built-from-sha
echo ""

popd >/dev/null
23 changes: 10 additions & 13 deletions scripts/generate-cocoa-bindings.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,9 @@ $PSNativeCommandUseErrorActionPreference = $true

$RootPath = (Get-Item $PSScriptRoot).Parent.FullName
$CocoaSdkPath = "$RootPath/modules/sentry-cocoa"
if (Test-Path "$CocoaSdkPath/.git")
{
# Cocoa SDK cloned to modules/sentry-cocoa for local development
$HeadersPath = "$CocoaSdkPath/Carthage/Headers"
$PrivateHeadersPath = "$CocoaSdkPath/Carthage/Headers"
}
else
{
# Cocoa SDK downloaded from GitHub releases and extracted into modules/sentry-cocoa
$HeadersPath = "$CocoaSdkPath/Sentry.framework/Headers"
$PrivateHeadersPath = "$CocoaSdkPath/Sentry.framework/PrivateHeaders"
}
# The Cocoa SDK is built from source from the modules/sentry-cocoa submodule;
# build-sentry-cocoa.sh copies the headers here.
$HeadersPath = "$CocoaSdkPath/Carthage/Headers"
$BindingsPath = "$RootPath/src/Sentry.Bindings.Cocoa"
$BackupPath = "$BindingsPath/obj/_unpatched"

Expand Down Expand Up @@ -164,12 +155,18 @@ else
}

# Generate bindings
# The SentryObjC*.h headers expose the structured hybrid API (SentryObjCSDK.internal)
Write-Output 'Generating bindings with Objective Sharpie.'
sharpie bind -sdk $iPhoneSdkVersion `
-scope "$CocoaSdkPath" `
"$HeadersPath/Sentry.h" `
"$HeadersPath/Sentry-Swift.h" `
"$HeadersPath/PrivateSentrySDKOnly.h" `
"$HeadersPath/SentryObjCSDK.h" `
Comment thread
jamescrosswell marked this conversation as resolved.
"$HeadersPath/SentryObjCInternalApi.h" `
"$HeadersPath/SentryObjCInternalSdkApi.h" `
"$HeadersPath/SentryObjCInternalProfilingApi.h" `
"$HeadersPath/SentryObjCId.h" `
"$HeadersPath/SentryObjCSpanId.h" `
-o $BindingsPath `
-c -Wno-objc-property-no-attribute `
-F"$iPhoneSdkPath/System/Library/SubFrameworks" # needed for UIUtilities.framework in Xcode 26+
Expand Down
36 changes: 23 additions & 13 deletions scripts/patch-cocoa-bindings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
.PropertyToMethod("Sentry*", "Serialize")
.PropertyToMethod("SentrySpan", "ToTraceHeader")
.PropertyToMethod("SentryTraceContext", "ToBaggage")
.PropertyToMethod("PrivateSentrySDKOnly", "Capture*")
// Verify the rest
.VerifyProperty("*Sentry*", "*", "MethodToProperty") // TODO: replace broad patterns with one-by-one verification
.VerifyProperty("SentryOptions", "*Targets", "StronglyTypedNSArray")
Expand All @@ -81,11 +80,6 @@
.WithAttribute("SentryBeforeBreadcrumbCallback", "return: NullAllowed")
.WithAttribute("SentryBeforeSendEventCallback", "return: NullAllowed")
.WithAttribute("SentryTracesSamplerCallback", "return: NullAllowed")
// Fix nullable return attributes
.RemoveAttribute("PrivateSentrySDKOnly", "CaptureScreenshots", "NullAllowed")
.RemoveAttribute("PrivateSentrySDKOnly", "CaptureViewHierarchy", "NullAllowed")
.WithAttribute("PrivateSentrySDKOnly", "CaptureScreenshots", "return: NullAllowed")
.WithAttribute("PrivateSentrySDKOnly", "CaptureViewHierarchy", "return: NullAllowed")
// Fix nullable property attributes
.WithPropertyAttribute("SentryOptions", "OnCrashedLastRun", "NullAllowed")
// Fix nullable generic type arguments
Expand All @@ -104,10 +98,6 @@
.RemoveMethod("Sentry*", "CopyWithZone")
// error CS0111: Type 'SentryAttribute' already defines a member called 'Constructor' with the same parameter types
.RemoveMethod("SentryLog", "SetAttribute")
// SentryEnvelope* is not whitelisted
.RemoveMethod("PrivateSentrySDKOnly", "CaptureEnvelope")
.RemoveMethod("PrivateSentrySDKOnly", "EnvelopeWithData")
.RemoveMethod("PrivateSentrySDKOnly", "StoreEnvelope")
// SentryLoggerDelegate and SentryCurrentDateProvider are not whitelisted
.RemoveMethod("SentryLogger", "Constructor")
// SentryAppStartMeasurement is not whitelisted
Expand All @@ -116,17 +106,24 @@
.RemoveDelegate("SentryUserFeedbackConfigurationBlock")
// error CS0114: 'SentryXxx.Description' hides inherited member 'NSObject.Description'.
.RemoveProperty("Sentry*", "Description")
// SentryAppStartMeasurement is not whitelisted
.RemoveProperty("PrivateSentrySDKOnly", "*AppStartMeasurement*")
// Minimize SentryDependencyContainer
.RemoveMethod("SentryDependencyContainer", "*")
.KeepProperties("SentryDependencyContainer", "SharedInstance", "DebugImageProvider")
// SentryUserFeedbackConfiguration is not whitelisted
.RemoveProperty("SentryOptions", "ConfigureUserFeedback")
.RemoveProperty("SentryOptions", "UserFeedbackConfiguration")
// SentryObjCSDK.internal is the entry point to the API for hybrid SDKs
// We only bind the `internal` accessor; every other SentryObjCSDK member references SentryObjC*
// types we don't whitelist.
.KeepProperties("SentryObjCSDK", "Internal")
.RemoveMethod("SentryObjCSDK", "*")
.KeepProperties("SentryObjCInternalApi", "Sdk", "Profiling")
.KeepMethods("SentryObjCInternalApi", "SetTrace", "IgnoreNextSignal")
// Sharpie generates enums for types the SentryObjC headers reference, but the members that used
// them are trimmed above - drop the dead enums
.RemoveEnum("SentryObjC*")
.KeepInterfaces(
"ISentryRRWebEvent",
"PrivateSentrySDKOnly",
"SentryAttachment",
"SentryBaggage",
"SentryBreadcrumb",
Expand Down Expand Up @@ -155,6 +152,12 @@
"SentryMechanismContext",
"SentryMessage",
"SentryNSError",
"SentryObjCId",
"SentryObjCInternalApi",
"SentryObjCInternalProfilingApi",
"SentryObjCInternalSdkApi",
"SentryObjCSDK",
"SentryObjCSpanId",
"SentryOptions",
"SentryProfileOptions",
"SentryRedactOptions",
Expand Down Expand Up @@ -251,6 +254,13 @@ public static CompilationUnitSyntax RemoveClass(
return root.RemoveByPredicate<ClassDeclarationSyntax>(node => node.Identifier.Matches(name));
}

public static CompilationUnitSyntax RemoveEnum(
this CompilationUnitSyntax root,
string name)
{
return root.RemoveByPredicate<EnumDeclarationSyntax>(node => node.Identifier.Matches(name));
}

public static CompilationUnitSyntax RemoveDelegate(
this CompilationUnitSyntax root,
string name)
Expand Down
Loading
Loading