Hive Hive
Sign in

fix(cli): avoid shadowing SwiftPM public headers

GitHub issue · Closed

Metadata
Source
tuist/tuist #11653
Updated
Jul 5, 2026
Domains
Generated projects
Details

What changed

Backports #11648 to releases/4.202.x.

  • Keeps SwiftPM C directory-target public headers de-duplicated for framework copy destinations while also excluding shadowed duplicate headers from the generated project header glob.
  • Extends the nanopb-style acceptance fixture with a sibling C package that includes <nanopb/pb.h> from a generated header.
  • Tightens acceptance coverage so shadowed wrapper headers must not remain in the generated nanopb headers phase.

Why it changed

The latest RC line already includes the duplicate public-header fix, but still needs the follow-up nested-include fix. Without this backport, nanopb-style wrapper headers can remain available as generated project headers, allowing module-qualified includes such as <nanopb/pb.h> to resolve to a wrapper that includes itself recursively in some Xcode/header-map configurations.

Root cause

The previous fix selected only one public framework header per flattened framework destination, which avoided duplicate copy commands. The shadowed wrapper headers were no longer Public, but they were still emitted as project headers. That left the wrapper headers available to consumers even though the nested headers were the actual framework public headers.

Approach

This is a clean cherry-pick of the merged mainline fix commit from #11648:

  • Mainline merge commit: 58e514491f85c1daae6fe2742ea33939efb5150c
  • Backport commit: 96e450b8724

Impact

The RC should avoid both nanopb-style failure modes:

  • duplicate public framework header copy commands
  • recursive wrapper-header resolution when consumers include module-qualified public headers

Validation

Backport application:

  • Clean cherry-pick onto origin/releases/4.202.x
  • git diff --check origin/releases/4.202.x..HEAD

Mainline validation from #11648:

  • Red: temporarily reverted only the mapper implementation while keeping the new test/fixture. The focused acceptance command failed with nonPublicHeaderNames equal to ["pb.h", "pb.h", "pb_common.h", "pb_common.h"] instead of ["pb.h", "pb_common.h"].
  • Green: restored the mapper fix and reran the same focused acceptance command. It passed and built the generated app fixture.
  • xcodebuild test -workspace Tuist.xcworkspace -scheme Tuist-Workspace -only-testing TuistGeneratorAcceptanceTests/GenerateAcceptanceTestAppWithSPMCTargetDuplicatePublicHeaders -destination platform=macOS -derivedDataPath /private/tmp/tuist-nested-headers-acceptance CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" COMPILATION_CACHE_ENABLE_CACHING=NO
  • xcodebuild test -workspace Tuist.xcworkspace -scheme Tuist-Workspace -only-testing TuistLoaderTests/PackageInfoMapperTests -destination platform=macOS -derivedDataPath /private/tmp/tuist-nested-headers-loader-red CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" COMPILATION_CACHE_ENABLE_CACHING=NO
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