diff --git a/.github/workflows/update-deps.yml b/.github/workflows/update-deps.yml
index 131b8ea37e..202b8a885c 100644
--- a/.github/workflows/update-deps.yml
+++ b/.github/workflows/update-deps.yml
@@ -16,7 +16,7 @@ jobs:
matrix:
include:
- name: Cocoa SDK
- path: modules/sentry-cocoa.properties
+ path: modules/sentry-cocoa
- name: Java SDK
path: scripts/update-java.ps1
- name: Native SDK
diff --git a/.gitignore b/.gitignore
index 561954efe0..ac0360faaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,9 +29,6 @@ test/**/*.apk
.sentry-native
**/EnvironmentVariables.g.cs
-# Download cache for Cocoa SDK
-modules/sentry-cocoa
-
# Local Claude Code settings that should not be committed
.claude/settings.local.json
diff --git a/.gitmodules b/.gitmodules
index 71bd96d198..494aae20cb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "modules/sentry-native"]
path = modules/sentry-native
url = https://github.com/getsentry/sentry-native.git
+[submodule "modules/sentry-cocoa"]
+ path = modules/sentry-cocoa
+ url = https://github.com/getsentry/sentry-cocoa.git
diff --git a/modules/sentry-cocoa b/modules/sentry-cocoa
new file mode 160000
index 0000000000..3a22ecd00a
--- /dev/null
+++ b/modules/sentry-cocoa
@@ -0,0 +1 @@
+Subproject commit 3a22ecd00ad1398747bfd587e44df82716908dd3
diff --git a/modules/sentry-cocoa.properties b/modules/sentry-cocoa.properties
deleted file mode 100644
index 38a61fb5d7..0000000000
--- a/modules/sentry-cocoa.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-version = 9.10.0
-repo = https://github.com/getsentry/sentry-cocoa
diff --git a/scripts/build-sentry-cocoa.sh b/scripts/build-sentry-cocoa.sh
index 55dbdbde6e..6e18143f1a 100755
--- a/scripts/build-sentry-cocoa.sh
+++ b/scripts/build-sentry-cocoa.sh
@@ -4,7 +4,33 @@ set -euo pipefail
pushd "$(dirname "$0")" >/dev/null
cd ../modules/sentry-cocoa
-rm -rf Carthage
+mkdir -p Carthage
+PID_FILE="$PWD/Carthage/.build.pid"
+trap 'if [[ "$(cat "$PID_FILE" 2>/dev/null)" == "$$" ]]; then rm -f "$PID_FILE"; fi' EXIT
+
+# Serialize concurrent invocations; parallel xcodebuilds race on DerivedData.
+TMP_FILE=$(mktemp "$PID_FILE.tmp.XXXXXX")
+echo $$ > "$TMP_FILE"
+while ! ln "$TMP_FILE" "$PID_FILE" 2>/dev/null; do
+ build_pid=$(cat "$PID_FILE" 2>/dev/null || true)
+ if [[ -n "$build_pid" ]] && ! kill -0 "$build_pid" 2>/dev/null; then
+ echo "Previous build did not complete (pid $build_pid); cleaning up and retrying" >&2
+ if mv "$PID_FILE" "$PID_FILE.stale.$$" 2>/dev/null; then
+ rm -f "$PID_FILE.stale.$$"
+ fi
+ continue
+ fi
+ sleep 2
+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
+ popd >/dev/null
+ exit 0
+fi
+
+rm -rf Carthage/output-*.xcarchive Carthage/Build-* Carthage/Headers Carthage/.built-from-sha
# Grabbing the first SDK versions
sdks=$(xcodebuild -showsdks)
@@ -62,7 +88,7 @@ find Carthage/Build-ios/Sentry.xcframework/ios-arm64 -name '*.h' -exec cp {} Car
find Carthage/Build* \( -name Headers -o -name PrivateHeaders -o -name Modules \) -exec rm -rf {} +
rm -rf Carthage/output-*
-cp .git/HEAD Carthage/.built-from-sha
+echo "$current_sha" > Carthage/.built-from-sha
echo ""
popd >/dev/null
diff --git a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs
index 75cc6a25a9..9a56e35d80 100644
--- a/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs
+++ b/src/Sentry.Bindings.Cocoa/ApiDefinitions.cs
@@ -11,7 +11,6 @@
using CoreGraphics;
using Foundation;
using ObjCRuntime;
-using Sentry;
using UIKit;
namespace Sentry.CocoaSdk;
diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
index 4d7db910ee..96bc4b2d0c 100644
--- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
+++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
@@ -8,19 +8,29 @@
true
.NET Bindings for the Sentry Cocoa SDK
..\..\modules\sentry-cocoa\
+ $(MSBuildThisFileDirectory)..\..\modules\sentry-cocoa.properties
$(SentryCocoaCache)Sentry.framework\
- $([System.IO.File]::ReadAllText("$(MSBuildThisFileDirectory)../../modules/sentry-cocoa.properties"))
- $([System.Text.RegularExpressions.Regex]::Match($(SentryCocoaProperties), 'version\s*=\s*([^\s]+)').Groups[1].Value)
- $(SentryCocoaCache)Sentry-$(SentryCocoaVersion).xcframework
- ../../modules/sentry-cocoa.properties;../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaFrameworkHeaders)**/*.h
$(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
../../scripts/generate-cocoa-bindings.ps1;$(SentryCocoaCache)Carthage/.built-from-sha;$(SentryCocoaCache)Carthage/**/*.h
+
+ $([MSBuild]::NormalizePath($(MSBuildThisFileDirectory), $(SentryCocoaCache).git))
+
+ .git
+
+ $([System.IO.File]::ReadAllText('$(SentryCocoaGitFile)').Trim().Replace('gitdir: ', ''))
@@ -58,7 +68,7 @@
+ Condition="$([MSBuild]::IsOSPlatform('OSX')) And Exists('$(SentryCocoaProperties)') And !Exists('$(SentryCocoaCache).git') And !Exists('$(SentryCocoaFramework)')">
@@ -97,7 +107,7 @@
+ Inputs="$(SentryCocoaCache)$(SentryCocoaGitDir)\HEAD;..\..\scripts\build-sentry-cocoa.sh" Outputs="..\..\modules\sentry-cocoa\Carthage\.built-from-sha">
@@ -125,7 +135,8 @@
Condition="$([MSBuild]::IsOSPlatform('OSX'))" />
-
+
+
diff --git a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs
index d8d6b45634..23ee524f72 100644
--- a/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs
+++ b/src/Sentry.Bindings.Cocoa/StructsAndEnums.cs
@@ -9,7 +9,6 @@
using System.Runtime.InteropServices;
using Foundation;
using ObjCRuntime;
-using Sentry;
namespace Sentry.CocoaSdk;