Target Branch
0.87
Link to commit or PR to be picked
react/react-native#57757
Landed on main as react/react-native@6ff47ef
Description
SwiftPM has no equivalent of CocoaPods' script_phase, so a framework that generates content at build time cannot get one. The first casualty is expo-constants: nothing writes EXConstants.bundle/app.config, which surfaces at runtime as "Unable to find the embedded app config".
This adds a 6th field to the SwiftPM autolinking plugin contract:
scriptPhases: [{id, name, script, position?: 'beforeCompile' | 'end',
inputPaths?, outputPaths?, alwaysOutOfDate?}]
The plugin returns data; RN validates it, records it to a .spm-plugin-script-phases.json sidecar, and spm add/update emits one PBXShellScriptBuildPhase per entry — tracked in .spm-injected.json by id, so update reconciles and deinit reverts.
Requested for 0.87 because the experimental SwiftPM support ships on that line, and without this contract Expo (and any other package that needs a build-time generation step) simply cannot work under SwiftPM on 0.87. This is the missing half of a feature already on the branch rather than a new capability of its own.
Verified end to end by the Expo team on a real Expo app against a local cut of this branch: the phase lands last, after "Bundle React Native code and images", BUILD SUCCEEDED, and app.config is written with the sdkVersion whose absence caused the original bug. They also independently confirmed deinit leaves zero residue and add is idempotent. Their side is expo/expo#47647.
Scope is confined to the SwiftPM injector scripts; yarn jest packages/react-native/scripts is green at 853 tests, with the SwiftPM suite going from 462 → 637. The change also fixes, in passing, that add → update → deinit did not restore project.pbxproj byte-for-byte even with zero script phases.
Target Branch
0.87
Link to commit or PR to be picked
react/react-native#57757
Landed on
mainas react/react-native@6ff47efDescription
SwiftPM has no equivalent of CocoaPods'
script_phase, so a framework that generates content at build time cannot get one. The first casualty is expo-constants: nothing writesEXConstants.bundle/app.config, which surfaces at runtime as "Unable to find the embedded app config".This adds a 6th field to the SwiftPM autolinking plugin contract:
The plugin returns data; RN validates it, records it to a
.spm-plugin-script-phases.jsonsidecar, andspm add/updateemits onePBXShellScriptBuildPhaseper entry — tracked in.spm-injected.jsonbyid, soupdatereconciles anddeinitreverts.Requested for 0.87 because the experimental SwiftPM support ships on that line, and without this contract Expo (and any other package that needs a build-time generation step) simply cannot work under SwiftPM on 0.87. This is the missing half of a feature already on the branch rather than a new capability of its own.
Verified end to end by the Expo team on a real Expo app against a local cut of this branch: the phase lands last, after "Bundle React Native code and images",
BUILD SUCCEEDED, andapp.configis written with thesdkVersionwhose absence caused the original bug. They also independently confirmeddeinitleaves zero residue andaddis idempotent. Their side is expo/expo#47647.Scope is confined to the SwiftPM injector scripts;
yarn jest packages/react-native/scriptsis green at 853 tests, with the SwiftPM suite going from 462 → 637. The change also fixes, in passing, thatadd → update → deinitdid not restoreproject.pbxprojbyte-for-byte even with zero script phases.