From 55e3f9f559d027c5fae3842c4802cdf89d18fa6d Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Wed, 16 Sep 2026 13:46:24 +0200 Subject: [PATCH 1/3] build: Use Sharpie.Bind.Tool NuGet tool Remove usage of the objectivesharpie Homebrew cask to avoid dependency on Rosetta. This homebrew version is an outdated x86_64 Mono application that needs Rosetta, and it only emits usable bindings alongside a separate Xamarin.iOS installation which also needs Rosetta. The dotnet tool runs natively on Apple silicon and carries its own .NET binding profile, so neither is required. Co-Authored-By: Claude Opus 5 --- .config/dotnet-tools.json | 13 +++ scripts/generate-cocoa-bindings.ps1 | 95 ++++----------------- src/Sentry.Bindings.Cocoa/ApiDefinitions.cs | 2 +- src/Sentry.Bindings.Cocoa/sharpie.md | 4 + 4 files changed, 33 insertions(+), 81 deletions(-) create mode 100644 .config/dotnet-tools.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..748c26073f --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "sharpie.bind.tool": { + "version": "26.6.0.18", + "commands": [ + "sharpie" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index 78128e81e4..a0cf119116 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -19,86 +19,14 @@ if (!$IsMacOS) -CategoryActivity Error -ErrorAction Stop } -# Ensure Objective Sharpie is installed -if (!(Get-Command sharpie -ErrorAction SilentlyContinue)) -{ - Write-Output 'Objective Sharpie not found. Attempting to install via Homebrew.' - brew install --cask objectivesharpie - - if (!(Get-Command sharpie -ErrorAction SilentlyContinue)) - { - Write-Error 'Could not install Objective Sharpie automatically. Try installing from https://aka.ms/objective-sharpie manually.' - } -} - -# Ensure Xamarin is installed (or sharpie won't produce expected output). -if (!(Test-Path '/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/64bits/iOS/Xamarin.iOS.dll')) -{ - Write-Output 'Xamarin.iOS not found. Attempting to install manually.' - - # Download Xamarin.iOS package - $packageName = 'xamarin.ios-16.4.0.23.pkg' - $directDownloadUrl = 'https://github.com/getsentry/sentry-dotnet/releases/download/1.0.0.0-xamarin-ios/Xamarin.iOS.16.4.0.23.pkg' - $downloadPath = "/tmp/$packageName" - $expectedSha256 = '3c3a2e3c5adebf7955934862b89c82e4771b0fd44dfcfebad0d160033a6e0a1a' - - Write-Output "Downloading Xamarin.iOS package..." - curl -L -o $downloadPath $directDownloadUrl - - if ($LASTEXITCODE -ne 0) - { - Write-Error "Failed to download Xamarin.iOS package. Exit code: $LASTEXITCODE" - } - - # Verify checksum - Write-Output "Verifying package checksum..." - $actualSha256 = (Get-FileHash -Path $downloadPath -Algorithm SHA256).Hash.ToLower() - - if ($actualSha256 -ne $expectedSha256) - { - Write-Error "Checksum verification failed. Expected: $expectedSha256, Actual: $actualSha256" - Remove-Item $downloadPath -Force -ErrorAction SilentlyContinue - exit 1 - } - - Write-Output "Checksum verification passed." - - if (Test-Path $downloadPath) - { - Write-Output "Downloaded package to $downloadPath" - Write-Output "Installing Xamarin.iOS package..." - - # Install the package using installer command (requires sudo) - sudo installer -pkg $downloadPath -target / - - if ($LASTEXITCODE -ne 0) - { - Write-Error "Failed to install Xamarin.iOS package. Exit code: $LASTEXITCODE" - } - else - { - Write-Output "Xamarin.iOS package installed successfully" - } - - # Clean up downloaded file - Remove-Item $downloadPath -Force -ErrorAction SilentlyContinue - } - else - { - Write-Error "Downloaded package not found at $downloadPath" - } - - if (!(Test-Path '/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/64bits/iOS/Xamarin.iOS.dll')) - { - Write-Error 'Xamarin.iOS not found after installation.' - } -} +# Objective Sharpie is pinned in /.config/dotnet-tools.json. +Write-Output 'Restoring the pinned Objective Sharpie dotnet tool.' +dotnet tool restore # Get iPhone SDK version -$XcodePath = (xcode-select -p) -replace '/Contents/Developer$', '' -$iPhoneSdkVersion = sharpie xcode -xcode $XcodePath -sdks | grep -o -m 1 'iphoneos\S*' +$iPhoneSdkVersion = "iphoneos$(xcrun --sdk iphoneos --show-sdk-version)" Write-Output "iPhoneSdkVersion: $iPhoneSdkVersion" -$iPhoneSdkPath = xcrun --show-sdk-path --sdk $iPhoneSdkVersion +$iPhoneSdkPath = xcrun --show-sdk-path --sdk iphoneos Write-Output "iPhoneSdkPath: $iPhoneSdkPath" # Generate bindings. @@ -110,14 +38,21 @@ Write-Output "iPhoneSdkPath: $iPhoneSdkPath" # The SentryObjC headers resolve their own imports via `__has_include` guards and don't use the # `SENTRY_HEADER` macro, so - unlike the classic Sentry.h/Sentry-Swift.h headers we used to bind - # no header patching is needed before invoking sharpie. +# +# The header must be passed via `--header`; as a bare positional argument sharpie hands it straight +# to Clang, which then parses it as C and fails on the first Objective-C declaration. Write-Output 'Generating bindings with Objective Sharpie.' -sharpie bind -sdk $iPhoneSdkVersion ` - -scope "$CocoaSdkPath" ` - "$HeadersPath/SentryObjC.h" ` +dotnet sharpie bind -sdk $iPhoneSdkVersion ` + --scope "$CocoaSdkPath" ` + --header "$HeadersPath/SentryObjC.h" ` -o $BindingsPath ` -c -Wno-objc-property-no-attribute ` -F"$iPhoneSdkPath/System/Library/SubFrameworks" # needed for UIUtilities.framework in Xcode 26+ +# The dotnet tool emits ApiDefinition.cs; the committed file and the csproj both use the plural +# name. Renamed here so this change stays a pure toolchain swap - the file rename is a follow-up. +Move-Item "$BindingsPath/ApiDefinition.cs" "$BindingsPath/ApiDefinitions.cs" -Force + # Ensure backup path exists if (!(Test-Path $BackupPath)) { diff --git a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs index 3c304f29cf..39ce1e4a47 100644 --- a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs +++ b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs @@ -1463,7 +1463,7 @@ interface SentryObjCOptions [Wrap("WeakUrlSessionDelegate")] [NullAllowed] - NSUrlSessionDelegate UrlSessionDelegate { get; set; } + INSUrlSessionDelegate UrlSessionDelegate { get; set; } // @property (nonatomic, weak) id _Nullable urlSessionDelegate; [NullAllowed, Export("urlSessionDelegate", ArgumentSemantic.Weak)] diff --git a/src/Sentry.Bindings.Cocoa/sharpie.md b/src/Sentry.Bindings.Cocoa/sharpie.md index bdb6fa8185..9c79957615 100644 --- a/src/Sentry.Bindings.Cocoa/sharpie.md +++ b/src/Sentry.Bindings.Cocoa/sharpie.md @@ -2,6 +2,10 @@ The files in this folder aren't "normal" C# files, but rather they are [Xamarin They are generated using [Objective Sharpie][2], using the script in `../scripts/generate-cocoa-bindings.ps1`. Do not modify the `.cs` files directly. Instead, update the script as needed and re-generate. +`Sentry.Bindings.Cocoa.csproj` re-runs the generation script on every macOS build whose Cocoa headers or scripts are newer than these files, and CI then fails on any difference between the regenerated output and what is committed - so a hand-edit will be overwritten locally and rejected by CI. Mechanical fixups to Sharpie's raw output belong in `../scripts/patch-cocoa-bindings.cs`, which the generation script applies afterwards. + +Objective Sharpie is the [`Sharpie.Bind.Tool`][3] dotnet tool, pinned in `/.config/dotnet-tools.json` and invoked as `dotnet sharpie`; the generation script runs `dotnet tool restore` first, so no manual install is needed. Pinning it matters because the generated output shifts between Sharpie versions - bump the manifest deliberately, then re-generate and commit the result. [1]: https://docs.microsoft.com/xamarin/cross-platform/macios/binding/objective-c-libraries [2]: https://docs.microsoft.com/xamarin/cross-platform/macios/binding/objective-sharpie +[3]: https://www.nuget.org/packages/Sharpie.Bind.Tool From 4b177b9136dc26628b2d5322c50443dafe88d5a3 Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Wed, 16 Sep 2026 13:54:41 +0200 Subject: [PATCH 2/3] build: Rename ApiDefinitions.cs file The newest version of Sharpie generates the ApiDefinition.cs file name as singular instead of plural. This commit changes our files to the new standard. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 4 ++-- scripts/generate-cocoa-bindings.ps1 | 8 ++------ scripts/patch-cocoa-bindings.cs | 2 +- .../{ApiDefinitions.cs => ApiDefinition.cs} | 0 src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj | 4 ++-- 5 files changed, 7 insertions(+), 11 deletions(-) rename src/Sentry.Bindings.Cocoa/{ApiDefinitions.cs => ApiDefinition.cs} (100%) diff --git a/AGENTS.md b/AGENTS.md index 74f8afd7cb..c2a8f45d76 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -105,7 +105,7 @@ Windows). |------|---------| | `*.slnf` | Edit `scripts/generate-solution-filters-config.yaml`, then run `scripts/generate-solution-filters.ps1` | | `CHANGELOG.md` | Generated on squash-merge from the PR title. `.github/workflows/changelog-guard.yml` fails CI on manual entries | -| `src/Sentry.Bindings.Cocoa/ApiDefinitions.cs`, `StructsAndEnums.cs` | Edit `scripts/patch-cocoa-bindings.cs`, then run `scripts/generate-cocoa-bindings.ps1` | +| `src/Sentry.Bindings.Cocoa/ApiDefinition.cs`, `StructsAndEnums.cs` | Edit `scripts/patch-cocoa-bindings.cs`, then run `scripts/generate-cocoa-bindings.ps1` | | `modules/**` | Git submodules pointing at other repositories — change them upstream, never in place | | `*.verified.*` | Run the tests, then `pwsh ./scripts/accept-verifier-changes.ps1` | @@ -147,7 +147,7 @@ scripts/ # Build and maintenance scripts - **macOS only**. Requires Xcode. - `Sentry.Bindings.Cocoa` wraps the native Cocoa SDK. - Device tests run in CI only. -- `src/Sentry.Bindings.Cocoa/ApiDefinitions.cs` and `StructsAndEnums.cs` are **auto-generated** — do not edit them directly. All changes must go in `scripts/patch-cocoa-bindings.cs` and be applied by running `scripts/generate-cocoa-bindings.ps1`. +- `src/Sentry.Bindings.Cocoa/ApiDefinition.cs` and `StructsAndEnums.cs` are **auto-generated** — do not edit them directly. All changes must go in `scripts/patch-cocoa-bindings.cs` and be applied by running `scripts/generate-cocoa-bindings.ps1`. ### MAUI - Requires MAUI workloads: `sudo dotnet workload restore` (macOS/Linux) or `dotnet workload restore` (Windows). diff --git a/scripts/generate-cocoa-bindings.ps1 b/scripts/generate-cocoa-bindings.ps1 index a0cf119116..3909f293d6 100644 --- a/scripts/generate-cocoa-bindings.ps1 +++ b/scripts/generate-cocoa-bindings.ps1 @@ -49,10 +49,6 @@ dotnet sharpie bind -sdk $iPhoneSdkVersion ` -c -Wno-objc-property-no-attribute ` -F"$iPhoneSdkPath/System/Library/SubFrameworks" # needed for UIUtilities.framework in Xcode 26+ -# The dotnet tool emits ApiDefinition.cs; the committed file and the csproj both use the plural -# name. Renamed here so this change stays a pure toolchain swap - the file rename is a follow-up. -Move-Item "$BindingsPath/ApiDefinition.cs" "$BindingsPath/ApiDefinitions.cs" -Force - # Ensure backup path exists if (!(Test-Path $BackupPath)) { @@ -70,9 +66,9 @@ Copy-Item "$BindingsPath/$File" -Destination "$BackupPath/$File" & dotnet run "$PSScriptRoot/patch-cocoa-bindings.cs" "$BindingsPath/$File" | ForEach-Object { Write-Host $_ } ################################################################################ -# Patch ApiDefinitions.cs +# Patch ApiDefinition.cs ################################################################################ -$File = 'ApiDefinitions.cs' +$File = 'ApiDefinition.cs' Write-Output "Patching $BindingsPath/$File" Copy-Item "$BindingsPath/$File" -Destination "$BackupPath/$File" & dotnet run "$PSScriptRoot/patch-cocoa-bindings.cs" "$BindingsPath/$File" | ForEach-Object { Write-Host $_ } diff --git a/scripts/patch-cocoa-bindings.cs b/scripts/patch-cocoa-bindings.cs index e2455bfd01..5285ecde9a 100644 --- a/scripts/patch-cocoa-bindings.cs +++ b/scripts/patch-cocoa-bindings.cs @@ -9,7 +9,7 @@ if (args.Length != 1) { - Console.Error.WriteLine("Usage: patch-cocoa-bindings.cs "); + Console.Error.WriteLine("Usage: patch-cocoa-bindings.cs "); return; } diff --git a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs b/src/Sentry.Bindings.Cocoa/ApiDefinition.cs similarity index 100% rename from src/Sentry.Bindings.Cocoa/ApiDefinitions.cs rename to src/Sentry.Bindings.Cocoa/ApiDefinition.cs diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj index d55b7dee0a..94b79b4d7b 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -43,7 +43,7 @@ - + @@ -100,7 +100,7 @@ + Outputs="ApiDefinition.cs;StructsAndEnums.cs"> From 4c872ca4bf98145e7fe01075c934cc74b76ea0da Mon Sep 17 00:00:00 2001 From: Ricardo Colombo Oliveira Date: Wed, 16 Sep 2026 15:52:53 +0200 Subject: [PATCH 3/3] build: Track the dotnet tools manifest as a Cocoa bindings input --- 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 94b79b4d7b..3bdf984a2e 100644 --- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj +++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj @@ -17,7 +17,7 @@ See getsentry/sentry-dotnet#5492. --> $(SentryCocoaCache)Carthage\Build-$(TargetPlatformIdentifier)\SentryObjC-Dynamic.xcframework - ../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/Headers/**/*.h + ../../scripts/generate-cocoa-bindings.ps1;../../.config/dotnet-tools.json;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/Headers/**/*.h $([MSBuild]::NormalizePath($(MSBuildThisFileDirectory), $(SentryCocoaCache).git))