Repository navigation
Conversation
Summary: The SwiftPM setup adds a "Sync SPM Autolinking" pre-action to the app's Xcode scheme. The pre-action never ran its sync step. The script is many lines long. `escapeXmlAttribute` wrote it into the `scriptText` XML attribute with raw line breaks. An XML parser replaces each raw line break in an attribute value with a space (XML 1.0 §3.3.3). So Xcode read the script as one line. The second line of the script is a `#` comment, so everything after `set -euo pipefail` became part of that comment. This PR makes two changes in `packages/react-native/scripts/spm/generate-spm-xcodeproj.js`: - `escapeXmlAttribute` now also encodes `\r`, `\n` and `\t` as `&https://github.com/react/react-native/issues/13;`, `&https://github.com/react/react-native/issues/10;` and `&https://github.com/react/react-native/issues/9;`. Xcode itself writes the script this way. - `deinit` deletes a scheme that RN created only when the scheme is still unchanged. This check now ignores the value of the script. Without this change, a scheme that an older version wrote with raw line breaks would no longer match, and `deinit` would leave it on disk. The XML decoder had no callers left after this change, so this PR removes it. Existing projects get the fixed script when the user runs `npx react-native spm update` once. The build-time `sync` does not rewrite the scheme. ## Changelog: [IOS] [FIXED] - SwiftPM: keep line breaks in the scheme pre-action script so that the "Sync SPM Autolinking" pre-action runs. Run `npx react-native spm update` once to rewrite an existing scheme. Pull Request resolved: #58826 Test Plan: New tests: - `generate-spm-xcodeproj-test.js`: parses the generated scheme with `xmldom/xmldom` and checks that the script keeps its line breaks and tabs. A second test checks that a refresh of an older scheme with raw line breaks writes `&https://github.com/react/react-native/issues/10;`. - `remove-spm-injection-test.js`: checks that `deinit` still deletes an RN-created scheme whose script has raw line breaks. ``` yarn jest --no-cache -i packages/react-native/scripts/spm/__tests__/generate-spm-xcodeproj-test.js packages/react-native/scripts/spm/__tests__/remove-spm-injection-test.js ``` - Before the fix: 2 failed, 124 passed (the two `generate-spm-xcodeproj` tests). - With only the encoding change: the new `deinit` test and 4 existing `deinit` tests failed. - With both changes: 2 suites passed, 126 tests passed. ESLint and Prettier pass on the changed files. `flow check-contents` reports no errors for `generate-spm-xcodeproj.js`. I did not build an app in Xcode for this PR. An Expo app had the problem: when the line breaks in its scheme were changed to `&https://github.com/react/react-native/issues/10;` by hand, the pre-action ran. Reviewed By: christophpurrer Differential Revision: D123382914 Pulled By: cipolleschi fbshipit-source-id: 0c51cb7c6fe7a66567602d813a13381f6bf3704f (cherry picked from commit b8df948)
Summary: The SwiftPM build-time sync runs only when its stamp is older than one of the files it watches. A watched path that did not exist at the last sync was dropped from the watch list. So when that path appeared later, the sync did not run. Examples: - A plugin watches its precompiled-module folder. On a fresh clone, that folder does not exist yet, so later precompiles never trigger a sync. - A dependency has no root `Package.swift` or `.react-native/` folder. When one appears later, for example after `npx react-native spm scaffold`, the dependency is detected differently, but the sync does not run. This PR writes missing watch paths to a new file, `.spm-sync-watch-absent`. The stamp is stale when one of those paths now exists. The missing paths do not go to `.spm-sync-watch-paths`, because projects from older versions treat a missing path in that file as stale and would sync on every build. Those projects get this fix after running `npx react-native spm update` once. The paths that can go to `.spm-sync-watch-absent`: - a plugin `watchPaths` entry that does not exist yet - the root `Package.swift` and `.react-native/` of each dependency, when they do not exist The docs now tell plugins to list their precompiled-module folder in `watchPaths`, but only a folder that the Xcode build does not write to. This PR does not watch `project.pbxproj`. Xcode rewrites that file on many edits in the IDE, so watching it would run a full sync after each edit. #58827 makes `.spm-injected.json` a watched file instead. Only `spm add` and `spm update` change that file. This PR is independent of #58827. They can land in either order. Both change the generated sync check, so the second one to land needs a rebase. ## Changelog: [IOS] [FIXED] - SwiftPM: the build-time sync now runs again when a watched path that did not exist at the last sync appears. Pull Request resolved: #58828 Test Plan: ``` yarn jest --no-cache -i packages/react-native/scripts/spm/__tests__/ ``` Result: 21 suites and 1010 tests pass. - `generate-spm-autolinking-test.js`: - A missing watch path goes to `.spm-sync-watch-absent` only. This test failed before the change. - A dependency without a root `Package.swift` or `.react-native/` lists both paths as absent. The first version of this PR already did this, so the test passed at once. Removing the two paths from the code makes it fail. - `project.pbxproj` is not watched. This test failed before the change. - `generate-spm-xcodeproj-test.js`: runs the shipped bash check under `/bin/bash`. The stamp is stale only when a path listed as absent now exists. Reviewed By: andrewdacenko Differential Revision: D125206241 Pulled By: cipolleschi fbshipit-source-id: 2cb530615941b15adb27f8fcc4699812538e9f3d (cherry picked from commit c89f412)
This was referenced Oct 21, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Port of c89f412 (#58828, "Re-sync SwiftPM autolinking when a watched path appears") to
0.88-stable. That commit already landed in main. This PR exists so that the 0.88 pick does not run into merge conflicts.This is PR 2 of 5 in a stack. Each PR contains the commits of the PRs before it. Merge them in order:
Pick request: reactwg/react-native-releases#1450
Changelog:
[IOS] [FIXED] - SwiftPM: the build-time sync now runs again when a watched path that did not exist at the last sync appears.
Test Plan:
git cherry-pick -x c89f4120ac7, no conflicts. The change is the same as on main (git patch-idmatches).yarn jest --no-cache -i packages/react-native/scripts/spmon this branch: all pass. Counts per branch: 0.88-stable 1005, then 1008, 1010, 1052, 1052, 1099 tests.