Skip to content

[0.87] Pick SwiftPM support chain (#57442, #57332, #57564)#57578

Merged
cipolleschi merged 3 commits into
0.87-stablefrom
picks-57442-57332-57564
Jul 16, 2026
Merged

[0.87] Pick SwiftPM support chain (#57442, #57332, #57564)#57578
cipolleschi merged 3 commits into
0.87-stablefrom
picks-57442-57332-57564

Conversation

@cipolleschi

@cipolleschi cipolleschi commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Cherry-picks the three commits from the pick request reactwg/react-native-releases#1344 that the @react-native-bot failed to apply to 0.87-stable.

The bot successfully picked 4 of the 7 requested commits (#57285, #57305, #57440, #57565) but failed on the SwiftPM chain below. The failures were an ordering artifact: the bot never landed #57442 (its push failed), so the two downstream picks then hit conflicts in files that #57442 owns. Picking #57442 first makes all three apply cleanly.

Picked in dependency order:

PR Commit Notes
#57442 6aa147f ReactNativeDependenciesHeaders sidecar + pure-RN ReactNativeHeaders
#57332 47fad09 SwiftPM support in iOS
#57564 a693f41 Fix Prettier lint failure after SwiftPM support landed

Verification

Changelog:

[IOS] [CHANGED] - Prebuilt artifacts: ReactNativeHeaders is pure-RN; third-party deps headers ship in the new ReactNativeDependenciesHeaders.xcframework sidecar (and the ReactNativeDependencies pod), published standalone to Maven
[IOS] [ADDED] - npx react-native spm command + SwiftPM package-generation tooling (opt-in; CocoaPods stays supported)

Test Plan

  • Relying on CI (SwiftPM script test suites under packages/react-native/scripts/spm/__tests__ + Prettier lint).

chrfalch and others added 3 commits July 16, 2026 15:50
…veHeaders, published to Maven (#57442)

Summary:
Step 2 of the prebuilt-deps roadmap: ship the deps headers as a **SwiftPM-ready, self-contained artifact** and make every header namespace have exactly **one physical home**.

1. **New artifact: `ReactNativeDependenciesHeaders.xcframework`** — the binary `ReactNativeDependencies.xcframework` is framework-type, so its root `Headers/` is invisible to SwiftPM binaryTargets (`HeadersPath` is rejected on framework entries; verified empirically). The deps prebuild now emits a headers-only library-type sidecar (stub archives + per-slice `Headers/` + `HeadersPath` — the exact `ReactNativeHeaders` recipe, factored into a shared `headers-xcframework.js` emitter) carrying all seven deps namespaces incl. SocketRocket, with slice parity derived from the binary artifact's Info.plist. Ships inside the deps tarball *and* standalone.

2. **`ReactNativeHeaders` goes pure-RN** — the R2 relocation of deps namespaces (and the `DEPS_NAMESPACES_NOT_RELOCATED` SocketRocket exclusion list) is deleted. Relocated copies are what enabled the SocketRocket dual-copy regression (duplicate `interface` / poisoned module graph under `use_frameworks!`); that bug class is now structurally impossible. Headers gate flipped: deps namespaces must be **absent** from RNH; the sidecar emitter enforces set-equality with `DEPS_NAMESPACES` fail-closed in both directions. On the CocoaPods side, a new `ReactNativeDependenciesUtils.configure_aggregate_xcconfig` injects the deps pod's `Headers/` globally (aggregate + every pod target), mirroring the rncore injection — this replaces the folly/glog resolution pods previously got via the flattened `React-Core-prebuilt/Headers`.

3. **CI: prebuilt + dynamic-frameworks lane** — the regression's exact config had no coverage (the `test-ios-rntester` action hard-coupled `use-frameworks:true` to source builds). New `use-prebuilds` input; `test_ios_rntester`'s dynamic cells now consume the workflow-built prebuilt artifacts.

4. **Maven publishing** — `ReactNativeHeaders` and `ReactNativeDependenciesHeaders` publish standalone on `react-native-artifacts` (classifiers `reactnative-headers-*`, `reactnative-dependencies-headers-*`); `verifyArtifactsAreOnMaven` now HEAD-checks every classifier tarball instead of only the POM.

Stacked on #57440. The SwiftPM preview (#57332) rebases on top and wires the sidecar as its 5th binaryTarget.

## Changelog:

[IOS] [CHANGED] - Prebuilt artifacts: ReactNativeHeaders is pure-RN; third-party deps headers ship in the new ReactNativeDependenciesHeaders.xcframework sidecar (and the ReactNativeDependencies pod), published standalone to Maven

Pull Request resolved: #57442

Test Plan:
- Headers gate: include-health, structural (deps absent from RNH, byte-matched module maps), and compile smokes (React module + 14 namespace modules + Expo-shape ObjC++/Swift fixtures vs the deps include path) — ALL PASSED
- jest: 33/33 (`scripts/ios-prebuild/__tests__`, incl. new sidecar set-equality tests)
- ESLint (`--max-warnings 0`), Prettier, Flow (`yarn flow-check`): clean
- E2E (locally built artifacts): rn-tester prebuilt static ✅, prebuilt `USE_FRAMEWORKS=dynamic` ✅ (the regression config — verified `React-Core-prebuilt/Headers` contains no deps namespaces and the deps pod serves all seven), helloworld static ✅, source-core + prebuilt-deps ✅ (React compiled from source resolves folly via the deps pod), source-mode control with unchanged dependency graph ✅
- Sidecar inspected: per-slice `HeadersPath`, 7 namespaces, slice parity with the binary
- Publication validated end-to-end with `publishReleasePublicationToMavenLocal`: all 12 files + POM land with the expected classifier names

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed By: fabriziocucci

Differential Revision: D111449462

Pulled By: cipolleschi

fbshipit-source-id: e1217d14c0588d00a207622d346c9e6f4705a95d
Summary:
⚠️  This is a stacked PR — review/merge the base PRs first

Builds on, and should land after (bottom-up):

1. #57285 — Remove the Clang VFS overlay / modularize React headers (base of the stack). <React/…> via the framework module map; lowercase namespaces (react/, yoga/, jsi/, …) via the ReactNativeHeaders module map.
2. #57305 — Prebuilt artifact resources + ReactNativeHeaders.xcframework. Ships the prebuilt core artifacts (incl. ReactNativeHeaders in the tarball + embedded React.framework resources) and the CocoaPods React-Core-prebuilt facades.
3. #57440 — Self-serving prebuilt ReactNativeDependencies + dependency-only facades. The deps pod becomes the single header authority for the third-party namespaces (RCT-Folly/glog/boost/…); community `s.dependency "RCT-Folly"` resolves to local facades instead of trunk source pods.
4. #57442 — ReactNativeDependenciesHeaders sidecar + pure-RN ReactNativeHeaders (immediate base). The deps prebuild emits a headers-only LIBRARY-type sidecar (the binary deps xcframework is framework-type — invisible to SwiftPM binaryTargets), ReactNativeHeaders drops the third-party namespaces, and both headers artifacts publish standalone to Maven.

The whole stack is rebased onto current main (2026-07-06).

This PR consumes the final **five-artifact set**: React, ReactNativeHeaders (pure-RN), ReactNativeDependencies, ReactNativeDependenciesHeaders, hermes-engine.

Adds npx react-native spm and the package-generation tooling that turns an app into a SwiftPM-integrated RN app using the base stack's prebuilt XCFrameworks. CocoaPods stays supported — additive, opt-in, no Ruby toolchain. Integration is injected into the existing .xcodeproj in place (nothing generated/renamed/replaced), recorded in .spm-injected.json so it reverses exactly.

### What this PR adds

- The spm CLI (add/update/deinit/scaffold + hidden sync/codegen/download), zero-arg auto-resolution, --deintegrate for CocoaPods→SwiftPM.
- SwiftPM package generation (scripts/spm/): autolinking→Package.swift, Codegen→React-GeneratedCode, core XCFramework binary targets, artifact download/cache, surgical pbxproj inject/remove.
- ReactNativeDependenciesHeaders wired as the 5th binaryTarget: the headers-only companions (ReactNativeHeaders from the core tarball, the deps sidecar from the deps tarball) are staged automatically out of their parent tarballs — no --headers-tarball priming; REQUIRED_ARTIFACTS covers all five.
- Community-library scaffolding from podspecs (incl. root-level-source podspecs via generated include/<SwiftName>/ shims, sibling wiring for transitive spm.dependencies, self-ingestion guards).
- In-place Xcode integration (XCLocalSwiftPackageReference + Sync build phase + scheme pre-action + auto-sync; ${PODS_ROOT}-anchored REACT_NATIVE_PATH replaced on --deintegrate with exact deinit rollback).
- rn-tester + helloworld SwiftPM consumption + test library; npm-packaging hygiene; a small RNCoreFacades.podspec_dir fix.

## Documentation

- **Tool docs** (usage, quick start, architecture): [`scripts/spm/__doc__/spm-scripts.md`](https://github.com/react/react-native/blob/chrfalch/swift-package-manager/packages/react-native/scripts/spm/__doc__/spm-scripts.md)
- **Header-paths contract** (how the five artifacts serve headers): [`scripts/spm/__doc__/spm-header-paths-contract.md`](https://github.com/react/react-native/blob/chrfalch/swift-package-manager/packages/react-native/scripts/spm/__doc__/spm-header-paths-contract.md)
- **RFC** (updated): [react-native-community/discussions-and-proposals#994](react-native-community/discussions-and-proposals#994)

## Changelog:

[IOS] [ADDED] - `npx react-native spm` command + SwiftPM package-generation tooling (opt-in; CocoaPods stays supported)

Pull Request resolved: #57332

Test Plan:
350 scripts/spm unit tests (incl. byte-identical add→deinit round-trip); manual E2E against the five-artifact set: fresh app via `cli init`→`spm add --deintegrate`→build (artifact resources verified in the app), rn-tester in-place migration (RNTesterPods.xcodeproj, test libraries + spmModules), helloworld in-place migration — all BUILD SUCCEEDED. Verified `npx react-native spm <cmd>` from the command line in each journey.

## Scope & limitations

iOS, prebuilt-only (no build-from-source yet); full spm.xcframework/spm.source library metadata not yet (app-local spm.modules + scaffolding are); Expo not yet.

## Follow-ups

Remote-mode ReactNative Package.swift must vend the ReactNativeDependenciesHeaders product (spm-distribution repo); library self-containment for repo-portable manifests; build-from-source.

Reviewed By: mdvacca

Differential Revision: D111449548

Pulled By: cipolleschi

fbshipit-source-id: 87a873bf5c8be2d60f7893611e16924bfa730a46
)

Summary:
The OSS lint job went red after the SwiftPM stack landed (#57332 and its base PRs). The failing signal is the **Prettier** step of the `lint` job.

The offending file (introduced in base PR #57442) is:

`packages/react-native/scripts/ios-prebuild/__tests__/headers-xcframework-test.js`

```js
let tmp /*: string */;
```

This is a Flow *comment-type annotation* on an **uninitialized** `let`. Prettier reformats an uninitialized declaration by moving the trailing comment past the semicolon:

```js
let tmp; /*: string */   // annotation detached — no longer a type annotation
```

Because CI runs `prettier --list-different` (fails on any diff), this made the lint job fail. Prettier only keeps the `/*: string */` annotation inline when the declaration has an initializer, so the fix is to give `tmp` one:

```js
let tmp /*: string */ = '';
```

Semantically safe — `tmp` is assigned in `beforeEach` before any use.

## Changelog:

[INTERNAL] [FIXED] - Fix Prettier lint failure in `headers-xcframework` test

Pull Request resolved: #57564

Test Plan:
- `yarn format-check` — clean across the repo
- `yarn lint` (ESLint) — passes
- `yarn lint-markdown` — passes
- `yarn test-typescript-legacy` — passes
- Jest `headers-xcframework-test.js` — all 5 tests pass

Reviewed By: cortinico, fabriziocucci

Differential Revision: D112114604

Pulled By: cipolleschi

fbshipit-source-id: 9f2d116eae0cf5581cf0e1a1e79c0c3b28f7c176
@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 16, 2026
@cipolleschi
cipolleschi merged commit 486df8d into 0.87-stable Jul 16, 2026
40 of 43 checks passed
@cipolleschi
cipolleschi deleted the picks-57442-57332-57564 branch July 16, 2026 13:56
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: Facebook Partner: Facebook Partner Pick Request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants