Skip to content

Commit 9379eb3

Browse files
chrfalchclaude
andcommitted
Docs: qualify deinit's byte-identical promise for a promoted setting
`spm add` promotes an array build setting that is already present as a scalar (`HEADER_SEARCH_PATHS`, `OTHER_LDFLAGS`, `FRAMEWORK_SEARCH_PATHS`, `LD_RUNPATH_SEARCH_PATHS`), and reversing that promotion rewrites the whole field, because the injected members and the user's own are indistinguishable once folded together. Members hand-added to such an array afterwards are lost on `deinit`, and on `update`, which reverts to the recorded baseline before re-injecting. The docs claimed the pre-`add` restore was byte-identical with no qualification. ## Summary: - Follow a stock Xcode app target being an instance of this (the template writes `LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";` as a target-level scalar), so the caveat reads as concrete rather than theoretical, and note that an existing array keeps the shape it was written in — including the one-line form hand edits and other generators emit. - The `.spm-injected.json` row of "What to commit" described the marker as a record of injected edits only; it also pins the pre-injection value of a build setting `add` rewrote. Docs only; no behavior change. ## Changelog: [Internal] - SwiftPM: document that `deinit` cannot preserve members added by hand to a promoted array build setting ## Test Plan: Prose review of `packages/react-native/scripts/spm/__doc__/spm-scripts.md`. Every claim traced to this PR's code: the recorded marker key (`promotedArrayScalars` on `BuildSettingChange`), the settings merged as arrays (`INJECTED_ARRAY_SETTINGS` + `frameworkArrayBuildSettings`), the whole-field rewrite in `removeRecordedBuildSettings`, and `update` re-applying from `removeRecordedBuildSettings(original, prevMarker…)`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent f4c790d commit 9379eb3

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

packages/react-native/scripts/spm/__doc__/spm-scripts.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ package graph, or require a second build.
161161
| Path | Commit? | Why |
162162
|------|---------|-----|
163163
| `MyApp.xcodeproj/` | Yes | Your project, with SwiftPM injected in place. Holds your signing, capabilities, Build Phases — `add` only adds SwiftPM refs/settings, additively. |
164-
| `MyApp.xcodeproj/.spm-injected.json` | Yes | Marker recording every edit `add` made, so `deinit` can surgically reverse it and re-runs stay idempotent. |
164+
| `MyApp.xcodeproj/.spm-injected.json` | Yes | Marker recording every edit `add` made — plus the pre-injection value of any build setting it rewrote — so `deinit` can surgically reverse it and re-runs stay idempotent. |
165165
| `build/generated/` | No | Codegen/autolinking output; regenerated |
166166
| `build/xcframeworks/` | No | Symlinks to the machine-local artifact cache |
167167
| `Package.resolved` | No | SwiftPM resolution file; machine-specific |
@@ -173,7 +173,22 @@ stays untouched, and a re-run is a no-op. The injected refs point at three
173173
stable sub-package paths under `build/`; adding or removing community deps
174174
changes the sub-package contents (gitignored) and never re-injects. `deinit`
175175
removes exactly what was injected (using the marker), leaving the project
176-
byte-identical to its pre-`add` state.
176+
byte-identical to its pre-`add` state — with one exception, described next.
177+
178+
**Build settings that already exist** are edited in place. The four array
179+
settings `add` merges into — `HEADER_SEARCH_PATHS`, `OTHER_LDFLAGS`,
180+
`FRAMEWORK_SEARCH_PATHS`, `LD_RUNPATH_SEARCH_PATHS` — keep the shape they were
181+
written in: Xcode's multi-line form as well as the compact one-line form hand
182+
edits and other generators (XcodeGen, Tuist) emit. One that exists as a plain
183+
*scalar* is promoted to a `( … )` array — the shape an Xcode-authored target can
184+
carry, e.g. a
185+
`LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";` written
186+
as a scalar rather than a list. `add` records the pre-injection value in the
187+
marker and
188+
`deinit` restores it by rewriting the whole field — once folded together, the
189+
injected members and your own are indistinguishable — so **members you add to
190+
a promoted array by hand afterwards are lost**. That applies to `update` too,
191+
which reverts to the recorded baseline before re-injecting.
177192

178193
Because everything under `build/` is gitignored, a clean checkout has no
179194
resolvable Swift packages until they are regenerated — see the next section.

0 commit comments

Comments
 (0)