Skip to content

fix(ios): narrow the podspec's public headers - #1448

Merged
msluszniak merged 2 commits into
mainfrom
@ms/podspec-public-headers
Sep 9, 2026
Merged

fix(ios): narrow the podspec's public headers#1448
msluszniak merged 2 commits into
mainfrom
@ms/podspec-public-headers

Conversation

@msluszniak

@msluszniak msluszniak commented Sep 8, 2026

Copy link
Copy Markdown
Member

Description

use_frameworks! makes CocoaPods build this pod as a framework, and two things break there:

  • plain use_frameworks! means dynamic linkage (what Firebase's docs show), and pod install refuses it: transitive dependencies that include statically linked binaries: opencv2.xcframework
  • every header was public, and 21 basenames repeat, so Xcode flat-copies them onto each other: Multiple commands produce .../Headers/Types.h

Fixed with s.static_framework = true and public_header_files limited to the Objective-C entry points. The C++ headers stay reachable through HEADER_SEARCH_PATHS.

Root cause found by @barhanc.

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

Expo 57 app with the pod kept as a framework:

podspec pod install xcodebuild
as published fails
+ static_framework passes fails, 21 errors
+ both passes BUILD SUCCEEDED

No regression: :linkage => :static installs clean, and a clean build with no use_frameworks! still succeeds.

__tests__/api/podspecPublicHeaders.test.ts fails if public_header_files is dropped (the shipped 0.10.0 state) or widened onto the C++ tree.

Related issues

#203

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

`use_frameworks!` builds the pod as a framework, and Xcode flat-copies
every public header into one `Headers/` directory. With no
`public_header_files` every header in `source_files` is public, and 21
basenames occur more than once, so the build fails at planning with
`Multiple commands produce .../Headers/Types.h`.

Restrict the public set to the Objective-C entry points; the C++ headers
are already reached through HEADER_SEARCH_PATHS. Fixes discussion #203.

Co-authored-by: Bartosz Hanc <bartosz.hanc02@gmail.com>
@msluszniak msluszniak added platform: ios Issues and tasks related to iOS important ❗ This issue has high priority bug fix PRs that are fixing bugs labels Sep 8, 2026
@msluszniak
msluszniak requested a review from barhanc September 8, 2026 21:19
`use_frameworks!` with no linkage argument means dynamic, which is what
Firebase's setup instructions show. CocoaPods then refuses to install,
because a dynamic framework may not carry statically linked binaries and
opencv-rne vendors one:

  [!] The 'Pods-YourApp' target has transitive dependencies that include
  statically linked binaries: (.../opencv-rne/opencv2.xcframework)

`s.static_framework = true` resolves it without the app having to spell out
`:linkage => :static`, and is inert when the pod builds as a static library.

Verified on an Expo 57 app with the pod kept as a framework: dynamic
linkage goes from a failed `pod install` to `** BUILD SUCCEEDED **` with
this and the public-header fix together, and the default configuration
still builds clean.
@msluszniak
msluszniak merged commit 12ce3bb into main Sep 9, 2026
5 checks passed
@msluszniak
msluszniak deleted the @ms/podspec-public-headers branch September 9, 2026 12:03
msluszniak added a commit that referenced this pull request Sep 9, 2026
## Description

The `react-native-worklets` peer was `^0.10.0` and undocumented: the
requirements page claimed React Native 0.81+ / Expo SDK 54+, which that
peer rules out, and the install command asks for worklets with no
version.

- peer becomes `>=0.10.0 <0.13.0`. `^0.10.0` excluded worklets 0.11 and
0.12, the current releases, which carry the same API and typecheck clean
here.
- 0.10 stays the floor: it is the first release to serialize an
`ArrayBufferView` natively ([reanimated
#9475](software-mansion/react-native-reanimated#9475)).
Below it a view is rebuilt over its whole backing buffer, so `new
Uint8Array(buffer, 64, 16)` arrives with `length` 1024 instead of 16.
Our public API takes views from user code, so that is silent corruption,
not slowness.
- Getting Started states the range and what SDK 55/56 users must
install, since those SDKs bundle an older worklets and Reanimated pins
it exactly:

  ```bash
npm install react-native-worklets@^0.10.0 react-native-reanimated@^4.5.0
  ```

Cost: Expo SDK 54, React Native 0.81 and 0.82 drop out. Expo 55 and 56
are inside worklets 0.10's range once asked for explicitly.

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [x] iOS
- [ ] Android

### Testing instructions

| worklets | React Native peer | native ArrayBufferView serialization |
| --- | --- | --- |
| 0.8.3 / 0.9.3 | `0.81 - 0.85` | no |
| 0.10.4 / 0.11.4 | `0.83 - 0.86` | yes |
| 0.12.2 | `0.83 - 0.87` | yes |

`__tests__/api/workletsVersionRange.test.ts` ties the range to the
installed worklets, to the React Native floor it implies, and to the
number in the docs, which is the pair that drifted.

### Related issues

Follow-up to the compatibility question raised alongside #1448.

### Checklist

- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly
- [x] My changes generate no new warnings

### Additional notes

The first commit took the opposite approach (peer down to 0.8.0 plus a
copy at the worklet boundary); the second supersedes it, so review the
net diff.

`0.8.x` / `0.9.x` on React Native 0.86 are marked untested rather than
guessed. Flip those cells if you know.

---------

Co-authored-by: Bartosz Hanc <bartosz.hanc02@gmail.com>
Co-authored-by: Mateusz Słuszniak <msluszniak1@gmail.com>
msluszniak added a commit that referenced this pull request Sep 9, 2026
0.10.0 is `lastVersion`, so the pages users land on still carried the
pre-#1448/#1449/#1450 state: React Native 0.81+ / Expo SDK 54+, no
worklets floor, no troubleshooting.

- getting-started and the compatibility table take the #1449 changes
  verbatim, plus the minSdkVersion and troubleshooting pointers
- native-libraries takes the monorepo and pnpm notes
- a Troubleshooting page written against what 0.10.0 actually ships:
  the `use_frameworks!` header collision needs the Podfile
  `pre_install` workaround, the OpenCV conflict has no `opencvPod`
  escape hatch, and `minSdkVersion` defaults to 21 against API 26 `.so`
  files

Also corrects the monorepo note on the current docs, which still said an
app-level block is always ignored - the lookup now walks up from the
installed package too.
msluszniak added a commit that referenced this pull request Sep 9, 2026
#1452)

## Description

Two defects in #1450, both reproduced against `main` at `a1ff6c9`.

**`if enable_opencv` was never closed.** Its `end` sat at the bottom of
the spec, one line above `install_modules_dependencies(s)`, and the
indentation of everything after the `s.dependency` call reads as if the
block had already ended. So five attributes were assigned only when
OpenCV was on:

| attribute | what an app loses without it |
| --- | --- |
| `pod_target_xcconfig` | every `HEADER_SEARCH_PATHS` entry |
| `vendored_frameworks` | `ExecutorchLib.xcframework` |
| `static_framework` | the `use_frameworks!` fix from #1448 |
| `libraries` | `z`, `sqlite3` |
| `frameworks` | `Accelerate`, `CoreML`, Metal |

An app that turns OpenCV off through the `libs` config block installs
fine and then fails to compile or link. #1450 is what made this
reachable: before it, a config block in an app package was ignored and
OpenCV was always on.

**`rne_build_config` was nil without a config file.** The `else` branch
set the five `enable_*` flags but never assigned the hash, and #1450
added `rne_build_config["opencvPod"]` on the path that branch reaches,
so a checkout without `rne-build-config.json` raised `NoMethodError`
during `pod install`. The comment above it names that case as supported
("a fresh checkout where the native libs were provisioned manually").
The branch is gone: the config is a hash either way, and every flag
already reads `!= false`, so an empty hash means all-enabled.

**Test.** `pod install` is the only thing that runs this file, and every
example app takes the same config row, so a misplaced `end` passes lint,
types, tests and review. `__tests__/api/podspecAttributes.test.ts`
evaluates the real podspec under a stubbed `Pod::Spec` and asserts the
build-critical attributes are assigned, for eight config rows. Against
`a1ff6c9` it fails three of them:

```
● with no config file (manual provisioning)
  podspec:242: undefined method `[]' for nil:NilClass (NoMethodError)
● with opencv off
● with every optional library off
  missing: pod_target_xcconfig, static_framework, vendored_frameworks, libraries, frameworks
```

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [ ] iOS
- [ ] Android

### Testing instructions

```bash
yarn workspace react-native-executorch test __tests__/api/podspecAttributes.test.ts
git stash && yarn workspace react-native-executorch test __tests__/api/podspecAttributes.test.ts  # 3 failures
```

Needs an `enableOpencv: false` `pod install` on a device build before
merge; I have only run the podspec evaluation.

### Related issues

Follow-up to #1450.

### Additional notes

Backport to `release/0.10` goes on top of #1451.
msluszniak added a commit that referenced this pull request Sep 9, 2026
)

## Description

Backports the three 0.10.0 setup fixes from `main` to `release/0.10`,
plus the follow-up that fixes two defects in the third one.
Cherry-picked with `-x`, no manual edits to any of them.

| commit | PR |
| --- | --- |
| `12ce3bb` | #1448 fix(ios): narrow the podspec's public headers |
| `c51f76a` | #1449 fix(deps): require worklets >=0.10.0 <0.13.0 and
document it |
| `a1ff6c9` | #1450 fix(build): fail with the cause when the setup is
wrong |
| `080e764` | #1452 fix(ios): keep the podspec's build attributes out of
the OpenCV branch |

All four are now on `main`; #1452 merged as `c8f44f6`.

Only conflict was `docs/versioned_docs/version-0.10.0/**`: that snapshot
exists on `main` only, since on this branch `docs/docs` **is** the 0.10
documentation. Those three hunks were dropped and the equivalent
`docs/docs` changes came across in the same commits.

`packages/react-native-executorch/package.json` keeps `0.10.0`; only the
worklets peer range changed.

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [ ] iOS
- [ ] Android

### Testing instructions

`yarn workspace react-native-executorch test` passes, 3868 tests across
34 suites.

The podspec, `android/build.gradle.kts`, `scripts/download-libs.js` and
the new podspec test on this branch are byte-identical to `main`:

```bash
git fetch origin main
git diff origin/main HEAD -- packages/react-native-executorch/react-native-executorch.podspec \
  packages/react-native-executorch/android/build.gradle.kts \
  packages/react-native-executorch/scripts/download-libs.js \
  packages/react-native-executorch/__tests__/api/podspecAttributes.test.ts
```

### Related issues

#1448, #1449, #1450, #1452

---------

Co-authored-by: Bartosz Hanc <bartosz.hanc02@gmail.com>
Co-authored-by: Mateusz Słuszniak <msluszniak1@gmail.com>
@msluszniak msluszniak mentioned this pull request Sep 9, 2026
7 tasks
msluszniak added a commit that referenced this pull request Sep 9, 2026
## Description

Patch release **v0.10.1**. The fixes are already on `release/0.10` via
#1451 (backports of #1448, #1449, #1450, #1452); this PR only bumps the
version.

- `packages/react-native-executorch/package.json`: `0.10.0` -> `0.10.1`.
`nativeLibsVersion` stays `0.10.0`; the native artifacts release is
unchanged.
- `src/fetcher/telemetry.ts`: `LIB_VERSION` -> `0.10.1`, asserted equal
to the package version by `__tests__/fetcher/telemetry.test.ts`.

Satellites (`bare-resource-fetcher`, `expo-resource-fetcher`, `webrtc`)
are untouched by the backports, so their versions stay at `0.10.0`.
`models.ts` stays on `resolve/v0.10.0`; no model files moved.

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Other (chores, tests, code style improvements etc.)

### Tested on

- [ ] iOS
- [ ] Android

### Testing instructions

CI runs `yarn workspace react-native-executorch test`; the telemetry
version assertion covers the bump.

### Related issues

#1451

### Checklist

- [x] I have performed a self-review of my code
- [x] My changes generate no new warnings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug fix PRs that are fixing bugs important ❗ This issue has high priority platform: ios Issues and tasks related to iOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants