Repository navigation
[0.88] [iOS][SPM] Derive the generated manifests' iOS platform floor from the app (+2 prerequisites) #1414
Description
Target Branch
0.88
Link to commit or PR to be picked
Pick in this order (oldest first):
- [iOS][swiftpm] Derive an SPM library's Swift name from its podspec react/react-native#58290 —
1cfc5f29a00— Derive an SPM library's Swift name from its podspec - Run SPM-generated shell scripts under bash, not /bin/sh react/react-native#58362 —
25f48bd72fd— Run SPM-generated shell scripts under bash, not/bin/sh - [iOS][SPM] Derive the generated manifests' iOS platform floor from the app react/react-native#58379 —
92564f33fda— Derive the generated manifests' iOS platform floor from the app (D119653699)
Description
The change we actually want is #58379. The other two are prerequisites, so the request covers all three.
Why #58379 is needed
The SwiftPM manifests React Native generates (the Autolinked aggregate, the per-dependency synth packages and the scaffolded community packages) hardcode platforms: [.iOS(.v15)]. SwiftPM refuses to link a product whose minimum platform is above the depending target's, so any self-managed package with a higher floor cannot be autolinked.
Every Expo package declares iOS 16.4, so a stock Expo app fails at build time:
error: The package product 'Expo' requires minimum platform version 16.4 for the iOS platform,
but this target supports 15.0 (in target 'AutolinkedAggregate' from project 'Autolinked')
The app itself is correct (IPHONEOS_DEPLOYMENT_TARGET = 16.4). Only the generated manifests disagree. The fix derives the floor from the app's own deployment target, clamped to React Native's minimum (15.1).
Why the prerequisites
#58290 is a hard dependency. #58379 imports findPodspecs and readPodspecCached from scripts/spm/read-podspec.js. On 0.88-stable that module exports only readPodspec, so the pick does not build without #58290 first. Cherry-picking #58379 alone conflicts in generate-spm-autolinking.js and scaffold-package-swift.js.
#58362 is taken to avoid a conflict. It and #58379 both modify scripts/spm/generate-spm-xcodeproj.js. Not a functional dependency, but skipping it makes #58379 conflict there.
#58425 is deliberately not taken. It is chronologically between #58362 and #58379 and touches scripts/spm/, but shares no file with #58379 (it changes download-spm-artifacts.js, the CocoaPods ruby helpers and the Gradle Kotlin plugin). It is a separate concern and is not required here.
Risk
The chain is larger than a typical post-RC1 pick, so worth being explicit about the blast radius.
All of the code these commits change lives under packages/react-native/scripts/spm/ plus scripts/setup-apple-spm.js. That tree is required only by setup-apple-spm.js, which is a manual entry point (node node_modules/react-native/scripts/setup-apple-spm.js [action]). It is not wired into pod install or any build phase. The only SPM code that runs unconditionally is the CocoaPods hook SPM.apply_on_post_install, which iterates a dependency map that stays empty unless a podspec declares an SPM dependency, and none of these commits touch it.
So an app that does not opt into SwiftPM cannot execute a line any of these change.
The remaining files in #58290 are packages/rn-tester/ and packages/react-native-test-library/, which are React Native's own fixtures and are not shipped.
On size: #58290 reads as +3386/-912 across 26 files, but roughly 2264 of those additions are test files and ~143 are docs. The production delta is around +900/-325.
Two behaviour changes that do land, both only for SwiftPM users:
- SwiftPM name collisions become a hard error naming
swiftpmConfig.nameas the fix, where previously colliding names were auto-corrected. The old behaviour invented a module name no#importcould predict, so the error is the better outcome, but it is new. SCAFFOLDER_VERSIONbumps to 20, so existing scaffolds regenerate with the new floor on the nextspm add/spm update.
Prerequisite audit
Checked against a full (unshallowed) main history: every SPM commit preceding #58290 is already on 0.88-stable (#58292, #58060, #58044, #58033, #58087, #58059, #58034, #58035). The chain starts cleanly at #58290 and is exactly these three.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone / Picked
Activity
github-actions commentedon Sep 15, 2026
Thank you for opening a new React Native Pick Request.
These are the criteria we follow when accepting or rejecting a code change into a React Native release branch (source).
If your Pick Request does not satisfy the criteria below, please close it as it will not be considered.
✅ Which Pick Requests we accept
TurboModule.getEnforcingfunction is throwing an unexpected assertion error.react-native-macosis not behaving as expected or is regressingReactRootView.java) if it is causing a breaking change for the React Native ecosystem.❌ Which Pick Requests we don't accept
ℹ️ What makes for a good Pick Request
In order for your Pick Request to be considered, please do the following:
main, or one PR against the release branch.[-][0.88] [iOS][SPM] Derive the generated manifests' iOS platform floor from the app[/-][+][0.88] [iOS][SPM] Derive the generated manifests' iOS platform floor from the app (+2 prerequisites)[/+]fabriziocucci commentedon Sep 15, 2026
Picked manually into
0.88-stable:0.88-stable38302c95345903c4ab76366069149f257All three applied without conflicts. SPM test suites pass: 1001 tests across 21 suites.