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