From cdb16ced1266c23d829bfe816dfca3a206201ec9 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Mon, 20 Jul 2026 16:16:41 +1200 Subject: [PATCH 01/22] ref: scaffold migration from PrivateSentrySDKOnly to SentryObjCSDK.internal Opens the branch/PR for the phased migration off the deprecated PrivateSentrySDKOnly hybrid API (#5331). Phases land as subsequent commits. Co-Authored-By: Claude Opus 4.8 From e532a2ff0ee9920ae3a7c7d871eb9658c202ce6f Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Mon, 20 Jul 2026 16:33:56 +1200 Subject: [PATCH 02/22] ref: generate SentryObjC bindings alongside PrivateSentrySDKOnly (#5331) Phase 1 of migrating the Cocoa hybrid API off the deprecated PrivateSentrySDKOnly to the structured SentryObjCSDK.internal API. - build-sentry-cocoa.sh now also builds the SentryObjC and SentryObjCCompat schemes from source into thin xcframeworks (iOS, iOS-sim, Mac Catalyst). These dynamically link the existing Sentry.framework rather than embedding their own copy of the SDK, so they don't duplicate it - unlike the self-contained released SentryObjC-Dynamic.xcframework. - generate-cocoa-bindings.ps1 feeds the SentryObjC entry-point, internal-API, and id headers to Objective Sharpie. - patch-cocoa-bindings.cs keeps the new interfaces and trims SentryObjCSDK to its `internal` accessor and SentryObjCInternalApi to the members the .NET wrappers use (sdk, profiling, setTrace, ignoreNextSignal). - Sentry.Bindings.Cocoa.csproj bundles the two new frameworks via NativeReference. PrivateSentrySDKOnly is kept in parallel; call sites migrate in phase 2. Co-Authored-By: Claude Opus 4.8 --- scripts/build-sentry-cocoa.sh | 51 +++++++ scripts/generate-cocoa-bindings.ps1 | 10 ++ scripts/patch-cocoa-bindings.cs | 15 ++ src/Sentry.Bindings.Cocoa/ApiDefinitions.cs | 132 ++++++++++++++++++ .../Sentry.Bindings.Cocoa.csproj | 8 ++ src/Sentry.Bindings.Cocoa/StructsAndEnums.cs | 15 ++ .../Sentry.Bindings.Cocoa.targets | 3 +- 7 files changed, 233 insertions(+), 1 deletion(-) diff --git a/scripts/build-sentry-cocoa.sh b/scripts/build-sentry-cocoa.sh index f3ef2b7558..dce1234791 100755 --- a/scripts/build-sentry-cocoa.sh +++ b/scripts/build-sentry-cocoa.sh @@ -67,6 +67,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 +# 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 \ @@ -83,9 +115,28 @@ 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::" + # 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 {} + diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 1c102f3b17..369deb2e01 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -164,12 +164,22 @@ else } # Generate bindings +# The SentryObjC* headers expose the structured hybrid API (SentryObjCSDK.internal) that replaces +# the deprecated PrivateSentrySDKOnly. We only bind the entry point (SentryObjCSDK), the internal +# API surface, and the two id types the .NET wrappers pass; patch-cocoa-bindings.cs trims everything +# else these headers pull in via forward declarations. 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" ` + "$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+ diff --git a/scripts/patch-cocoa-bindings.cs b/scripts/patch-cocoa-bindings.cs index 6d6eb801e7..eb9ce94fc7 100644 --- a/scripts/patch-cocoa-bindings.cs +++ b/scripts/patch-cocoa-bindings.cs @@ -124,6 +124,15 @@ // SentryUserFeedbackConfiguration is not whitelisted .RemoveProperty("SentryOptions", "ConfigureUserFeedback") .RemoveProperty("SentryOptions", "UserFeedbackConfiguration") + // SentryObjCSDK.internal is the entry point to the new hybrid API (replacing PrivateSentrySDKOnly). + // We only bind the `internal` accessor; every other SentryObjCSDK member references SentryObjC* + // types we don't whitelist. + .KeepProperties("SentryObjCSDK", "Internal") + .RemoveMethod("SentryObjCSDK", "*") + // On the internal API the .NET wrappers only use the SDK-metadata and profiling sub-objects plus + // setTrace / ignoreNextSignal. The remaining accessors return sub-API/options types that aren't bound. + .KeepProperties("SentryObjCInternalApi", "Sdk", "Profiling") + .KeepMethods("SentryObjCInternalApi", "SetTrace", "IgnoreNextSignal") .KeepInterfaces( "ISentryRRWebEvent", "PrivateSentrySDKOnly", @@ -155,6 +164,12 @@ "SentryMechanismContext", "SentryMessage", "SentryNSError", + "SentryObjCId", + "SentryObjCInternalApi", + "SentryObjCInternalProfilingApi", + "SentryObjCInternalSdkApi", + "SentryObjCSDK", + "SentryObjCSpanId", "SentryOptions", "SentryProfileOptions", "SentryRedactOptions", diff --git a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs index 8b0245cfbd..937113e871 100644 --- a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs +++ b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs @@ -3024,3 +3024,135 @@ interface SentryViewScreenshotOptions : SentryRedactOptions [DesignatedInitializer] NativeHandle Constructor(bool enableViewRendererV2, bool enableFastViewRendering, bool maskAllText, bool maskAllImages, Class[] maskedViewClasses, Class[] unmaskedViewClasses, NSSet excludedViewClasses, NSSet includedViewClasses); } + +// @interface SentryObjCSDK : NSObject +[BaseType(typeof(NSObject))] +[Internal] +interface SentryObjCSDK +{ + + // @property (readonly, nonatomic, class) SentryObjCInternalApi * _Nonnull internal; + [Static] + [Export("internal")] + SentryObjCInternalApi Internal { get; } +} + +// @interface SentryObjCInternalApi : NSObject +[BaseType(typeof(NSObject))] +[DisableDefaultCtor] +[Internal] +interface SentryObjCInternalApi +{ + // @property (readonly, nonatomic) SentryObjCInternalSdkApi * _Nonnull sdk; + [Export("sdk")] + SentryObjCInternalSdkApi Sdk { get; } + + // @property (readonly, nonatomic) SentryObjCInternalProfilingApi * _Nonnull profiling; + [Export("profiling")] + SentryObjCInternalProfilingApi Profiling { get; } + + // -(void)setTrace:(SentryObjCId * _Nonnull)traceId spanId:(SentryObjCSpanId * _Nonnull)spanId; + [Export("setTrace:spanId:")] + void SetTrace(SentryObjCId traceId, SentryObjCSpanId spanId); + + // -(void)ignoreNextSignal:(int)signum; + [Export("ignoreNextSignal:")] + void IgnoreNextSignal(int signum); +} + +// @interface SentryObjCInternalSdkApi : NSObject +[BaseType(typeof(NSObject))] +[DisableDefaultCtor] +[Internal] +interface SentryObjCInternalSdkApi +{ + // @property (copy, nonatomic) NSString * _Nonnull name; + [Export("name")] + string Name { get; set; } + + // @property (copy, nonatomic) NSString * _Nonnull versionString; + [Export("versionString")] + string VersionString { get; set; } + + // -(void)setName:(NSString * _Nonnull)name version:(NSString * _Nonnull)version; + [Export("setName:version:")] + void SetName(string name, string version); + + // -(void)addPackageName:(NSString * _Nonnull)name version:(NSString * _Nonnull)version; + [Export("addPackageName:version:")] + void AddPackageName(string name, string version); + + // @property (readonly, copy, nonatomic) NSDictionary * _Nonnull extraContext; + [Export("extraContext", ArgumentSemantic.Copy)] + NSDictionary ExtraContext { get; } + + // @property (readonly, copy, nonatomic) NSString * _Nonnull installationID; + [Export("installationID")] + string InstallationID { get; } +} + +// @interface SentryObjCInternalProfilingApi : NSObject +[BaseType(typeof(NSObject))] +[DisableDefaultCtor] +[Internal] +interface SentryObjCInternalProfilingApi +{ + // -(uint64_t)startFor:(SentryObjCId * _Nonnull)traceId; + [Export("startFor:")] + ulong StartFor(SentryObjCId traceId); + + // -(NSDictionary * _Nullable)collectBetweenStartTime:(uint64_t)startTime andEndTime:(uint64_t)endTime forTraceId:(SentryObjCId * _Nonnull)traceId; + [Export("collectBetweenStartTime:andEndTime:forTraceId:")] + [return: NullAllowed] + NSDictionary CollectBetweenStartTime(ulong startTime, ulong endTime, SentryObjCId traceId); + + // -(void)discardFor:(SentryObjCId * _Nonnull)traceId; + [Export("discardFor:")] + void DiscardFor(SentryObjCId traceId); +} + +// @interface SentryObjCId : NSObject +[BaseType(typeof(NSObject))] +[Internal] +interface SentryObjCId +{ + // @property (readonly, copy, nonatomic) NSString * _Nonnull sentryIdString; + [Export("sentryIdString")] + string SentryIdString { get; } + + // @property (readonly, nonatomic, strong, class) SentryObjCId * _Nonnull empty; + [Static] + [Export("empty", ArgumentSemantic.Strong)] + SentryObjCId Empty { get; } + + // -(instancetype _Nonnull)initWithUuid:(NSUUID * _Nonnull)uuid; + [Export("initWithUuid:")] + NativeHandle Constructor(NSUuid uuid); + + // -(instancetype _Nonnull)initWithUUIDString:(NSString * _Nonnull)uuidString; + [Export("initWithUUIDString:")] + NativeHandle Constructor(string uuidString); +} + +// @interface SentryObjCSpanId : NSObject +[BaseType(typeof(NSObject))] +[Internal] +interface SentryObjCSpanId +{ + // @property (readonly, copy, nonatomic) NSString * _Nonnull sentrySpanIdString; + [Export("sentrySpanIdString")] + string SentrySpanIdString { get; } + + // @property (readonly, nonatomic, strong, class) SentryObjCSpanId * _Nonnull empty; + [Static] + [Export("empty", ArgumentSemantic.Strong)] + SentryObjCSpanId Empty { get; } + + // -(instancetype _Nonnull)initWithUuid:(NSUUID * _Nonnull)uuid; + [Export("initWithUuid:")] + NativeHandle Constructor(NSUuid uuid); + + // -(instancetype _Nonnull)initWithValue:(NSString * _Nonnull)value; + [Export("initWithValue:")] + NativeHandle Constructor(string value); +} diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index 96bc4b2d0c..1fd15ada4f 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -24,6 +24,11 @@ $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\Sentry.xcframework + + $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjC.xcframework + $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjCCompat.xcframework ../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/**/*.h $([MSBuild]::NormalizePath($(MSBuildThisFileDirectory), $(SentryCocoaCache).git)) @@ -54,6 +59,9 @@ + + + diff --git a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs index 589f710723..246e6d95d5 100644 --- a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs +++ b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs @@ -175,3 +175,18 @@ internal enum SentryTransactionNameSource : long Component = 4, Task = 5 } + +[Native] +internal enum SentryObjCFeedbackSource : long +{ + Widget = 0, + Custom +} + +[Native] +internal enum SentryObjCLastRunStatus : long +{ + Unknown = 0, + DidNotCrash, + DidCrash +} diff --git a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets index 4b74ad10fe..54c4d34e05 100644 --- a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets +++ b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets @@ -45,7 +45,8 @@ --> - + + From cada27595020cf7f70138bd27b70255aecf1698c Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Mon, 20 Jul 2026 17:07:07 +1200 Subject: [PATCH 03/22] ref: migrate Cocoa wrappers to SentryObjCSDK.internal (#5331) Phase 2: repoint the SentryCocoaHybridSdk alias from PrivateSentrySDKOnly to SentryObjCSDK and move the five call sites onto the new instance-based API: - SetSdkName -> Internal.Sdk.Name = - SetTrace -> Internal.SetTrace (using the new SentryObjCId / SentryObjCSpanId) - StartProfilerForTrace -> Internal.Profiling.StartFor - CollectProfileBetween -> Internal.Profiling.CollectBetweenStartTime - IgnoreNextSignal -> Internal.IgnoreNextSignal MiscExtensions gains ToCocoaObjCId / ToCocoaObjCSpanId for the new id types and drops the now-unused ToCocoaSentryId / ToCocoaSpanId. Sentry builds for net10.0-ios26 and net10.0-maccatalyst26 with no warnings. PrivateSentrySDKOnly is still bound (removed in phase 3). Co-Authored-By: Claude Opus 4.8 --- src/Sentry/Platforms/Cocoa/CocoaProfiler.cs | 6 +++--- src/Sentry/Platforms/Cocoa/CocoaProfilerFactory.cs | 4 ++-- src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs | 2 +- src/Sentry/Platforms/Cocoa/Extensions/MiscExtensions.cs | 8 +++++--- src/Sentry/Platforms/Cocoa/RuntimeAdapter.cs | 2 +- src/Sentry/Platforms/Cocoa/Sentry.Cocoa.props | 2 +- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 2 +- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs index 3bbed89c7b..6a008ed8ba 100644 --- a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs +++ b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs @@ -9,12 +9,12 @@ internal class CocoaProfiler : ITransactionProfiler { private readonly SentryOptions _options; private readonly SentryId _traceId; - private readonly CocoaSdk.SentryId _cocoaTraceId; + private readonly CocoaSdk.SentryObjCId _cocoaTraceId; private readonly ulong _startTimeNs; private ulong _endTimeNs; private readonly SentryStopwatch _stopwatch; - public CocoaProfiler(SentryOptions options, ulong startTimeNs, SentryId traceId, CocoaSdk.SentryId cocoaTraceId) + public CocoaProfiler(SentryOptions options, ulong startTimeNs, SentryId traceId, CocoaSdk.SentryObjCId cocoaTraceId) { _stopwatch = SentryStopwatch.StartNew(); _options = options; @@ -36,7 +36,7 @@ public void Finish() public ISerializable? Collect(SentryTransaction transaction) { - var payload = SentryCocoaHybridSdk.CollectProfileBetween(_startTimeNs, _endTimeNs, _cocoaTraceId); + var payload = SentryCocoaHybridSdk.Internal.Profiling.CollectBetweenStartTime(_startTimeNs, _endTimeNs, _cocoaTraceId); if (payload is null) { _options.LogWarning("Trace {0} collected profile payload is null", _traceId); diff --git a/src/Sentry/Platforms/Cocoa/CocoaProfilerFactory.cs b/src/Sentry/Platforms/Cocoa/CocoaProfilerFactory.cs index 2d49446bdd..246ad5b516 100644 --- a/src/Sentry/Platforms/Cocoa/CocoaProfilerFactory.cs +++ b/src/Sentry/Platforms/Cocoa/CocoaProfilerFactory.cs @@ -15,8 +15,8 @@ internal CocoaProfilerFactory(SentryOptions options) /// public ITransactionProfiler? Start(ITransactionTracer tracer, CancellationToken cancellationToken) { - var traceId = tracer.TraceId.ToCocoaSentryId(); - var startTime = SentryCocoaHybridSdk.StartProfilerForTrace(traceId); + var traceId = tracer.TraceId.ToCocoaObjCId(); + var startTime = SentryCocoaHybridSdk.Internal.Profiling.StartFor(traceId); return new CocoaProfiler(_options, startTime, tracer.TraceId, traceId); } } diff --git a/src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs b/src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs index 46f8aebf5e..98746e5f15 100644 --- a/src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs +++ b/src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs @@ -112,7 +112,7 @@ public void SetTrace(SentryId traceId, SpanId parentSpanId) { try { - SentryCocoaHybridSdk.SetTrace(traceId.ToCocoaSentryId(), parentSpanId.ToCocoaSpanId()); + SentryCocoaHybridSdk.Internal.SetTrace(traceId.ToCocoaObjCId(), parentSpanId.ToCocoaObjCSpanId()); } finally { diff --git a/src/Sentry/Platforms/Cocoa/Extensions/MiscExtensions.cs b/src/Sentry/Platforms/Cocoa/Extensions/MiscExtensions.cs index 777d09caf1..c23b5bf8d3 100644 --- a/src/Sentry/Platforms/Cocoa/Extensions/MiscExtensions.cs +++ b/src/Sentry/Platforms/Cocoa/Extensions/MiscExtensions.cs @@ -4,9 +4,11 @@ internal static class MiscExtensions { public static SentryId ToSentryId(this CocoaSdk.SentryId sentryId) => new(Guid.Parse(sentryId.SentryIdString)); - public static CocoaSdk.SentryId ToCocoaSentryId(this SentryId sentryId) => new(sentryId.ToString()); - public static SpanId ToSpanId(this CocoaSdk.SentrySpanId spanId) => new(spanId.SentrySpanIdString); - public static CocoaSdk.SentrySpanId ToCocoaSpanId(this SpanId spanId) => new(spanId.ToString()); + // The SentryObjCSDK.internal hybrid API uses its own id types (SentryObjCId / SentryObjCSpanId) + // rather than the Sentry.framework SentryId / SentrySpanId used elsewhere. + public static CocoaSdk.SentryObjCId ToCocoaObjCId(this SentryId sentryId) => new(sentryId.ToString()); + + public static CocoaSdk.SentryObjCSpanId ToCocoaObjCSpanId(this SpanId spanId) => new(spanId.ToString()); } diff --git a/src/Sentry/Platforms/Cocoa/RuntimeAdapter.cs b/src/Sentry/Platforms/Cocoa/RuntimeAdapter.cs index 21e9200201..c7534a0f63 100644 --- a/src/Sentry/Platforms/Cocoa/RuntimeAdapter.cs +++ b/src/Sentry/Platforms/Cocoa/RuntimeAdapter.cs @@ -25,7 +25,7 @@ private RuntimeAdapter() public bool IsMono { get; } = Type.GetType("Mono.Runtime") != null; - public void IgnoreNextSignal(int signal) => SentryCocoaHybridSdk.IgnoreNextSignal(signal); + public void IgnoreNextSignal(int signal) => SentryCocoaHybridSdk.Internal.IgnoreNextSignal(signal); [SecurityCritical] private void OnMarshalManagedException(object sender, MarshalManagedExceptionEventArgs e) => MarshalManagedException?.Invoke(this, e); diff --git a/src/Sentry/Platforms/Cocoa/Sentry.Cocoa.props b/src/Sentry/Platforms/Cocoa/Sentry.Cocoa.props index 3c98f1fc4e..7f02ed04c3 100644 --- a/src/Sentry/Platforms/Cocoa/Sentry.Cocoa.props +++ b/src/Sentry/Platforms/Cocoa/Sentry.Cocoa.props @@ -8,7 +8,7 @@ - + diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 9fd3f62ef5..2b0df2a7e3 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -166,7 +166,7 @@ private static void InitSentryCocoaSdk(SentryOptions options) } // Set hybrid SDK name - SentryCocoaHybridSdk.SetSdkName("sentry.cocoa.dotnet"); + SentryCocoaHybridSdk.Internal.Sdk.Name = "sentry.cocoa.dotnet"; // Now initialize the Cocoa SDK SentryCocoaSdk.StartWithOptions(nativeOptions); From 4f49f46a180a831a59080af625a123a8db593762 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 21 Jul 2026 10:41:49 +1200 Subject: [PATCH 04/22] ci: pin Xcode 26.6 for .NET iOS 26.5 workload The 10.0.302 workload ships the iOS SDK pack 26.5.10301, which requires Xcode 26.6. CI was pinning Xcode 26.5, causing iOS/MacCatalyst builds and device tests to fail. The macos-26 runner already used by these jobs has Xcode 26.6 available, so switch the pin to it. Co-Authored-By: Claude Opus 4.8 --- .github/actions/environment/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/environment/action.yml b/.github/actions/environment/action.yml index 71960bf651..b1f081f3b9 100644 --- a/.github/actions/environment/action.yml +++ b/.github/actions/environment/action.yml @@ -43,7 +43,7 @@ runs: - name: Pin the Xcode Version if: runner.os == 'macOS' shell: bash - run: sudo xcode-select --switch /Applications/Xcode_26.5.app + run: sudo xcode-select --switch /Applications/Xcode_26.6.app # Java 21 is needed by .NET Android - name: Install Java 21 From 4216c8006356d018837fa23b02ea16f2c957e915 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 21 Jul 2026 11:12:43 +1200 Subject: [PATCH 05/22] ci: align codeql-action/analyze to v4.37.1 to match init Dependabot bumped only codeql-action/init to 4.37.1, leaving analyze on 4.37.0. CodeQL requires all steps use the same version, so analyze failed with "Loaded a configuration file for version '4.37.1', but running version '4.37.0'". Pin analyze to the same v4.37.1 SHA. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 087069f34a..6b25744b86 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,6 +49,6 @@ jobs: run: dotnet build Sentry-CI-CodeQL.slnf --no-restore --nologo - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 + uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1 with: category: '/language:csharp' From cc9c9db9ecad92e18ca76293f3cf15d9c35f81c7 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 21 Jul 2026 15:41:27 +1200 Subject: [PATCH 06/22] fix: strip embedded Frameworks from SentryObjC xcframeworks (#5331) xcodebuild embeds each framework's dynamic dependencies under .framework/Frameworks/, producing deeply nested paths (SentryObjC.framework/Frameworks/SentryObjCCompat.framework/Frameworks/Sentry.framework) that exceed NuGet's path-length limit and fail packing with NU5123. We bundle Sentry, SentryObjCCompat and SentryObjC as separate NativeReferences (each embedded into the consuming app and resolved via @rpath), so the nested copies are redundant. Strip them after building the xcframeworks. Co-Authored-By: Claude Opus 4.8 --- scripts/build-sentry-cocoa.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/build-sentry-cocoa.sh b/scripts/build-sentry-cocoa.sh index dce1234791..7e65010c8c 100755 --- a/scripts/build-sentry-cocoa.sh +++ b/scripts/build-sentry-cocoa.sh @@ -132,6 +132,13 @@ for fw in SentryObjC SentryObjCCompat; do done echo "::endgroup::" +# Xcode embeds each framework's dynamic dependencies under .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). Strip them; the frameworks resolve each other via @rpath at the app level. +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 \; From e6bf220dda4745bcfa9775a9410a595dc32d7807 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 21 Jul 2026 15:41:28 +1200 Subject: [PATCH 07/22] fix: copy immutable profile payload before mutating (#5331) The new SentryObjCSDK.internal profiling API returns an immutable NSDictionary, whereas the old PrivateSentrySDKOnly.collectProfileBetween returned a mutable one. CocoaProfiler.Collect mutates the payload (adds transaction id/trace_id/ name/timestamp), which threw NotSupportedException on the immutable dictionary and failed Profiler_RunningUnderFullClient_SendsProfileData. Copy it into an NSMutableDictionary first. Co-Authored-By: Claude Opus 4.8 --- src/Sentry/Platforms/Cocoa/CocoaProfiler.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs index 6a008ed8ba..c846504d98 100644 --- a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs +++ b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs @@ -36,14 +36,18 @@ public void Finish() public ISerializable? Collect(SentryTransaction transaction) { - var payload = SentryCocoaHybridSdk.Internal.Profiling.CollectBetweenStartTime(_startTimeNs, _endTimeNs, _cocoaTraceId); - if (payload is null) + var collected = SentryCocoaHybridSdk.Internal.Profiling.CollectBetweenStartTime(_startTimeNs, _endTimeNs, _cocoaTraceId); + if (collected is null) { _options.LogWarning("Trace {0} collected profile payload is null", _traceId); return null; } _options.LogDebug("Trace {0} profile payload collected", _traceId); + // The SentryObjCSDK.internal profiling API returns an immutable NSDictionary (the old + // PrivateSentrySDKOnly API returned a mutable one), so copy it before mutating below. + var payload = (NSMutableDictionary)collected.MutableCopy(); + var payloadTx = payload["transaction"]?.MutableCopy() as NSMutableDictionary; if (payloadTx is null) { From 2050c34ace9634658ed807a7824961eaddaf88d3 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 22 Jul 2026 18:22:34 +1200 Subject: [PATCH 08/22] fix: expect SentryObjC debug symbols in iOS symbol-upload test (#5331) The app bundle now contains the SentryObjC and SentryObjCCompat frameworks alongside Sentry.framework, so sentry-cli uploads their debug symbols too. Add them to the expected upload list. Co-Authored-By: Claude Opus 4.8 --- integration-test/cli.Tests.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration-test/cli.Tests.ps1 b/integration-test/cli.Tests.ps1 index d03d5c235a..e02e69b66d 100644 --- a/integration-test/cli.Tests.ps1 +++ b/integration-test/cli.Tests.ps1 @@ -191,7 +191,9 @@ Describe 'MAUI ()' -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]*'; From 55ff0b8580666c952cb0d36f28d983b065d3b042 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 22 Jul 2026 20:15:53 +1200 Subject: [PATCH 09/22] ref: remove the PrivateSentrySDKOnly binding (#5331) Phase 3: all call sites migrated to SentryObjCSDK.internal in the previous phase, so drop the deprecated PrivateSentrySDKOnly interface entirely - the header no longer feeds Objective Sharpie, the patch rules that shaped it are gone, and the regenerated ApiDefinitions.cs loses the interface (pure removal, no other changes). sentry-cocoa removes the class in its next major. Co-Authored-By: Claude Opus 4.8 --- scripts/generate-cocoa-bindings.ps1 | 1 - scripts/patch-cocoa-bindings.cs | 13 -- src/Sentry.Bindings.Cocoa/ApiDefinitions.cs | 166 -------------------- 3 files changed, 180 deletions(-) diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 369deb2e01..789a3a1330 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -173,7 +173,6 @@ sharpie bind -sdk $iPhoneSdkVersion ` -scope "$CocoaSdkPath" ` "$HeadersPath/Sentry.h" ` "$HeadersPath/Sentry-Swift.h" ` - "$HeadersPath/PrivateSentrySDKOnly.h" ` "$HeadersPath/SentryObjCSDK.h" ` "$HeadersPath/SentryObjCInternalApi.h" ` "$HeadersPath/SentryObjCInternalSdkApi.h" ` diff --git a/scripts/patch-cocoa-bindings.cs b/scripts/patch-cocoa-bindings.cs index eb9ce94fc7..7abc336696 100644 --- a/scripts/patch-cocoa-bindings.cs +++ b/scripts/patch-cocoa-bindings.cs @@ -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") @@ -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 @@ -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 @@ -116,8 +106,6 @@ .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") @@ -135,7 +123,6 @@ .KeepMethods("SentryObjCInternalApi", "SetTrace", "IgnoreNextSignal") .KeepInterfaces( "ISentryRRWebEvent", - "PrivateSentrySDKOnly", "SentryAttachment", "SentryBaggage", "SentryBreadcrumb", diff --git a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs index 937113e871..f9d79d19db 100644 --- a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs +++ b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs @@ -1517,172 +1517,6 @@ interface SentryUser : SentrySerializable nuint Hash { get; } } -// @interface PrivateSentrySDKOnly : NSObject -[BaseType(typeof(NSObject))] -[Internal] -interface PrivateSentrySDKOnly -{ - - // +(void)setSdkName:(NSString * _Nonnull)sdkName andVersionString:(NSString * _Nonnull)versionString; - [Static] - [Export("setSdkName:andVersionString:")] - void SetSdkName(string sdkName, string versionString); - - // +(void)setSdkName:(NSString * _Nonnull)sdkName; - [Static] - [Export("setSdkName:")] - void SetSdkName(string sdkName); - - // +(NSString * _Nonnull)getSdkName; - [Static] - [Export("getSdkName")] - string SdkName { get; } - - // +(NSString * _Nonnull)getSdkVersionString; - [Static] - [Export("getSdkVersionString")] - string SdkVersionString { get; } - - // +(void)addSdkPackage:(NSString * _Nonnull)name version:(NSString * _Nonnull)version; - [Static] - [Export("addSdkPackage:version:")] - void AddSdkPackage(string name, string version); - - // +(NSDictionary * _Nonnull)getExtraContext; - [Static] - [Export("getExtraContext")] - NSDictionary ExtraContext { get; } - - // +(void)setTrace:(SentryId * _Nonnull)traceId spanId:(SentrySpanId * _Nonnull)spanId; - [Static] - [Export("setTrace:spanId:")] - void SetTrace(SentryId traceId, SentrySpanId spanId); - - // +(uint64_t)startProfilerForTrace:(SentryId * _Nonnull)traceId; - [Static] - [Export("startProfilerForTrace:")] - ulong StartProfilerForTrace(SentryId traceId); - - // +(NSMutableDictionary * _Nullable)collectProfileBetween:(uint64_t)startSystemTime and:(uint64_t)endSystemTime forTrace:(SentryId * _Nonnull)traceId; - [Static] - [Export("collectProfileBetween:and:forTrace:")] - [return: NullAllowed] - NSMutableDictionary CollectProfileBetween(ulong startSystemTime, ulong endSystemTime, SentryId traceId); - - // +(void)discardProfilerForTrace:(SentryId * _Nonnull)traceId; - [Static] - [Export("discardProfilerForTrace:")] - void DiscardProfilerForTrace(SentryId traceId); - - // @property (readonly, copy, nonatomic, class) NSString * _Nonnull installationID; - [Static] - [Export("installationID")] - string InstallationID { get; } - - // @property (readonly, copy, nonatomic, class) SentryOptions * _Nonnull options; - [Static] - [Export("options", ArgumentSemantic.Copy)] - SentryOptions Options { get; } - - // @property (assign, nonatomic, class) BOOL framesTrackingMeasurementHybridSDKMode; - [Static] - [Export("framesTrackingMeasurementHybridSDKMode")] - bool FramesTrackingMeasurementHybridSDKMode { get; set; } - - // @property (readonly, assign, nonatomic, class) BOOL isFramesTrackingRunning; - [Static] - [Export("isFramesTrackingRunning")] - bool IsFramesTrackingRunning { get; } - - // @property (readonly, assign, nonatomic, class) SentryScreenFrames * _Nonnull currentScreenFrames; - [Static] - [Export("currentScreenFrames", ArgumentSemantic.Assign)] - SentryScreenFrames CurrentScreenFrames { get; } - - // +(NSArray * _Nullable)captureScreenshots; - [Static] - [Export("captureScreenshots")] - [return: NullAllowed] - NSData[] CaptureScreenshots(); - - // +(NSData * _Nullable)captureViewHierarchy; - [Static] - [Export("captureViewHierarchy")] - [return: NullAllowed] - NSData CaptureViewHierarchy(); - - // +(void)setCurrentScreen:(NSString * _Nullable)screenName; - [Static] - [Export("setCurrentScreen:")] - void SetCurrentScreen([NullAllowed] string screenName); - - // +(void)configureSessionReplayWith:(id _Nullable)breadcrumbConverter screenshotProvider:(id _Nullable)screenshotProvider; - [Static] - [Export("configureSessionReplayWith:screenshotProvider:")] - void ConfigureSessionReplayWith([NullAllowed] SentryReplayBreadcrumbConverter breadcrumbConverter, [NullAllowed] SentryViewScreenshotProvider screenshotProvider); - - // +(void)captureReplay; - [Static] - [Export("captureReplay")] - void CaptureReplay(); - - // +(NSString * _Nullable)getReplayId; - [Static] - [NullAllowed, Export("getReplayId")] - string ReplayId { get; } - - // +(void)addReplayIgnoreClasses:(NSArray * _Nonnull)classes; - [Static] - [Export("addReplayIgnoreClasses:")] - void AddReplayIgnoreClasses(Class[] classes); - - // +(void)addReplayRedactClasses:(NSArray * _Nonnull)classes; - [Static] - [Export("addReplayRedactClasses:")] - void AddReplayRedactClasses(Class[] classes); - - // +(void)setIgnoreContainerClass:(Class _Nonnull)containerClass; - [Static] - [Export("setIgnoreContainerClass:")] - void SetIgnoreContainerClass(Class containerClass); - - // +(void)setRedactContainerClass:(Class _Nonnull)containerClass; - [Static] - [Export("setRedactContainerClass:")] - void SetRedactContainerClass(Class containerClass); - - // +(void)setReplayTags:(NSDictionary * _Nonnull)tags; - [Static] - [Export("setReplayTags:")] - void SetReplayTags(NSDictionary tags); - - // +(SentryUser * _Nonnull)userWithDictionary:(NSDictionary * _Nonnull)dictionary; - [Static] - [Export("userWithDictionary:")] - SentryUser UserWithDictionary(NSDictionary dictionary); - - // +(SentryBreadcrumb * _Nonnull)breadcrumbWithDictionary:(NSDictionary * _Nonnull)dictionary; - [Static] - [Export("breadcrumbWithDictionary:")] - SentryBreadcrumb BreadcrumbWithDictionary(NSDictionary dictionary); - - // +(SentryOptions * _Nullable)optionsWithDictionary:(NSDictionary * _Nonnull)options didFailWithError:(NSError * _Nullable * _Nullable)error; - [Static] - [Export("optionsWithDictionary:didFailWithError:")] - [return: NullAllowed] - SentryOptions OptionsWithDictionary(NSDictionary options, [NullAllowed] out NSError error); - - // +(void)setLogOutput:(void (^ _Nonnull)(NSString * _Nonnull))output; - [Static] - [Export("setLogOutput:")] - void SetLogOutput(Action output); - - // +(void)ignoreNextSignal:(int)signum; - [Static] - [Export("ignoreNextSignal:")] - void IgnoreNextSignal(int signum); -} - // @interface SentryOptions : NSObject [BaseType(typeof(NSObject))] [Internal] From 4689d205c1ea96b3d7526a7989436828824bbd2d Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 10:31:39 +1200 Subject: [PATCH 10/22] Make code comments more concise Co-authored-by: James Crosswell --- scripts/generate-cocoa-bindings.ps1 | 5 +---- scripts/patch-cocoa-bindings.cs | 4 +--- src/Sentry/Platforms/Cocoa/CocoaProfiler.cs | 3 +-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 789a3a1330..216ddbb72c 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -164,15 +164,12 @@ else } # Generate bindings -# The SentryObjC* headers expose the structured hybrid API (SentryObjCSDK.internal) that replaces -# the deprecated PrivateSentrySDKOnly. We only bind the entry point (SentryObjCSDK), the internal -# API surface, and the two id types the .NET wrappers pass; patch-cocoa-bindings.cs trims everything -# else these headers pull in via forward declarations. Write-Output 'Generating bindings with Objective Sharpie.' sharpie bind -sdk $iPhoneSdkVersion ` -scope "$CocoaSdkPath" ` "$HeadersPath/Sentry.h" ` "$HeadersPath/Sentry-Swift.h" ` + # SentryObjC.h* exposes the structured hybrid API (SentryObjCSDK.internal) "$HeadersPath/SentryObjCSDK.h" ` "$HeadersPath/SentryObjCInternalApi.h" ` "$HeadersPath/SentryObjCInternalSdkApi.h" ` diff --git a/scripts/patch-cocoa-bindings.cs b/scripts/patch-cocoa-bindings.cs index 7abc336696..e934e2f954 100644 --- a/scripts/patch-cocoa-bindings.cs +++ b/scripts/patch-cocoa-bindings.cs @@ -112,13 +112,11 @@ // SentryUserFeedbackConfiguration is not whitelisted .RemoveProperty("SentryOptions", "ConfigureUserFeedback") .RemoveProperty("SentryOptions", "UserFeedbackConfiguration") - // SentryObjCSDK.internal is the entry point to the new hybrid API (replacing PrivateSentrySDKOnly). + // 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", "*") - // On the internal API the .NET wrappers only use the SDK-metadata and profiling sub-objects plus - // setTrace / ignoreNextSignal. The remaining accessors return sub-API/options types that aren't bound. .KeepProperties("SentryObjCInternalApi", "Sdk", "Profiling") .KeepMethods("SentryObjCInternalApi", "SetTrace", "IgnoreNextSignal") .KeepInterfaces( diff --git a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs index c846504d98..98e368357f 100644 --- a/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs +++ b/src/Sentry/Platforms/Cocoa/CocoaProfiler.cs @@ -44,8 +44,7 @@ public void Finish() } _options.LogDebug("Trace {0} profile payload collected", _traceId); - // The SentryObjCSDK.internal profiling API returns an immutable NSDictionary (the old - // PrivateSentrySDKOnly API returned a mutable one), so copy it before mutating below. + // The SentryObjCSDK.internal profiling API returns an immutable NSDictionary, so copy it before mutating below. var payload = (NSMutableDictionary)collected.MutableCopy(); var payloadTx = payload["transaction"]?.MutableCopy() as NSMutableDictionary; From e9dad162515be92c91c17c545a19cc036941a6bd Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 10:35:29 +1200 Subject: [PATCH 11/22] Apply suggestion from @jamescrosswell --- scripts/build-sentry-cocoa.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-sentry-cocoa.sh b/scripts/build-sentry-cocoa.sh index 7e65010c8c..748e8de8e3 100755 --- a/scripts/build-sentry-cocoa.sh +++ b/scripts/build-sentry-cocoa.sh @@ -136,7 +136,7 @@ echo "::endgroup::" # 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). Strip them; the frameworks resolve each other via @rpath at the app level. +# 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 From 1cd8cdb17adb199d265432c4dbc0868d2badbfcf Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 10:43:49 +1200 Subject: [PATCH 12/22] docs: clarify that NativeReference order is not load-bearing (#5331) The previous comment implied the SentryObjCCompat/SentryObjC order was a requirement. These are dynamic frameworks whose inter-dependencies are recorded in their own Mach-O load commands and resolved by dyld via @rpath at load time, so the item order has no functional effect - it's dependency-first purely for readability. Co-Authored-By: Claude Opus 4.8 --- src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index 1fd15ada4f..aa50ed3db9 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -59,7 +59,9 @@ - + From ba5e065d172b9838a90582b659eba209b328317a Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 10:47:36 +1200 Subject: [PATCH 13/22] Removed redundant comments Co-authored-by: James Crosswell --- src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index aa50ed3db9..710a3bda50 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -25,8 +25,7 @@ $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\Sentry.xcframework + Sentry.framework above; build-sentry-cocoa.sh builds them from source. → $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjC.xcframework $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjCCompat.xcframework ../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/**/*.h @@ -59,9 +58,6 @@ - From 6da006399ffff8c84cd6e154c3235b025dd2baa5 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 10:53:20 +1200 Subject: [PATCH 14/22] fix: repair unterminated XML comment in Sentry.Bindings.Cocoa.csproj The comment's closing --> was accidentally replaced with a Unicode arrow, leaving the comment unterminated so the project file failed to load (NETSDK: "An XML comment cannot contain '--'"), which broke every CI job at environment setup. Co-Authored-By: Claude Opus 4.8 --- src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index 710a3bda50..e00383936b 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -25,7 +25,7 @@ $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\Sentry.xcframework $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjC.xcframework $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjCCompat.xcframework ../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/**/*.h From 5f06ee9d20f1df2d9942ed923d1a0dafab64bc4c Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 11:16:36 +1200 Subject: [PATCH 15/22] fix: move comment out of the sharpie backtick continuation PowerShell terminates a backtick line-continuation at a comment line, so the inline comment split the sharpie bind invocation in two and the script failed to parse (ParserError at the next header argument), breaking bindings generation. Keep the comment, but above the command. Co-Authored-By: Claude Opus 4.8 --- scripts/generate-cocoa-bindings.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 216ddbb72c..41e900c1a9 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -164,12 +164,12 @@ 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" ` - # SentryObjC.h* exposes the structured hybrid API (SentryObjCSDK.internal) "$HeadersPath/SentryObjCSDK.h" ` "$HeadersPath/SentryObjCInternalApi.h" ` "$HeadersPath/SentryObjCInternalSdkApi.h" ` From 5025efe38ae3d28488debea7427986d3f0b037af Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 13:51:35 +1200 Subject: [PATCH 16/22] ref: remove the pre-built Cocoa SDK download path (#5331) The download path could only supply Sentry-Dynamic.xcframework - it had no way to provide the SentryObjC/SentryObjCCompat frameworks the bindings now require (there is no non-duplicating released artifact), so if ever activated it would produce a build that fails at runtime on any hybrid-API use. It was already dormant: modules/sentry-cocoa.properties does not exist, and CI checks out the submodule, so the source build is the only path actually exercised. Remove _DownloadCocoaSDK, the released-builds property group and the SanitizeSentryCocoaFramework target (the source build already strips headers, modules and dSYMs), simplify the bindings-generation script accordingly, and fail with a clear error if the submodule is missing. Update docs, solution items and workflow path filters that referenced sentry-cocoa.properties. Co-Authored-By: Claude Opus 4.8 --- .generated.NoMobile.slnx | 1 - .github/workflows/device-tests-android.yml | 1 - .github/workflows/device-tests-ios.yml | 1 - CONTRIBUTING.md | 30 ++++---- Sentry.slnx | 1 - scripts/generate-cocoa-bindings.ps1 | 15 +--- .../Sentry.Bindings.Cocoa.csproj | 71 +++---------------- 7 files changed, 25 insertions(+), 95 deletions(-) diff --git a/.generated.NoMobile.slnx b/.generated.NoMobile.slnx index d6fd58d14f..babff9ea4d 100644 --- a/.generated.NoMobile.slnx +++ b/.generated.NoMobile.slnx @@ -54,7 +54,6 @@ - diff --git a/.github/workflows/device-tests-android.yml b/.github/workflows/device-tests-android.yml index 5a5fe3c5c0..ec35ae3f12 100644 --- a/.github/workflows/device-tests-android.yml +++ b/.github/workflows/device-tests-android.yml @@ -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' diff --git a/.github/workflows/device-tests-ios.yml b/.github/workflows/device-tests-ios.yml index 7d7bfdb0b1..749827140b 100644 --- a/.github/workflows/device-tests-ios.yml +++ b/.github/workflows/device-tests-ios.yml @@ -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' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc60035091..8b438b7fcc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -194,27 +194,23 @@ 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: ```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 +$ cd modules/sentry-cocoa +$ git fetch origin && git checkout +$ cd ../.. && dotnet build ... # rebuilds the Cocoa SDK from the new ref ``` ## Local Sentry Android SDK checkout diff --git a/Sentry.slnx b/Sentry.slnx index d6fd58d14f..babff9ea4d 100644 --- a/Sentry.slnx +++ b/Sentry.slnx @@ -54,7 +54,6 @@ - diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 41e900c1a9..e1e368d73a 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -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" diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index e00383936b..d8ea44d13b 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -8,20 +8,13 @@ true .NET Bindings for the Sentry Cocoa SDK ..\..\modules\sentry-cocoa\ - $(MSBuildThisFileDirectory)..\..\modules\sentry-cocoa.properties - $(SentryCocoaCache)Sentry.framework\ $(NoWarn);CS0108 - - - $([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText('$(SentryCocoaProperties)')), 'version\s*=\s*([^\s]+)').Groups[1].Value) - $(SentryCocoaCache)Sentry-$(SentryCocoaVersion).xcframework - $(SentryCocoaProperties);../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaFrameworkHeaders)**/*.h - - - + $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\Sentry.xcframework - - - - - - - - - - - - - - - - - - - - - - - - - - - + DependsOnTargets="_BuildCocoaSDK;_GenerateSentryCocoaBindings" + Condition="$([MSBuild]::IsOSPlatform('OSX'))"> + + - - + @@ -158,15 +114,6 @@ - - - - - - - - From a6dbf0b9ca5d818dd5a961f1818142e8d2a22128 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 16:22:54 +1200 Subject: [PATCH 17/22] fix: scope Hot Restart simulator-strip to this package's frameworks (#5331) buildTransitive targets are imported into consuming apps, where ReferenceCopyLocalPaths spans every referenced package - the broadened '.xcframework' match could strip other packages' simulator resources during Hot Restart builds. Enumerate our three frameworks explicitly instead (note 'Sentry.xcframework' is not a substring of 'SentryObjC.xcframework', so all three clauses are required). Co-Authored-By: Claude Opus 4.8 --- .../buildTransitive/Sentry.Bindings.Cocoa.targets | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets index 54c4d34e05..0a61c4e0fd 100644 --- a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets +++ b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets @@ -45,8 +45,9 @@ --> - - + + From df02fb7921a4f325c0456eec82f3509978d99d01 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 16:26:25 +1200 Subject: [PATCH 18/22] Apply suggestion from @jamescrosswell --- .../buildTransitive/Sentry.Bindings.Cocoa.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets index 0a61c4e0fd..2a15428c60 100644 --- a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets +++ b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets @@ -45,8 +45,8 @@ --> - + From 1e8b02a0f868e8953a16db6927997b8e32a45697 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 16:28:50 +1200 Subject: [PATCH 19/22] ref: run the missing-submodule check before the Cocoa build targets The check previously ran in the _SetupCocoaSDK body, after its dependencies. It was still reached in practice (with no submodule the generation target is skipped for having no inputs - verified empirically), but that relied on a non-obvious MSBuild skip rule. Give the check its own target that runs first in the dependency chain so the ordering is structural. Co-Authored-By: Claude Opus 4.8 --- src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index d8ea44d13b..6f23ff8266 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -74,13 +74,15 @@ - + + + Date: Thu, 23 Jul 2026 16:32:08 +1200 Subject: [PATCH 20/22] ref: drop unused SentryObjC enums from the generated bindings (#5331) Sharpie emits SentryObjCFeedbackSource / SentryObjCLastRunStatus because the SentryObjC headers reference them, but the members that used them are trimmed by the patch script, leaving dead enums. Add a RemoveEnum filter and drop all SentryObjC* enums - the hybrid-API surface we bind uses none. Co-Authored-By: Claude Opus 4.8 --- scripts/patch-cocoa-bindings.cs | 10 ++++++++++ src/Sentry.Bindings.Cocoa/StructsAndEnums.cs | 15 --------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/scripts/patch-cocoa-bindings.cs b/scripts/patch-cocoa-bindings.cs index e934e2f954..b9edea2de5 100644 --- a/scripts/patch-cocoa-bindings.cs +++ b/scripts/patch-cocoa-bindings.cs @@ -119,6 +119,9 @@ .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", "SentryAttachment", @@ -251,6 +254,13 @@ public static CompilationUnitSyntax RemoveClass( return root.RemoveByPredicate(node => node.Identifier.Matches(name)); } + public static CompilationUnitSyntax RemoveEnum( + this CompilationUnitSyntax root, + string name) + { + return root.RemoveByPredicate(node => node.Identifier.Matches(name)); + } + public static CompilationUnitSyntax RemoveDelegate( this CompilationUnitSyntax root, string name) diff --git a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs index 246e6d95d5..589f710723 100644 --- a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs +++ b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs @@ -175,18 +175,3 @@ internal enum SentryTransactionNameSource : long Component = 4, Task = 5 } - -[Native] -internal enum SentryObjCFeedbackSource : long -{ - Widget = 0, - Custom -} - -[Native] -internal enum SentryObjCLastRunStatus : long -{ - Unknown = 0, - DidNotCrash, - DidCrash -} From 1163b236090a327d4c6cfec348b72fe0aa5a1e48 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 23 Jul 2026 16:39:52 +1200 Subject: [PATCH 21/22] fix: include the build script's hash in the Cocoa build stamp (#5331) The early-exit stamp only keyed on the sentry-cocoa submodule SHA, so a Carthage cache produced by an older version of this script (same submodule SHA, but without the SentryObjC/SentryObjCCompat frameworks) would be treated as up to date and the new frameworks would never be built. Key the stamp on the submodule SHA plus this script's own checksum - mirroring the cache key already used for sentry-native in CI - so any recipe change invalidates cached output. Co-Authored-By: Claude Opus 4.8 --- scripts/build-sentry-cocoa.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/build-sentry-cocoa.sh b/scripts/build-sentry-cocoa.sh index 748e8de8e3..4c78b66728 100755 --- a/scripts/build-sentry-cocoa.sh +++ b/scripts/build-sentry-cocoa.sh @@ -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 @@ -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 @@ -149,7 +154,7 @@ find Carthage/Build-ios/SentryObjCCompat.xcframework/ios-arm64 -name '*.h' -exec 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 From 6e5753956fb03c626e9677566cddc1bbe09bbcd7 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Fri, 24 Jul 2026 12:45:51 +1200 Subject: [PATCH 22/22] ref: simplify Hot Restart strip regex; document submodule-ref staging - Collapse the three per-framework Contains() clauses into one regex (jpnurmi's suggestion), matching Sentry/SentryObjC/SentryObjCCompat's simulator slices. Uses [\\/] for the path separator so it's robust and verifiable off-Windows; validated in MSBuild that it strips exactly those three and leaves device slices and other packages' xcframeworks. - CONTRIBUTING: note that building against a different Cocoa ref requires staging the submodule gitlink, since the solution build's automatic git submodule update (before.Sentry.sln.targets) otherwise reverts it. Co-Authored-By: Claude Opus 4.8 --- CONTRIBUTING.md | 11 +++++++---- .../buildTransitive/Sentry.Bindings.Cocoa.targets | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b438b7fcc..7553b5caad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -205,12 +205,15 @@ copy of the SDK alongside `Sentry.framework` (see [#5331](https://github.com/getsentry/sentry-dotnet/issues/5331)). To build against a different Cocoa SDK version, check out the desired ref in the -submodule: +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 -$ cd modules/sentry-cocoa -$ git fetch origin && git checkout -$ cd ../.. && dotnet build ... # rebuilds the Cocoa SDK from the new ref +$ git -C modules/sentry-cocoa fetch origin +$ git -C modules/sentry-cocoa checkout +$ 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 diff --git a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets index 2a15428c60..fcedf5b1b7 100644 --- a/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets +++ b/src/Sentry.Bindings.Cocoa/buildTransitive/Sentry.Bindings.Cocoa.targets @@ -45,9 +45,9 @@ --> - - + +