Skip to content

feat: detect Swift Package Manager projects - #2858

Open
thymikee wants to merge 2 commits into
mainfrom
feat/spm-project-detection
Open

thymikee wants to merge 2 commits into
mainfrom
feat/spm-project-detection

Conversation

@thymikee

@thymikee thymikee commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #2856

React Native 0.87 ships react-native spm, which migrates the Xcode project to Swift Package Manager, strips React Native out of the Podfile and leaves the file on disk. We treated those projects as broken: with no Podfile found, getProjectConfig bailed out, so config had no project.ios.sourceDir and run-ios/build-ios insisted on installing pods.

  • findSpmProjectDir looks for the .xcodeproj containing .spm-injected.json — the marker react-native spm writes inside the project bundle, and react-native spm deinit removes. It wins over a leftover Podfile, since react-native spm refuses to migrate a CocoaPods-integrated project anyway.
  • project.ios.buildSystem is spm or cocoapods, so commands know where React Native comes from.
  • resolvePods returns whether pods were installed, instead of both callers setting installedPods = true next to it, and skips CocoaPods for spm projects. --force-pods / --only-pods still run it, which is how pods unrelated to React Native keep working next to Swift Package Manager. Forcing pods where there is no Podfile now errors with a hint to run react-native spm.

Libraries still need a Package.swift, which is RN's react-native spm scaffold + patch-package story. Nothing to configure in the CLI anymore — no project.ios.sourceDir, no automaticPodsInstallation: false, no stub Podfile, e.g. the ones needed in bottom-tabs' SPM example.

Test Plan

yarn test packages/cli-config-apple

Verified against a real 0.87.1 app migrated with node node_modules/react-native/scripts/setup-apple-spm.js add --deintegrate --yes, with this build linked into node_modules:

$ npx react-native config | jq '.project.ios | {sourceDir, buildSystem}'
{
  "sourceDir": "/tmp/spm-proto/SpmApp/ios",
  "buildSystem": "spm"
}

$ npx react-native build-ios
success Successfully built the app

$ npx react-native run-ios --simulator "Apex CI Smoke" --port 8090
success Successfully built the app
success Successfully launched the app

Debug and Release both build, install, launch and render the app; no CocoaPods step runs. RN's own generate-spm-autolinking-config.js succeeds against this config output — before the change it failed with CLI config did not provide project.ios.sourceDir. A CocoaPods project's output is identical apart from buildSystem: "cocoapods".

The e2e config snapshot doesn't see the new field: that test inits a project, which pulls @react-native-community/cli-platform-ios from the React Native template, so the iOS project config comes from the published CLI rather than this checkout. Its only update here is RN's new spm [action] command, which landed with 0.87 and is pre-existing drift rather than something from this change.

One unrelated thing I tripped over: run-ios --port starts the dev server on that port, but installApp launches the app with a bare simctl launch, so the app still asks the packager on 8081. I had to launch with -RCT_jsLocation localhost:8090 to load my bundle. Worth a separate issue.

Checklist

  • Documentation is up to date.
  • Follows commit message convention described in CONTRIBUTING.md.
  • For functional changes, my test plan has linked these CLI changes into a local react-native checkout (instructions).

React Native 0.87's `react-native spm` migrates the Xcode project to Swift
Package Manager and leaves the `Podfile` on disk, which left `config` without a
`project.ios.sourceDir` and made `run-ios`/`build-ios` try to install pods.

Look for the `.spm-injected.json` marker `react-native spm` writes inside the
migrated `.xcodeproj`, expose `project.ios.buildSystem` and skip CocoaPods for
those projects unless pods are explicitly requested.

Closes #2856
@github-actions github-actions Bot added docs Documentation change feature labels Sep 14, 2026
@mateusz1913

Copy link
Copy Markdown

Works for a sample app

  "project": {
    "ios": {
      "sourceDir": "/Users/mateusz.medrek/work/rn/TestSample087/ios",
      "xcodeProject": {
        "name": "TestSample087.xcodeproj",
        "path": ".",
        "isWorkspace": false
      },
      "automaticPodsInstallation": false,
      "assets": [],
      "buildSystem": "spm"
    },
    "android": {
      "sourceDir": "/Users/mateusz.medrek/work/rn/TestSample087/android",
      "appName": "app",
      "packageName": "com.testsample087",
      "applicationId": "com.testsample087",
      "mainActivity": ".MainActivity",
      "assets": []
    }
  }

`init` pulls the latest React Native, which contributes a `spm [action]`
command to the config output.

`buildSystem` is not part of this snapshot: the e2e project resolves the iOS
platform config through the CLI pinned in the React Native template, and the
field is covered by the unit tests instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation change feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support existing CLI apple project use cases without relying on podfile existing on the disk (projects using SPM)

2 participants