Skip to content

feat(objc): SentryObjC wrapper SDK with compat architecture#7918

Merged
philprime merged 200 commits into
mainfrom
philprime/objc-wrapper-sdk-6342-2
May 29, 2026
Merged

feat(objc): SentryObjC wrapper SDK with compat architecture#7918
philprime merged 200 commits into
mainfrom
philprime/objc-wrapper-sdk-6342-2

Conversation

@philprime

@philprime philprime commented May 19, 2026

Copy link
Copy Markdown
Member

SentryObjC adds an experimental pure Objective-C entry point for ObjC and ObjC++ consumers that cannot enable Clang modules or import generated Swift headers. It keeps the main SDK unchanged while exposing startup, options, scope/event types, session replay, feedback, metrics, logging, and related APIs through uniform SentryObjC* types.

Closes #6342. See also #4543.

Architecture

SentryObjC now follows the two-target design in develop-docs/SENTRY-OBJC.md:

ObjC / ObjC++ consumer
  -> SentryObjC (hand-written Foundation-only ObjC headers)
  -> SentryObjCCompat (per-type Swift wrappers using internal import)
  -> SentryObjCInternal / Sentry

Sources/SentryObjC/Public/ is the public ABI anchor: hand-written headers, uniform SentryObjC* names, no SDK imports, no -Swift.h, and matching platform guards through SentryObjCDefines.h. Sources/SentryObjCCompat/ implements matching @objc(SentryObjCFoo) wrappers that delegate to the SDK and convert callback boundaries so Objective-C users stay on wrapper types.

Distribution And Validation

The SPM product exposes one SentryObjC library backed by SentryObjC -> SentryObjCCompat -> SentryObjCInternal, and the xcframework release pipeline builds SentryObjC-Dynamic.xcframework.zip. This branch also adds API extraction for sdk_api_objc.json, compat drift detection through sdk_api_objc.diff.json, and the iOS-ObjectiveCpp-NoModules sample as an integration check.

Testing

  • make build-framework-objc
  • make build-sentryobjc-xcframework-local SDKS=iphonesimulator
  • make build-sample-iOS-ObjectiveCpp-NoModules
  • make test-ios ONLY_TESTING=SentryObjCCompatTests
  • Checked that consumer-facing SentryObjC headers do not include generated *-Swift.h headers.
  • Full CI pass pending ready-to-merge.

Known Gaps

  • ObjC header and Swift wrapper drift detection is partially automated, but it does not catch every mismatch category yet.
  • A dedicated CI guard should still enforce the no--Swift.h boundary for SentryObjC.h compiled with -fmodules=NO.

Next Steps

  • Remove commented out .binaryTarget(..) target blocks in Package.swift files using a temporary patch approach.
  • Expand verification tooling for linking without UI frameworks.
  • Create public user-facing documentation.

philprime and others added 30 commits March 4, 2026 16:24
Add a pure Objective-C SDK wrapper that mirrors the Sentry public API so it can be used from ObjC++ without modules (e.g. for React Native, Haxe, custom build systems). Includes:

- SentryObjC product and target in Package.swift
- Re-declared headers for all public types in Sources/SentryObjC/Public/
- Wrapper implementations for Swift-only types (Unit, Metric, MetricValue, AttributeContent, RedactRegionType)
- iOS-ObjectiveCpp-NoModules sample using SentryObjC
- sdk_objc_api.json generation via extract-objc-api.py for API stability CI
- Makefile targets: build-spm-objc, verify-objc, generate-objc-api

Refs GH-6342
Add detailed documentation to core SentryObjC public APIs following
Objective-C documentation best practices:
- Document all properties with their purpose and behavior
- Document all methods with parameters and return values
- Add class-level documentation explaining usage context
- Include notes about automatic behavior and warnings where applicable

Files documented:
- SentryObjCSDK: Main SDK entry point
- SentryObjCOptions: Configuration options
- SentryObjCEvent: Event data structure
- SentryObjCScope: Contextual data container
- SentryObjCBreadcrumb: Breadcrumb trail
- SentryObjCUser: User identification
- SentryObjCSpanProtocol: Performance tracing protocol

Also adds changelog entry explaining the purpose of the SentryObjC
wrapper SDK.
Add comprehensive documentation to exception, attachment, message,
and tracing-related classes:
- SentryObjCException: Exception information
- SentryObjCAttachment: File attachments
- SentryObjCMessage: Log messages
- SentryObjCSpanContext: Span trace context
- SentryObjCTransactionContext: Transaction context

All classes now include detailed property and method documentation
following Objective-C best practices.
Add comprehensive documentation to:
- SentryObjCFrame: Stack frame with source location and context
- SentryObjCStacktrace: Stack trace with frames and registers
- SentryObjCThread: Thread information and crash state
- SentryObjCMechanism: Error mechanism and handling context
- SentryObjCDebugMeta: Debug symbols and binary metadata
- SentryObjCRequest: HTTP request information
- SentryObjCGeo: Geographical location data

All classes now include detailed property and method documentation.
Add comprehensive documentation to:
- SentryObjCReplayOptions: Session replay configuration with privacy controls
- SentryObjCReplayApi: Runtime replay control and masking API
- SentryObjCSamplingContext: Context for dynamic trace sampling decisions

All properties and methods now include detailed documentation explaining
their purpose, behavior, and usage.
Remove the conditional check for sdk_objc_api.json existence since an
empty baseline file will be added to main in a follow-up PR. This
simplifies the workflow logic.
Keep the original problem description explaining why modules don't work
in ObjC++ projects, then show how SentryObjC solves this issue. This
provides better context for readers to understand why SentryObjC exists.

- Restore "Problem" section describing module import failures
- Add "Solution: SentryObjC" section explaining how it solves the issue
- List key differences from the main Sentry framework
- Reference original issue #4543 and solution PR #6342
Sync with main to include latest changes and adopt new sample
structure using projectReferences instead of SPM packages.
Replace Python-based regex parsing with clang AST dump and jq
processing. The new approach:

- Uses xcrun clang -ast-dump=json for reliable parsing
- Extracts declarations via jq queries on intermediate files
- Outputs structured JSON objects instead of string signatures
- Migrates from Python to pure bash/jq pipeline

Also standardize filename to sdk_api_objc.json to match the
sdk_api.json and sdk_api_sentryswiftui.json naming convention.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Include the iOS-ObjectiveCpp-NoModules sample in CI build verification
to ensure it continues to build successfully with the SentryObjC wrapper.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add the SentryObjC product and target to Package@swift-6.1.swift so
the sample can reference it. Also revert iOS-ObjectiveCpp-NoModules
sample to use SPM packages instead of projectReferences since
SentryObjC is an SPM product, not an Xcode project target.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Complete documentation for:
- SentryObjCAppStartMeasurement (app start types and timestamps)
- SentryObjCAttributeContent (typed attribute values)
- SentryObjCBaggage (distributed tracing propagation)
- SentryObjCError (SDK error codes and helpers)
- SentryObjCLogger (structured logging interface)
- SentryObjCMechanismContext (crash metadata)
- SentryObjCMetric (custom performance metrics)
- SentryObjCMetricValue (metric value types)
- SentryObjCNSError (serializable error representation)

All public types, properties, methods, and enum values now have
comprehensive documentation following Objective-C best practices.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The SentryObjC product depends on SentryCppHelper, but it was only
defined in the binary targets section. Add it to the compile-from-source
targets array so it's available when building SentryObjC from source.

Fixes SPM package resolution error:
target 'SentryCppHelper' referenced in product 'SentryObjC' could not be found

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add SentryObjCSDK.m implementation that forwards all method calls to
SentrySDKInternal. This enables SentryObjC to work in projects with
CLANG_ENABLE_MODULES=NO, where Swift's @objc bridging is unavailable.

The wrapper provides a pure Objective-C implementation of the SentrySDK
class, making all SDK methods accessible via #import <SentryObjC.h>
without requiring modules or Swift bridging.

Update iOS-ObjectiveCpp-NoModules sample to use the corrected import
style (#import <SentryObjC.h> instead of <SentryObjC/SentryObjC.h>)
and add module.modulemap for SPM module resolution.

Refs #6342
SentryCppHelper must remain in the initial targets array because the
binary distribution products (Sentry, SentrySwiftUI, etc.) depend on it.

Moving it to the compile-from-source section broke those binary products.
The target can be safely referenced by both binary and source products.
Rename the wrapper class from SentrySDK to SentryObjCSDK to:
- Avoid naming conflicts with the Swift SentrySDK class
- Be consistent with other SentryObjC types (SentryObjCAttributeContent, etc.)
- Make it clearer this is the ObjC wrapper, not the main SDK class

Update sample app and README to use the new class name.
The Swift compiler was exporting SentryObjCBridge with a mangled name
(_TtC16SentryObjCBridge16SentryObjCBridge), but Objective-C forward
declarations expected the plain class name (_OBJC_CLASS_$_SentryObjCBridge).

This caused linker errors when building the iOS-ObjectiveCpp-NoModules
sample app with CLANG_ENABLE_MODULES=NO.

Add @objc(SentryObjCBridge) attribute to ensure the Swift class is
exported with the correct Objective-C symbol name.

Also refactored convertObjCAttributesToSwift to reduce cyclomatic
complexity and function body length by extracting conversion logic
into a separate helper method.

Refs #6342

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Addresses critical thread safety and implementation issues in the
SentryObjC wrapper SDK:

- Add atomic operations for _insideReportException flag to prevent race
  conditions when multiple threads throw exceptions simultaneously
- Implement replay API via bridge instead of returning nil, enabling
  session replay functionality in no-modules context
- Add SentryObjCBridge to Swift 6.1 package manifest to fix linker errors
- Use dispatch_once for metrics API lazy initialization instead of
  +initialize to prevent initialization order issues
- Fix const pointer placement in header (NSString *const vs const *)
- Improve attribute validation robustness with silent failure handling
- Add test coverage for replay API, invalid attributes, and singleton

All fixes verified with make format, analyze, build-ios, and sample build.

Refs #6342
Remove SentryCppHelper from SentryObjC product targets to fix SPM
resolution errors. SentryObjC is a compile-from-source product like
SentrySPM and should not include the C++ helper target (which is only
needed for binary distribution products).

Also fix documentation warnings in SentryObjC headers by removing
@ prefix from YES/NO literals in @c commands, and disable WIP test
that requires proper Xcode project integration.

Changes:
- Remove SentryCppHelper from SentryObjC product in Package.swift
- Remove SentryCppHelper from SentryObjC product in Package@swift-6.1.swift
- Fix @c @YES/@no to @c YES/NO in SentryObjCFrame.h
- Fix @c @YES/@no to @c YES/NO in SentryObjCMechanism.h
- Fix @c @YES/@no to @c YES/NO in SentryObjCThread.h
- Rename SentryObjCMetricsApiTests.m to .wip to skip compilation

Fixes iOS-Swift sample build and all unit tests in CI.

Refs #6342
…vider (#7655)

Extract getAppStartMeasurement from SentryTracer into a standalone SentryAppStartMeasurementProvider class. Pure refactoring — no logic changes.

Small additional cleanup: removed the profilerReferenceID parameter from the provider API since it was only used in a debug log message and not needed for the logic.
philprime added 5 commits May 28, 2026 11:28
Expose the SentryObjCBreadcrumb default initializer and mark ObjC wrapper default initializers unavailable when their wrapped types cannot be default-constructed.
Capture the assigned initialScope block instead of self when bridging to the wrapped Swift options.
Pass fully qualified xcodebuild test selectors through directly and reject class-only values instead of assuming the SentryTests target.
Comment thread Sources/SentryObjCCompat/SentryObjCTransactionContext.swift
Run package prep for every sample build and keep source-backed package products while stripping binary targets for release branch builds.
Comment thread Package@swift-6.1.swift
philprime added 4 commits May 28, 2026 13:28
Serialize the Sentry scheme build graph as a CI diagnostic for the module cache signature mismatch.
Comment thread Sources/SentryObjC/Public/SentryObjCAttributeContent.h

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit eb33e01. Configure here.

Comment thread Package.swift
Comment thread Sources/SentryObjC/Public/SentryObjCOptions.h Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code can easily blow up and is hard to test. We had severe bugs in the past. Be extra careful when changing these files, and have an extra careful look at these:

  • .github/file-filters.yml

@philprime philprime enabled auto-merge (squash) May 29, 2026 08:12
@philprime philprime merged commit cd4994f into main May 29, 2026
225 checks passed
@philprime philprime deleted the philprime/objc-wrapper-sdk-6342-2 branch May 29, 2026 08:18
@philprime philprime mentioned this pull request May 29, 2026
7 tasks
@github-actions github-actions Bot mentioned this pull request Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Use this label to trigger all PR workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create an ObjC SDK

4 participants