React-bridging header search path fails on iOS with use_frameworks! and pnpm

This issue has been tracked since 2022-09-21.

Description

https://github.com/evelant/test-pnpm-ios-headers-path-bug

iOS react-native header path failure with use_frameworks! and pnpm

When using pnpm as a package manager along with use_frameworks! iOS builds fail because the header files for
the React-bridging
pod don't get copied to the correct directory.

They should end up at iOS/Pods/Headers/Private/React-bridging/react/bridging
but they actually end up
at ios/build/Build/Products/Debug-iphonesimulator/React-bridging/.pnpm/[email protected]_xbangyd2oalr524ah376m5q3oi_tf4i3rco7go2qrnsv66v2274bm/node_modules/react-native/ReactCommon/react/bridging
.

I'm not sure if this is specific to EAS build but that's what I use so I made the repro using it.

Motivation

use_framewoks! is a requirement for react-native-firebase v15 and up since the underlying
google libraries have a hard requirement for it. I need to use v15+ in my app to support firebase cloud functions v2.

pnpm is used because I've been bitten by "ghost dependencies" too many times in a monorepo. Hoisting all packages to
root level and allowing any package to be resolved if it just happens to be required transitively by any project in
the repo is a recipe for pain. pnpm fixes that by disallowing resolution of undeclared dependencies,
requiring correct peer deps, and not hoisting anything globally. See below for tweaks needed to work around metro deficiencies.

To reproduce

  1. npm install -g pnpm
  2. npm install -g eas-cli
  3. pnpm install
  4. pnpm build-local

Observe the build failing. Result is a temp folder output at the end of build. Open it with XCode to see the mangled
path in the build phases of the React-bridging pod.

Manual fix

If you change the copy phase of the React-bridging pod to an absolute path of
$(PODS_ROOT)/Headers/Private/React-bridging/react/bridging
the headers get copied to the correct location. This fixes building of the pods project but the main project still
fails.

Add $(PODS_ROOT)/Headers/Private/React-bridging to the main project header search paths and the project will finally
build.

Possibly related issues

#34102

CocoaPods/CocoaPods#2382

CocoaPods/CocoaPods#6603

CocoaPods/CocoaPods#9451

CocoaPods/CocoaPods#5790

pnpm setup

To make pnpm work with react-native there are a couple of changes to the expo defaults for this project

  1. metro.config.js
    uses @rnx-kit/metro-resolver/symlinks
    to work around lack of symlink support in metro
  2. .npmrc contains a couple public-hoist-pattern entries to ensure some undeclared dependencies are resolvable in
    node_modules.
  3. There are a few dependencies added to devDependencies since pnpm doesn't allow undeclared dependencies to be
    resolved, they need to be stated explicitly instead of hopefully/maybe installed as a transitive dep.

Fixes attempted

  1. patches/[email protected] fixes the header path of React-bridging per react-native #34102
  2. update_ios_podfile_plugin.js modifies the Podfile to work around CocoaPods #5970
    (not sure if entirely necessary)

Per the above reproduction description the build can be made to work by manually fixing the copy step of the
React-bridging pod and manually adding a header search path to the root project.

I'm not sure how to apply proper fixes for either of those issues.

Environment info

System:
    OS: macOS 12.5.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 234.75 MB / 16.00 GB
    Shell: 0.68.1 - /Users/imagio/.cargo/bin/nu
  Binaries:
    Node: 16.17.0 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/node
    Yarn: 1.22.19 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/yarn
    npm: 7.18.1 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/npm
    Watchman: Not Found
  Managers:
    CocoaPods: 1.11.3 - /Users/imagio/.asdf/shims/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 16.0, macOS 12.3, tvOS 16.0, watchOS 9.0
    Android SDK: Not Found
  IDEs:
    Android Studio: Dolphin 2021.3.1 Dolphin 2021.3.1
    Xcode: 14.0/14A309 - /usr/bin/xcodebuild
  Languages:
    Java: 17.0.4.1 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.0.0 => 18.0.0
    react-native: 0.69.5 => 0.69.5
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Version

0.69.5

Output of npx react-native info

System:
OS: macOS 12.5.1
CPU: (10) arm64 Apple M1 Pro
Memory: 234.75 MB / 16.00 GB
Shell: 0.68.1 - /Users/imagio/.cargo/bin/nu
Binaries:
Node: 16.17.0 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/node
Yarn: 1.22.19 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/yarn
npm: 7.18.1 - ~/Library/Caches/fnm_multishells/47864_1663586667411/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.11.3 - /Users/imagio/.asdf/shims/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 16.0, macOS 12.3, tvOS 16.0, watchOS 9.0
Android SDK: Not Found
IDEs:
Android Studio: Dolphin 2021.3.1 Dolphin 2021.3.1
Xcode: 14.0/14A309 - /usr/bin/xcodebuild
Languages:
Java: 17.0.4.1 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.0.0 => 18.0.0
react-native: 0.69.5 => 0.69.5
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

  1. npm install -g pnpm
  2. npm install -g eas-cli
  3. pnpm install
  4. pnpm build-local

Observe the build failing. Result is a temp folder output at the end of build. Open it with XCode to see the mangled
path in the build phases of the React-bridging pod.

Snack, code example, screenshot, or link to a repository

https://github.com/evelant/test-pnpm-ios-headers-path-bug

cortinico wrote this answer on 2022-09-21

Thanks for your detailed explanation @evelant

We're aware that the support for use_frameworks as well as pnpm is suboptimal. @mikehardy knows way more than me on use_frameworks and can help here. pnpm support instead is probably affected by the lack of Symlink support on Metro.

On CI, we can't test every possible package manager, so we generally focus on npm/yarn.

I would suggest you move this issue on react-native-firebase repo as you might get better support there as other users are facing your same challenges.

evelant wrote this answer on 2022-09-21

@cortinico pnpm works fine without use_frameworks! thanks to the @rnx-kit/metro-resolver-symlinks plugin. It's only with use_frameworks! that the copy path for React-bridging headers goes wrong. Unfortunately I'm not sure how to diagnose it further, I was unable to find where that path gets calculated. I'll raise this with react-native-firebase, although it's not actually related to firebase at all, you're right it's probably the most likely place others will be encountering this.

cortinico wrote this answer on 2022-09-21

you're right it's probably the most likely place others will be encountering this.

Yeah exactly. If we pinpoint the issue, we can tweak the setup on our end to accomodate for this setup. Currently it's a bit hard to investigate for us as we don't actively use use_frameworks internally. RN Firebase folks might already have a solution for this.

mikehardy wrote this answer on 2022-09-21

Funny, I saw this after seeing the react-native-firebase issue (I prioritize those issues first so I was a little out of order reading this)

I was also going to suggest the microsoft RNX-Kit work for symlinks and I'm sorry to see that has been suggested and yet does not work.

Unfortunately as mentioned in react-native-firebase, react-native-firebase also does not really seem like the home for this.

This appears to be a frustratingly "in-between" bug, but I already have one of those ("let's make use_frameworks work everywhere" 😆 ) so I cannot take on another one ("let's make pnpm work everywhere...")

We do not already have a solution for pnpm, and all I can say with my experience attempting to figure out use_frameworks stuff is that you will have to drive the solution, bit by bit where problems are uncovered, and work diligently to push PRs upstream

Sounds a little dissatisfying as I type it but I'm not aware of a better way

More Details About Repo
Owner Name facebook
Repo Name react-native
Full Name facebook/react-native
Language JavaScript
Created Date 2015-01-09
Updated Date 2022-10-03
Star Count 105144
Watcher Count 3666
Fork Count 22469
Issue Count 2232

YOU MAY BE INTERESTED

Issue Title Created Date Updated Date