Skip to content

[0.88] [iOS][SPM] Derive the generated manifests' iOS platform floor from the app (+2 prerequisites) #1414

Description

@fabriziocucci

Target Branch

0.88

Link to commit or PR to be picked

Pick in this order (oldest first):

  1. [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
  2. 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
  3. [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.name as the fix, where previously colliding names were auto-corrected. The old behaviour invented a module name no #import could predict, so the error is the better outcome, but it is new.
  • SCAFFOLDER_VERSION bumps to 20, so existing scaffolds regenerate with the new floor on the next spm 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.

Activity

  1. github-actions commented on Sep 15, 2026

    @github-actions

    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
    1. ✅ Fixes for regressions to core APIs. Examples:
      • A core component is behaving differently between versions 0.X and 0.X-1
      • The TurboModule.getEnforcing function is throwing an unexpected assertion error.
    2. ✅ Fixes to bugs in core React Native. Examples:
      • Breakpoints in React Native DevTools not working correctly in the debugger
      • Fast Refresh not working as expected
      • Metro bundler not starting properly or ignoring the configuration file
      • Buttons that are not clickable
    3. ✅ Fixes to APIs used by third-party libraries and out-of-tree platforms. Examples:
      • An API used by react-native-macos is not behaving as expected or is regressing
    4. ✅ Bump of patch version of dependencies. Example:
      • Bump Gradle from 8.11.0 to 8.11.1
    5. ✅ Fixes for low/high severity security vulnerabilities. Example:
      • Bump Gradle from 8.11.0 to 8.12.0 if there is a security vulnerability in 8.11 and no 8.11.x version contains the same fix.
    6. ✅ Fixes and reverts of accidental breaking changes. Example:
      • Reverting or fix-forwarding a Kotlin migration of a file (e.g. ReactRootView.java) if it is causing a breaking change for the React Native ecosystem.
    7. ✅ Performance improvements. Examples:
      • Fixing unnecessary re-renders in FlatList.
    8. ✅ Any Pick Request if the release is still in RC0 (after RC1, the previously listed criteria apply)
    ❌ Which Pick Requests we don't accept
    1. ❌ Any Pick Request that introduces a breaking change after RC1. Example:
      • A bugfix that contains a refactoring, resulting in changes to the public API of a class
    2. ❌ Any Pick Request that introduces a new feature after RC1. Example:
      • A commit that introduces a new API or a specific feature for a component.
    3. ❌ Bump of major or minor version of dependencies. Examples:
      • Bump Gradle from 8.11.0 to 8.12.0
      • Bump Gradle from 8.11.0 to 9.0.0
    4. ❌ Bump of a dependency to a pre-release version. Example:
      • Bump Gradle from 8.11.0 to 8.11.1-beta.1
    5. ❌ Any Pick Request that introduces changes to the React Native testing infrastructure after RC1. Examples:
      • Changes to GitHub Actions workflows to optimize them, even if they are on main.
      • Changes to the logic used to publish packages to NPM or Maven Central
    6. ❌ Pick Request composed of multiple commits that have several merge conflicts.
      • If your Pick Request is too complex to apply to the release branch, it will be rejected.
    7. ❌ Any non-critical improvement that landed on main.
      • These will generally ship in the following version unless they fit one of the criteria above.
    8. ❌ Any Pick Request considered a "nice to have".
      • Even one-line changes carry a risk of destabilizing and further delaying the release.
    ℹ️ What makes for a good Pick Request

    In order for your Pick Request to be considered, please do the following:

    • ℹ️ Limit your Pick Request to one commit from main, or one PR against the release branch.
    • ℹ️ Include a clear explanation of why your Pick Request should be considered, ideally referencing one of the criteria above.
    • ℹ️ Target only one minor version of React Native (e.g. [0.76]). To have your Pick Request applied to more versions, please open separate Pick Requests.
  2. changed the title [-][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)[/+] on Sep 15, 2026
  3. fabriziocucci commented on Sep 15, 2026

    @fabriziocucci
    CollaboratorAuthor

    Picked manually into 0.88-stable:

    PR Commit on 0.88-stable
    #58290 38302c95345
    #58362 903c4ab7636
    #58379 6069149f257

    All three applied without conflicts. SPM test suites pass: 1001 tests across 21 suites.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions