Skip to content

fix(iOS): opt spm_dependency pod targets out of Swift explicit modules#57589

Open
chrfalch wants to merge 1 commit into
mainfrom
chrfalch/spm-explicit-modules-opt-out
Open

fix(iOS): opt spm_dependency pod targets out of Swift explicit modules#57589
chrfalch wants to merge 1 commit into
mainfrom
chrfalch/spm-explicit-modules-opt-out

Conversation

@chrfalch

@chrfalch chrfalch commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

fix(iOS): opt spm_dependency pod targets out of Swift explicit modules

Summary

After the VFS-overlay removal landed (#57285 / #57332 stack), the nightly-tests job for react-native-enriched-markdown (iOS) started failing on 0.88.0-nightly-20260717 with:

error: Clang dependency scanner failure:
  …/Debug-iphonesimulator/include/module.modulemap:1:8: error: redefinition of module 'RaTeXFFI'
  …/Debug-iphonesimulator/ReactNativeEnrichedMarkdown/include/module.modulemap:1:8: note: previously defined here

Root cause

A pod target consuming an SPM binary target via spm_dependency sees that target's module.modulemap twice:

  1. Xcode's ProcessXCFramework materializes the xcframework into both the platform-wide products dir (for the SPM package target) and the pod's own TARGET_BUILD_DIR (for the pod target).
  2. spm.rb's existing "Swift package not found" workaround adds the platform-wide products dir to the pod target's SWIFT_INCLUDE_PATHS, making the second copy visible.

This duplication has always existed and is benign under implicit modules. Before this stack, every pod consuming the prebuilt core carried -Xcc -ivfsoverlay React-VFS.yaml, which disqualified those targets from Xcode 26's default explicit modules mode — so they silently fell back to implicit modules. The VFS removal (an explicit goal of the stack) made these targets eligible for explicit module builds, whose dependency scanner loads every reachable module map eagerly and hard-errors on the duplicate definition.

Verified by diffing the same target's SwiftDriver invocation between the last green nightly (07-15: -ivfsoverlay, no -explicit-module-build) and the first red one (07-17: -fmodule-map-file, -explicit-module-build).

Fix

Set SWIFT_ENABLE_EXPLICIT_MODULES = NO on exactly the pod targets spm_dependency touches — the same targets that get the SWIFT_INCLUDE_PATHS workaround that makes the duplicate visible. This restores the pre-stack compile mode for the CocoaPods+SPM interop path only; explicit modules stay enabled everywhere else.

Changelog:

[IOS] [FIXED] - Fix "redefinition of module" errors for libraries using spm_dependency with binary SPM targets under Xcode 26 explicit modules

Test Plan

  • Micro-repro (standalone swiftc, two search dirs shipping the same module.modulemap): -explicit-module-build → hard redefinition of module scanner error (the CI failure shape); implicit modules → diagnostic printed but exit 0. This is the tolerated-vs-fatal boundary the fix moves the target across.
  • E2E: fresh app on react-native@0.88.0-nightly-20260717-b33de750b + react-native-enriched-markdown@0.8.0-nightly-20260716 with RCT_USE_RN_DEP=1 RCT_USE_PREBUILT_RNCORE=1:
    • Unpatched spm.rb: pod target compiles with -explicit-module-build (the CI failure precondition; the CI redefinition itself is Xcode-26.3-specific — 26.6's scanner changed modulemap lookup, so the error needs 26.3 to fire byte-for-byte).
    • Patched spm.rb: SWIFT_ENABLE_EXPLICIT_MODULES = NO lands in both configurations of the pod target, its SwiftDriver invocation no longer contains -explicit-module-build, and the build succeeds with the library's own dedup script disabled and both duplicate module maps forced present — proving the fix suffices on its own.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 17, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Jul 17, 2026
A pod target consuming an SPM binary target via spm_dependency sees the
binary target's module.modulemap twice: Xcode processes the xcframework
into both the platform-wide products dir and the pod's TARGET_BUILD_DIR,
and the existing SWIFT_INCLUDE_PATHS workaround makes the former visible.

Implicit modules tolerate the duplicate definition; the explicit-modules
dependency scanner (the default starting with Xcode 26) fails with
"redefinition of module". Before the VFS-overlay removal these targets
carried -ivfsoverlay, which disqualified them from explicit modules and
masked the problem; the overlay's removal made them eligible and the
nightly-tests react-native-enriched-markdown (RaTeX) job went red.

Set SWIFT_ENABLE_EXPLICIT_MODULES=NO on exactly the targets
spm_dependency touches, restoring the previous compile mode for the
CocoaPods+SPM interop path only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chrfalch
chrfalch force-pushed the chrfalch/spm-explicit-modules-opt-out branch from c13a030 to e5908b4 Compare July 17, 2026 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant