Hive Hive
Sign in

fix(cli): always expose -Swift.h for Swift-only SPM frameworks (#11007)

GitHub issue · Closed

Metadata
Source
tuist/tuist #11012
Updated
Jun 24, 2026
Domains
Generated projects
Details

Resolves https://github.com/tuist/tuist/issues/11007

What

Reverts #10971 so Swift-only SwiftPM framework targets again let Xcode synthesize their modulemap, which always exposes the -Swift.h Objective-C compatibility header. Also drops the @objc/NSObject source-scan that earlier commits on this branch explored, which was the wrong approach.

Why

#10971 made Swift-only SwiftPM framework targets emit a headerless modulemap (framework module X { export * } with DEFINES_MODULE=NO) to avoid #10967, a crash where Xcode 26 beta’s explicit-modules dependency scanner read the synthesized modulemap’s X-Swift.h reference before Swift had emitted that header.

The headerless modulemap hides the target’s Swift @objc interface, so Objective-C @import can no longer see the Swift classes. Concretely, RollbarNotifier’s @import RollbarReport; fails to compile with unknown receiver 'RollbarCrashDiagnosticFilter' (#11007).

Root cause and why this approach

  • A generate-time custom MODULEMAP_FILE cannot reference the build-generated X-Swift.h. The header is produced inside the built framework, and a relative header "X-Swift.h" only resolves from Xcode’s synthesized in-framework modulemap, never from a modulemap stored at a derived path. Every custom variant tested (top-level header, separate and nested requires objc submodules) fails with Header 'X-Swift.h' not found. So restructuring the modulemap to expose the header to Objective-C while hiding it from the Swift scanner is not possible.
  • The only way to expose the Swift interface to Objective-C is to let Xcode synthesize the modulemap. That is the pre-#10971 behavior and matches what SwiftPM does, which always emits the compatibility header for library targets.
  • #10967 no longer reproduces on current Xcode. Building an EE tuist and running the real tuist cache against a swift-log-as-framework project on Xcode 26.4.1, the single-arch simulator Binaries-Cache build (the exact #10967 scenario) succeeds with always-expose. The scanner ordering bug was specific to the Xcode 26 beta.

Validation

Real tuist cache on Xcode 26.4.1, simulator pass:

  • swift-log framework cache build succeeds, no Logging-Swift.h not found.
  • Rollbar cache build with --cache-profile only-external succeeds; RollbarCrashCollector.m consumes the Swift @objc classes through @import RollbarReport.

Caveats

  • The cache device pass was not re-tested locally (no iOS device SDK on the test machine; device builds are multi-arch and not the #10967 trigger). Worth confirming on CI.
  • Anyone still on an Xcode 26 beta where the scanner bug lives would regress to #10967. On release Xcode (26.4.1 and later) it is a non-issue.

🤖 Generated with Claude Code

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
PS
przemyslaw-szurmak Jun 3, 2026

yeah, thanks guys!