Skip to content

fix: MSB4006 circular dependency involving target "SetupCocoaSDK"#4956

Open
jamescrosswell wants to merge 4 commits intomainfrom
cocoa-circular-dependency
Open

fix: MSB4006 circular dependency involving target "SetupCocoaSDK"#4956
jamescrosswell wants to merge 4 commits intomainfrom
cocoa-circular-dependency

Conversation

@jamescrosswell
Copy link
Collaborator

@jamescrosswell jamescrosswell commented Feb 25, 2026

Resolves #4955:

Explanation

Me and Claude spent a bit of time looking at this. I think we now have a solution that is OK.

What the original code did

The recursive MSBuild call with RemoveProperties="TargetFramework" meant that during an inner build, instead of running _SetupCocoaSDK directly, it spawned a separate MSBuild process on the same project with no TargetFramework set. That separate process ran _SetupCocoaSDK once in isolation. So across both inner TFM builds, the actual work happened in one subprocess — not in the inner builds themselves.

What the new code does

_SetupCocoaSDK now runs once per inner build (once for net9.0-ios18.0, once for net9.0-maccatalyst18.0).

However, every sub-target of _SetupCocoaSDK is idempotent and has checks to make sure we're not double handling:

  • _DownloadCocoaSDK — has Condition="... And !Exists('$(SentryCocoaFramework)')", so ,skips if already downloaded
  • _BuildCocoaSDK — has Inputs/Outputs incremental build guards, skips if up-to-date
  • _GenerateSentryCocoaBindings — has Inputs/Outputs, skips if up-to-date
  • SanitizeSentryCocoaFramework — has "!Exists('$(SentryCocoaFramework).sanitized.stamp"

#skip-changelog

@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.88%. Comparing base (c8c4b00) to head (3b0a3b3).
⚠️ Report is 20 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4956      +/-   ##
==========================================
- Coverage   73.89%   73.88%   -0.02%     
==========================================
  Files         496      497       +1     
  Lines       17951    17957       +6     
  Branches     3516     3516              
==========================================
+ Hits        13265    13267       +2     
- Misses       3825     3832       +7     
+ Partials      861      858       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jamescrosswell jamescrosswell marked this pull request as ready for review February 25, 2026 20:41
Condition="$([MSBuild]::IsOSPlatform('OSX')) and Exists('$(SentryCocoaFramework)') and !Exists('$(SentryCocoaFramework).sanitized.stamp')">
<Message Importance="High" Text="Sanitizing $(SentryCocoaFramework): removing dSYMs, Headers, Modules, PrivateHeaders (including symlinks)." />
<Exec Command="find &quot;$(SentryCocoaFramework)&quot; -depth \( -name dSYMs -o -name Headers -o -name Modules -o -name PrivateHeaders \) -exec echo Removing {} \; -exec rm -rf {} + 2&gt;/dev/null || true" />
<Touch Files="$(SentryCocoaFramework).sanitized.stamp" AlwaysCreate="true" />
Copy link
Member

Choose a reason for hiding this comment

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

question: just to be sure ... this file doesn't get packed or published when an app is built, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No the framework directory/file is specified here:

<SentryCocoaFramework>$(SentryCocoaCache)Sentry-$(SentryCocoaVersion).xcframework</SentryCocoaFramework>

By appending .sanitized.stamp we effectively end up with a stamp file beside that directory/file.

@jamescrosswell jamescrosswell requested a review from Flash0ver March 5, 2026 22:36
Copy link

@cursor cursor bot left a comment

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.

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Stale stamp file can skip sanitization after re-extraction
    • Deleted the sanitization stamp at the start of _DownloadCocoaSDK so any re-extracted framework is always sanitized again.

Create PR

Or push these changes by commenting:

@cursor push 584ff6f330
Preview (584ff6f330)
diff --git a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
--- a/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
+++ b/src/Sentry.Bindings.Cocoa/Sentry.Bindings.Cocoa.csproj
@@ -62,6 +62,9 @@
 
     <Message Importance="High" Text="Setting up the Cocoa SDK version '$(SentryCocoaVersion)'." />
 
+    <!-- Ensure sanitization reruns after re-extracting an absent framework -->
+    <Delete Files="$(SentryCocoaFramework).sanitized.stamp" />
+
     <!-- Clean cache if version does not exist to get rid of old versions -->
     <RemoveDir
       Condition="!Exists('$(SentryCocoaFramework).zip')"

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Condition="$([MSBuild]::IsOSPlatform('OSX')) and Exists('$(SentryCocoaFramework)') and !Exists('$(SentryCocoaFramework).sanitized.stamp')">
<Message Importance="High" Text="Sanitizing $(SentryCocoaFramework): removing dSYMs, Headers, Modules, PrivateHeaders (including symlinks)." />
<Exec Command="find &quot;$(SentryCocoaFramework)&quot; -depth \( -name dSYMs -o -name Headers -o -name Modules -o -name PrivateHeaders \) -exec echo Removing {} \; -exec rm -rf {} + 2&gt;/dev/null || true" />
<Touch Files="$(SentryCocoaFramework).sanitized.stamp" AlwaysCreate="true" />
Copy link

Choose a reason for hiding this comment

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

Stale stamp file can skip sanitization after re-extraction

Low Severity

If the xcframework directory is removed (manually or by an external process) while its .zip file remains cached, _DownloadCocoaSDK re-extracts the framework but the RemoveDir step is skipped (it only runs when the zip is missing). The old $(SentryCocoaFramework).sanitized.stamp survives, causing SanitizeSentryCocoaFramework to be skipped entirely. This leaves an unsanitized framework (with dSYMs, Headers, Modules, PrivateHeaders still present) used for the build. Deleting the stamp file during re-extraction (or at the start of _DownloadCocoaSDK) would close this gap.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MSB4006: Circular dependency involving "SetupCocoaSDK"

2 participants