Skip to content

Commit c105182

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. - 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. [Internal] - SwiftPM: document that `deinit` cannot preserve members added by hand to a promoted array build setting 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 7b1718c commit c105182

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
@@ -195,7 +195,7 @@ package graph, or require a second build.
195195
| Path | Commit? | Why |
196196
|------|---------|-----|
197197
| `MyApp.xcodeproj/` | Yes | Your project, with SwiftPM injected in place. Holds your signing, capabilities, Build Phases — `add` only adds SwiftPM refs/settings, additively. |
198-
| `MyApp.xcodeproj/.spm-injected.json` | Yes | Marker recording every edit `add` made, so `deinit` can surgically reverse it and re-runs stay idempotent. Also pins settings later runs and Xcode builds must reuse, such as the [autolinking config command](#the-autolinking-config-command-is-remembered). |
198+
| `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. Also pins settings later runs and Xcode builds must reuse, such as the [autolinking config command](#the-autolinking-config-command-is-remembered). |
199199
| `build/generated/` | No | Codegen/autolinking output; regenerated |
200200
| `build/xcframeworks/` | No | Symlinks to the machine-local artifact cache |
201201
| `Package.resolved` | No | SwiftPM resolution file; machine-specific |
@@ -207,7 +207,22 @@ stays untouched, and a re-run is a no-op. The injected refs point at three
207207
stable sub-package paths under `build/`; adding or removing community deps
208208
changes the sub-package contents (gitignored) and never re-injects. `deinit`
209209
removes exactly what was injected (using the marker), leaving the project
210-
byte-identical to its pre-`add` state.
210+
byte-identical to its pre-`add` state — with one exception, described next.
211+
212+
**Build settings that already exist** are edited in place. The four array
213+
settings `add` merges into — `HEADER_SEARCH_PATHS`, `OTHER_LDFLAGS`,
214+
`FRAMEWORK_SEARCH_PATHS`, `LD_RUNPATH_SEARCH_PATHS` — keep the shape they were
215+
written in: Xcode's multi-line form as well as the compact one-line form hand
216+
edits and other generators (XcodeGen, Tuist) emit. One that exists as a plain
217+
*scalar* is promoted to a `( … )` array — the shape an Xcode-authored target can
218+
carry, e.g. a
219+
`LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";` written
220+
as a scalar rather than a list. `add` records the pre-injection value in the
221+
marker and
222+
`deinit` restores it by rewriting the whole field — once folded together, the
223+
injected members and your own are indistinguishable — so **members you add to
224+
a promoted array by hand afterwards are lost**. That applies to `update` too,
225+
which reverts to the recorded baseline before re-injecting.
211226

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

0 commit comments

Comments
 (0)