Skip to content

[0.87] SwiftPM: let autolinking plugins declare build-time script phases #1373

Description

@cipolleschi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type Pick RequestPick requests to include commits inside a React Native release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions