Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.73 fails to build on iOS with use_frameworks! :static due to yoga header path issue #41938

Closed
evelant opened this issue Dec 14, 2023 · 70 comments
Labels
Needs: Triage 🔍 Platform: iOS iOS applications. Type: Upgrade Issue Issues reported from upgrade issue form

Comments

@evelant
Copy link

evelant commented Dec 14, 2023

Old Version

0.72.7

New Version

0.73.0

Description

As seems to happen with every new version, header paths are broken on iOS with use_frameworks! :static

pnpm install

pnpm expo start

eas build -p ios --profile development --local

fails to compile due to header paths issue

[RUN_FASTLANE] › Compiling .pnpm Pods/Yoga » PixelGrid.cpp
[RUN_FASTLANE]
❌  (node_modules/.pnpm/react-native@0.73.0_@babel+core@7.23.6_@babel+preset-env@7.23.6_react@18.2.0/node_modules/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp:10:10)

   8 | #include <yoga/Yoga.h>
   9 |
> 10 | #include <yoga/algorithm/PixelGrid.h>
     |          ^ 'yoga/algorithm/PixelGrid.h' file not found
  11 | #include <yoga/numeric/Comparison.h>
  12 |
  13 | namespace facebook::yoga {

Steps to reproduce

https://github.com/evelant/expo50upgrade/

git clone https://github.com/evelant/expo50upgrade/

cd expo50upgrade

pnpm install

pnpm expo start

eas build -p ios --profile development --local

Affected Platforms

Build - MacOS

Output of npx react-native info

System:
  OS: macOS 14.2
  CPU: (10) arm64 Apple M1 Pro
  Memory: 348.45 MB / 16.00 GB
  Shell:
    version: 0.85.0
    path: /etc/profiles/per-user/imagio/bin/nu
Binaries:
  Node:
    version: 20.8.0
    path: /etc/profiles/per-user/imagio/bin/node
  Yarn:
    version: 1.22.21
    path: /etc/profiles/per-user/imagio/bin/yarn
  npm:
    version: 10.1.0
    path: /etc/profiles/per-user/imagio/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.12.1
    path: /etc/profiles/per-user/imagio/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.2
      - iOS 17.2
      - macOS 14.2
      - tvOS 17.2
      - watchOS 10.2
  Android SDK:
    API Levels:
      - "33"
    Build Tools:
      - 33.0.0
    Android NDK: Not Found
IDEs:
  Android Studio: Not Found
  Xcode:
    version: 15.1/15C65
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.8.1
    path: /etc/profiles/per-user/imagio/bin/javac
  Ruby:
    version: 3.1.4
    path: /etc/profiles/per-user/imagio/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.73.0
    wanted: 0.73.0
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Stacktrace or Logs

[RUN_FASTLANE] › Compiling .pnpm Pods/Yoga » PixelGrid.cpp
[RUN_FASTLANE]
❌  (node_modules/.pnpm/react-native@0.73.0_@babel+core@7.23.6_@babel+preset-env@7.23.6_react@18.2.0/node_modules/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp:10:10)

   8 | #include <yoga/Yoga.h>
   9 |
> 10 | #include <yoga/algorithm/PixelGrid.h>
     |          ^ 'yoga/algorithm/PixelGrid.h' file not found
  11 | #include <yoga/numeric/Comparison.h>
  12 |
  13 | namespace facebook::yoga {

Reproducer

https://github.com/evelant/expo50upgrade/

Screenshots and Videos

N/A

@evelant evelant added Needs: Triage 🔍 Type: Upgrade Issue Issues reported from upgrade issue form labels Dec 14, 2023
@github-actions github-actions bot added the Platform: iOS iOS applications. label Dec 14, 2023
@iron-leo
Copy link

iron-leo commented Dec 14, 2023

I can't run successfully iOS build even with default Readme.md

  1. Install npm deps, gems, cocoapods.
  2. npm start ( Metro bundler )
  • Xcode 15.1, Sonoma 14.2
  1. npm run ios ( in second terminal window ) failed:

❯ npm run ios

RnTemplate@0.0.1 ios
react-native run-ios

info A dev server is already running for this project on port 8081.
info Found Xcode workspace "RnTemplate.xcworkspace"
info Found booted iPhone SE (3rd generation)
info Building (using "xcodebuild -workspace RnTemplate.xcworkspace -configuration Debug -scheme RnTemplate -destination id=C26067CA-B437-43C3-BA26-072C31EA0211")
▸ Running script '[CP] Copy XCFrameworks'
▸ Running script '[CP] Copy XCFrameworks'
▸ Running script '[CP] Copy XCFrameworks'
Run script build phase '[CP-User] [Hermes] Replace Hermes for the right configuration, if needed' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'hermes-engine' from project 'Pods')
▸ Running script '[CP-User] [Hermes] Replace Hermes for the right configuration, if needed'
▸ Running script '[CP] Copy XCFrameworks'
▸ Processing ResourceBundle-RCTI18nStrings-React-Core-Info.plist
▸ Running script '[CP-User] Generate Specs'
Run script build phase 'Bundle React Native code and images' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'RnTemplate' from project 'RnTemplate')

info 💡 Tip: Make sure that you have set up your development environment correctly, by running npx react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctor

error Failed to build iOS project. "xcodebuild" exited with error code '65'. To debug build logs further, consider building your app with Xcode.app, by opening 'RnTemplate.xcworkspace'.

@evelant
Copy link
Author

evelant commented Dec 14, 2023

@iron-leo I think that's a totally separate issue. Did you run react-native start before trying to build? metro no longer gets started automatically and IIRC that's the (not super helpful) error message it gives.

@kelset
Copy link
Contributor

kelset commented Dec 15, 2023

cc @cipolleschi

@cipolleschi
Copy link
Contributor

cipolleschi commented Dec 15, 2023

Hi @evelant thanks for the report.
There are at least two things that concern me:

  1. pnpm is not officially supported yet, we know that there are issues with that setup
  2. you are using expo
  3. Dynamic frameworks jobs passed on 0.73. So we are confident that static frameworks will works as well, because dyn frameworks have stricter requirements.
npx react-native@latest init StaticFrameworks --version latest --skip-install
cd StaticFrameworks
yarn install
cd ios
bundle install
USE_FRAMEWORKS=static NO_FLIPPER=1 bundle exec pod install
open StaticFrameworks.xcworkspace

and then +B, it works properly.

@birdofpreyru
Copy link
Contributor

@cipolleschi I think I bumped into the same issue react-native-webview/react-native-webview#3263 when building a project using react-native-webview with iOS / RN v0.73 / New Arch. Using Yarn, no expo.

@birdofpreyru
Copy link
Contributor

@evelant
Copy link
Author

evelant commented Dec 15, 2023

@cipolleschi This same issue has happened in previous releases. I had a PR for 0.72 that fixed it then. It seems like it just keeps creeping back in due to the way cocoapods handles symlinks when given a relative path in a podfile. See the older PR here #38158 and an explanation of the problem here #38140 (comment)

It would be great if pnpm could be added to the automated tests. It should require zero extra setup. Just substitute yarn or npm for pnpm, that's all.

@cipolleschi
Copy link
Contributor

yeah, i remember. But we had to revert those changes because they were failing on other test cases, now I don't remember the specifics, unfortunately, as some weeks has passed. :(

@heath-clink
Copy link

heath-clink commented Dec 15, 2023

I've observed something very similar with lottie-react-native. I made a simple repro: https://github.com/heath-clink/rn73-lottie-repro

See also: lottie-react-native/lottie-react-native#1138

@NickGerleman
Copy link
Contributor

NickGerleman commented Dec 16, 2023

For folks maintaining webview and lottie Fabric native components, does the problem go away if you add install_modules_dependenciesas referenved here make the issue go away? https://reactnative.dev/docs/the-new-architecture/pillars-fabric-components#ios-create-the-podspec-file

@NickGerleman
Copy link
Contributor

33ebb5d made changes to Yoga header structure with new architecture. There is a lot of manual finagling of header search paths happening right now.

@cipolleschi
Copy link
Contributor

I think there are different problems:

  • The problem highlighted by @evelant is due to pnpm and the relative patch that are specified in the podspecs, which stops working correctly with some pnpm setups
  • The problem highlighted by react-native-webview and lottie should be solved using install_modules_dependenciesas as @NickGerleman suggested. I'll fix those on Monday as I fixed several libraries already. Notice that they will require a new release of the two libs, anyway.

@cipolleschi
Copy link
Contributor

For webview, there is already a PR pending with the fixes: https://github.com/react-native-webview/react-native-webview/pull/3231/files

@cipolleschi
Copy link
Contributor

I created the PR for Lottie as well: lottie-react-native/lottie-react-native#1139

@Johan-dutoit
Copy link
Contributor

Johan-dutoit commented Dec 31, 2023

I too am experiencing this with nx as my monorepo setup, with yarn.
Started as soon as I added use_frameworks! :linkage => :static to my podfile (required by firebase).

Using the bare RN flow and latest version (0.73.1)

image

@cipolleschi
Copy link
Contributor

Monorepo setup are not officially supported, unfortunately.
We haven't figured out a proper way to handle them. In monorepo setup the problems are likely to be the various relative path we have in the podspecs. In the Yoga.podspec we have a few of them.

Monorepo setups put those files in different paths w.r.t. the standard setup, and the podspecs layout is not handling that case.

@joaoveronezi
Copy link

joaoveronezi commented Jan 15, 2024

I'm creating a "SDK", using cocoapods lib create.

I'm having this issue:

Screen Shot 2024-01-15 at 13 10 55

Here is my podfile:

`platform :ios, '13.4'

source 'https://github.com/jveronezi/sdk-specs.git'
source 'https://github.com/CocoaPods/Specs.git'

use_frameworks!
target 'TestingSDK' do
pod 'SdkPod', '0.1.3'
end
`


This is my Yoga.podspec.json
{ "name": "Yoga", "version": "1.14.1", "license": { "type": "MIT" }, "homepage": "https://yogalayout.com", "documentation_url": "https://yogalayout.com/docs/", "summary": "Yoga is a cross-platform layout engine which implements Flexbox.", "description": "Yoga is a cross-platform layout engine enabling maximum collaboration within your team by implementing an API many designers are familiar with, and opening it up to developers across different platforms.", "authors": "Facebook", "source": { "git": "https://github.com/facebook/react-native.git", "tag": "v0.73.1" }, "module_name": "Yoga", "header_dir": "Yoga", "requires_arc": false, "pod_target_xcconfig": { "DEFINES_MODULE": "YES" }, "compiler_flags": [ "-fno-omit-frame-pointer", "-fexceptions", "-Wall", "-Werror", "-std=c++17", "-fPIC" ], "platforms": { "ios": "13.4" }, "source_files": "packages/react-native/ReactCommon/yoga/yoga/**/*.{cpp,h}", "header_mappings_dir": "yoga", "public_header_files": "ReactCommon/yoga/yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h", "private_header_files": [ "packages/react-native/ReactCommon/yoga/yoga/Yoga-internal.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/Align.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/Baseline.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/BoundAxis.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/Cache.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexDirection.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/FlexLine.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.h", "packages/react-native/ReactCommon/yoga/yoga/algorithm/ResolveValue.h", "packages/react-native/ReactCommon/yoga/yoga/bits/BitCast.h", "packages/react-native/ReactCommon/yoga/yoga/bits/NumericBitfield.h", "packages/react-native/ReactCommon/yoga/yoga/config/Config.h", "packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.h", "packages/react-native/ReactCommon/yoga/yoga/debug/Log.h", "packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Align.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Dimension.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Direction.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Display.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Edge.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Errata.h", "packages/react-native/ReactCommon/yoga/yoga/enums/ExperimentalFeature.h", "packages/react-native/ReactCommon/yoga/yoga/enums/FlexDirection.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Gutter.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Justify.h", "packages/react-native/ReactCommon/yoga/yoga/enums/LogLevel.h", "packages/react-native/ReactCommon/yoga/yoga/enums/MeasureMode.h", "packages/react-native/ReactCommon/yoga/yoga/enums/NodeType.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Overflow.h", "packages/react-native/ReactCommon/yoga/yoga/enums/PositionType.h", "packages/react-native/ReactCommon/yoga/yoga/enums/PrintOptions.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Unit.h", "packages/react-native/ReactCommon/yoga/yoga/enums/Wrap.h", "packages/react-native/ReactCommon/yoga/yoga/enums/YogaEnums.h", "packages/react-native/ReactCommon/yoga/yoga/event/event.h", "packages/react-native/ReactCommon/yoga/yoga/node/CachedMeasurement.h", "packages/react-native/ReactCommon/yoga/yoga/node/LayoutResults.h", "packages/react-native/ReactCommon/yoga/yoga/node/Node.h", "packages/react-native/ReactCommon/yoga/yoga/numeric/Comparison.h", "packages/react-native/ReactCommon/yoga/yoga/numeric/FloatOptional.h", "packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h", "packages/react-native/ReactCommon/yoga/yoga/style/Style.h" ], "preserve_paths": ["ReactCommon/yoga/yoga/**/*.h"] }


Xcode Yoga target build phases
Screen Shot 2024-01-15 at 13 12 31

@cipolleschi
Copy link
Contributor

You should not use cocoapods lib create to create a library for react-native.
Cocoapods is the tool we use but the base use case is to create a lib for a standard iOS project.

For React Native, there is much more running under the hoods. The tool you should use to create a library compatible with React Native is Bob that will properly setup the podspec and the whole folder structure for you.

It will also create an Example folder with a React Native sample app that you can use to test your library.

@Nasseratic
Copy link

Monorepo setup are not officially supported, unfortunately.
We haven't figured out a proper way to handle them. In monorepo setup the problems are likely to be the various relative path we have in the podspecs. In the Yoga.podspec we have a few of them.
Monorepo setups put those files in different paths w.r.t. the standard setup, and the podspecs layout is not handling that case.

Any way we can get around this? why use_frameworks! :linkage => :static is causing this to monorepo setup? as I understand from the thread it works without it?

@cipolleschi
Copy link
Contributor

The problem is that use_frameworks changes how the files are arranged in the disk after pod install run.
Frameworks must follow a very specific structure:

FrameworkName
'-> Headers
    '-> headerA.h
    '-> headerB.h
'-> ImplementationA.m
'-> PrivateHeaderC.h

While static libraries doesn't.

On top of that, Monorepos usually moves the whole frameworks in a different location and uses symlinks to connect the expected position on disk to the monorepo location.

Those links get broken in our current setup. The specific details of what get broken depend on the monorepo that is used, but what I saw happening is that, with use frameworks, not all the symlink are set up correctly and that broke it.

@Nantris
Copy link

Nantris commented Jan 26, 2024

Same issue here.

I see it's mentioned that monorepos aren't officially supported, but also I saw this comment which says symlinks are stable in 0.73. What other challenges remain for monorepos? I sort of expected the support for symlinks to remedy this problem.

@enchorb
Copy link

enchorb commented Jan 26, 2024

Getting this issue in an Nx monorepo

Related: nrwl/nx#20115

@cipolleschi
Copy link
Contributor

@slapbox symlink is stable for Metro, but not for the whole framework. My colleague that worked on simlinks for metro is now tackling monorepo scenarios, so, hopeful, we are going to have them working soon.

@birdofpreyru
Copy link
Contributor

birdofpreyru commented Jan 30, 2024

@cipolleschi my app fails to be archived for macOS (Catalyst) release with the seemingly similar error:
image

at the same time it builds and works fine if I just build it in release or debug mode to run locally on macOS, and it also works fine for iOS (both local builds & archiving for Apple.Store release). I am a bit lost in this thread, thus maybe you can hint me please, how to fix / temporary workaround it? I am not using expo; I am using npm; and I have use_frameworks! :linkage => :static in my podspec.

P.S.: I mean, I figured out I can just ad-hoc edit path includes in the pod source code, to make the build pass... which I guess works as a workaround, but might there be an easier method?

@joaoveronezi
Copy link

I solved my issue by going into the podspec.json and fixing the paths

@Nantris
Copy link

Nantris commented Jun 11, 2024

Unfortunately the changes mentioned by @cipolleschi on April 3rd (767330f) are already integrated in the version we're using, but the problem persists:

/Users/expo/workingdir/build/node_modules/react-native/React/Base/RCTConvert.h:19:9: fatal error: 'yoga/Yoga.h' file not found
#import <yoga/Yoga.h>
        ^~~~~~~~~~~~~
/Users/expo/workingdir/build/node_modules/react-native/React/Base/RCTConvert.h:19:9: note: did not find header 'Yoga.h' in framework 'yoga' (loaded from '/Users/expo/workingdir/build/packages/mobile/ios/build/Build/Products/Debug-iphonesimulator/Yoga')
1 error generated.

@Nantris
Copy link

Nantris commented Jun 14, 2024

@cipolleschi can you offer any advice or insights? Or is there anything else I can do to help get this resolved? We're on 0.74.2 and this is essentially a showstopper since we can't build.

@Nantris
Copy link

Nantris commented Jun 15, 2024

Can anyone offer any advice on this? Even @cnorman1977's approach which everyone seems to agree worked for 0.73.x does not resolve this in 0.74.2 - and my understanding is that it shouldn't even be necessary since #42847 was merged.

@birdofpreyru
Copy link
Contributor

Ogh… the patch solved the issue for me, and seemingly for everyone else but you; hence it reads like you do something wrong in your code.

@Nantris
Copy link

Nantris commented Jun 15, 2024

Thanks for your reply @birdofpreyru. Unfortunately we use Expo in a managed workflow so there's not much in terms of what I personally could be doing wrong, but perhaps something upstream from us.

Is there anything in your mind that Expo might need to do to resolve this? There's an unresolved issue there with several people struggling with it: expo/expo#25942

@birdofpreyru
Copy link
Contributor

I never used Expo, and I am very disappointed it is the officially recommended way to use RN since 0.74 🤷‍♂️ I’m glad to learn it doesn’t work smooth, unlike the barebone RN 😁

@Nantris
Copy link

Nantris commented Jun 15, 2024

Not a good look to gloat while someone's facing a problem.

@Nantris
Copy link

Nantris commented Jun 16, 2024

I tried removing the patch from #42847 and doing so restores the originally reported issue:

[RUN_FASTLANE] › Compiling react-native Pods/Yoga » event.cpp
[RUN_FASTLANE] 
❌  (../../node_modules/react-native/ReactCommon/yoga/yoga/YGValue.cpp:9:10)

   7 | 
   8 | #include <yoga/YGValue.h>
>  9 | #include <yoga/numeric/Comparison.h>
     |          ^ 'yoga/numeric/Comparison.h' file not found
  10 | 
  11 | using namespace facebook;
  12 | using namespace facebook::yoga;

[RUN_FASTLANE] › Compiling react-native Pods/Yoga » YGPixelGrid.cpp
[RUN_FASTLANE] 
❌  (../../node_modules/react-native/ReactCommon/yoga/yoga/YGPixelGrid.cpp:10:10)

   8 | #include <yoga/Yoga.h>
   9 | 
> 10 | #include <yoga/algorithm/PixelGrid.h>
     |          ^ 'yoga/algorithm/PixelGrid.h' file not found
  11 | 
  12 | using namespace facebook;
  13 | using namespace facebook::yoga;

But are we sure it really resolves 'yoga/Yoga.h' file not found @cnorman1977?

There are quite a few thumbs up on the comment here from long after the patch was theoretically applied, as well as #44340 which was closed as a duplicate - although I'm not sure that it really is.

It seems like for some people, the patch just got them one step closer to building, but exposed a new issue which is not addressed?

@Nantris
Copy link

Nantris commented Jun 20, 2024

Friendly bump. I do not believe this issue has truly been resolved for the reasons stated in the comment immediately prior.

Right now we can hang on on 0.72.x, but eventually this will leave us dead in the water.

@caustin24345
Copy link

caustin24345 commented Jun 24, 2024

@Nantris - I am facing the same issue. I am upgrading a managed project from Expo 49 (RN 0.72.x) to Expo 51 (RN 0.74.2). The patch was able to clear some errors related to header path mappings to Yoga from other RN podspecs, and progress the build further. However, I also believe there are additional errors to do with locating the Yoga files during the linking phase of the iOS build.

It is not immediately clear to me at the moment what the issue is - but it is clear that the patch seems to fix header path mappings from packages inside the projects node_modules directory. The new error that I am seeing indicates that it is not able to find the Yoga file from the Build/Products directory as you are seeing in your above comment here.

VSCode throws this error during linking:

Screenshot 2024-06-24 at 4 01 18 PM

While Xcode throws this error for the same build:

image

I will be actively working on this for the next few weeks, and will keep you updated with any new discoveries.

@cipolleschi
Copy link
Contributor

@Nantris @caustin24345 If you are using Expo, I strongly suggest to open an issue in their repo. Expo performs some configuration changes in the app that they support.
If a new app without Expo is able to build and archive with no issue, it means that Expo is updating some settings that are breaking the build.

@caustin24345
Copy link

Thanks @cipolleschi - I'm going to create a minimal reproducible example to find out exactly where this issue is coming from. My understanding is that Expo is now working directly with the RN team for their releases to ensure compatibility between RN versions and Expo SDK's. I will confirm that Expo 51 works out of the box with RN 0.74.

I'm using pnpm as my package manager and also understand that it is not fully supported by react-native since it stores its packages in a separate location to alternatives like yarn and npm. I found a patch for Cocoapods which addresses this issue for RN > 0.73 but I'm aware that there could still be additional issues around this.

Since other people might run into this issue using any combination of RN with Expo + pnpm, npm, yarn etc - and since the discussion is already started about this issue on this thread, I am inclined to post my findings here (for the next guy). However, I will also be active on Expo's repo for any findings directly related to that.

@Nantris
Copy link

Nantris commented Jun 25, 2024

@caustin24345 I had thought there was already an issue for this, but I couldn't find it, so perhaps it was only a related issue. Please do share here when you create an issue on the Expo tracker and I'll be sure to join you there.

Fwiw we're using Yarn and our error is identical to yours, so I don't think it's pnpm that's causing any problem for you. I tried Yarn 1.21 and Yarn 3.x and the error is identical with each.

@cipolleschi
Copy link
Contributor

@caustin24345 thanks for opening the issue on Expo.

My understanding is that Expo is now working directly with the RN team for their releases to ensure compatibility between RN versions and Expo SDK's. I will confirm that Expo 51 works out of the box with RN 0.74.

Yes, that's true. We control the React Native core part and we ensure that everything works without Expo.
Expo, on the other side, takes React Native Core and customize it to let you use the Expo libraries, EAS and their APIs.
That means that, sometimes, they have to tinker with the configuration of some modules.
We collaborate in a sense that we want React Native to be successful and Expo is one of the drivers of success for React Native. We constantly talk about our needs and their needs and we look for solutions that fit both.

Let us know how it goes.
If you are able to replicate the problem using this template, I'd be more than happy to look into that.

@caustin24345
Copy link

Thank you for the info @cipolleschi, it is much appreciated.

To update you - I created a new Expo 51, RN 0.74 project using pnpm as the dependency manager and was able to build and run the project almost immediately. I slowly transferred packages and build configs across from my existing project to see what was causing the build issue that we have discussed. I was not able to reproduce it after replicating the package.json, and app.json - however, I was able to replicate it after moving to a monorepo structure and using nx to manage dependency caching. My hunch is that there is some confusion from the monorepo project as to which packages to reference when linking iOS frameworks i.e the packages in the node_modules directory at the project level, or the packages in the nx cached node_modules/.pnpm directory at the monorepo root.

With that being said, it is clear to me that this is NOT a react native, Expo or pnpm specific build issue and very likely related to caching and project infrastructure. I'm happy to move this conversation elsewhere now that I understand that it is not related to the react native package itself. I am however wondering if you are using similar tools or structure in your application @Nantris?

@evelant
Copy link
Author

evelant commented Jun 28, 2024

@caustin24345 I don't use pnpm anymore but when I did I ran into issues like this frequently (which is why I opened it originally). They generally fell within a couple categories of problems:

  1. Part of the react-native build (usually a 3rd party library with native code) uses a hard coded path instead of using require.resolve( to find a path. Usually a relative path like ../../node_modules/something/or/other so it fails if dependencies are hoisted to root of a monorepo
  2. React-native or another library has a "phantom dependency". That is it has a bug where it depends upon a package without declaring it as a dep or peer. Pnpm does the correct thing and doesn't make undeclared dependencies available so the dep isn't available and the build fails. It only happens to work on npm/yarn because they use a flat node_modules that allows you to resolve packages you don't actually declare a dependency on, you just get lucky that some transitive dependency installed it.
  3. One or another tool doesn't play well with symlinks, usually metro or rubygems/cocoapods. IIRC symlinks like pnpm uses can cause cocoapods to copy headers to the wrong destination folder. I think I worked around that a few times by patching podfiles to resolve absolute paths to header dirs instead of using relative paths that broke with symlinks. If you look through the ios build outputs for headers you'll probably see them nested in really deep incorrect paths because cocoapods doesn't do well with symlinks.
  4. Related to 3, sometimes xcode's behavior changes between releases frustratingly breaking workarounds for 3

I hope that summary is useful! Like I said however, I don't use pnpm anymore, I've been using bun without problems because it replicates the (bug prone and IMO incorrect) behavior of npm/yarn.

Monorepo setup are not officially supported, unfortunately. We haven't figured out a proper way to handle them. In monorepo setup the problems are likely to be the various relative path we have in the podspecs. In the Yoga.podspec we have a few of them.

Monorepo setups put those files in different paths w.r.t. the standard setup, and the podspecs layout is not handling that case.

@cipolleschi I know it's difficult due to JS tooling being the wild west but isn't it a little silly that react-native itself is a monorepo yet monorepo setups are not "officially" supported? I wonder if we can figure out what the real root cause of these repeated issues is and get it fixed. It seems to me it's primarily bad symlink behavior in cocoapods/rubygems. Might it be possible to get that fixed upstream so this whole class of problems could go away?

@cipolleschi
Copy link
Contributor

@caustin24345 and @evelant, thank you so much for your investigations and for sharing your findings. Those are extremely valuable and we really appreciate them.

I know it's difficult due to JS tooling being the wild west but isn't it a little silly that react-native itself is a monorepo yet monorepo setups are not "officially" supported? I wonder if we can figure out what the real root cause of these repeated issues is and get it fixed. It seems to me it's primarily bad symlink behavior in cocoapods/rubygems. Might it be possible to get that fixed upstream so this whole class of problems could go away?

I completely agree with you and I share the same frustrations and perplexities.
It is completely doable to upstream such changes if we find the right root cause.

@robhogan was working on monorepo support some month ago, but now our internal priorities changed a bit and I'm pretty sure we won't have capacity to work on these topics in the very short term.
If there is a volunteer in the community that want to invest time in this, we are more than happy to support and make sure those changes land, but we don't have resources to work on this now. I'm hopeful that in six months or so, the situation might change a little.

@Nantris
Copy link

Nantris commented Jun 28, 2024

I am however wondering if you are using similar tools or structure in your application @Nantris?

Yes we use an nx monorepo but I do not believe caching plays any role in this issue. I don't think it's correct to say this isn't a React Native or Expo issue, because in my view it has to be one of those, but for the fact React Native inexplicably fails to officially support monorepos in 2024.

I really wish we could get proper support for monorepo. When I started with React Native in 2018, it seemed right around the corner. Literally tens of thousands of developer hours end up wasted on this sort of stuff every year - including their own developers' time.

It worked with just a slightly older version of React Native and Expo. To me, that screams that it's a React Native or Expo problem.


One or another tool doesn't play well with symlinks, usually metro or rubygems/cocoapods. IIRC symlinks like pnpm uses can cause cocoapods to copy headers to the wrong destination folder. I think I worked around that a few times by patching podfiles to resolve absolute paths to header dirs instead of using relative paths that broke with symlinks.

Indeed, in React Native 0.72 making these path changes as a patch resolved all of our issues, but now with nothing having changed but React Native and Expo, it fails to work either with or without the patch. So it's got to be React Native, no?

-    s.header_mappings_dir     = './'
+    s.header_mappings_dir     = File.absolute_path('./')

I feel very confident this is not an nx caching issue, but if you want to investigate that, according to ChatGPT, this config in your nx.json should be a good template to fully disable caching. I haven't verified it myself, but if you want to give it a try, ensure it disables caching, and try a build, that would be a valuable troubleshooting step to prove or disprove your theory.

  1. Update your nx.json to the below contents (update for your project - see docs: https://nx.dev/concepts/how-caching-works)
  2. Run pnpm nx reset to clear existing cache
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
      "options": {
        "cacheableOperations": []
      }
    }
  },
  "targetDefaults": {
    "*": {
      "inputs": ["default"],
      "outputs": ["{workspaceRoot}/dist/{projectName}"]
    }
  }
}

@dieguezz
Copy link
Contributor

dieguezz commented Sep 3, 2024

Using nrwl/nx and 767330f solved the problem for us

@Nantris
Copy link

Nantris commented Sep 4, 2024

Thanks for sharing @dieguezz! Are you saying you used patch-package to backport that change to 0.73.x?

@dieguezz
Copy link
Contributor

dieguezz commented Sep 5, 2024

@Nantris i am sorry, i was wrong. That solved the yoga issue, but i started having similar errors for other items inside react-native module. I think they changed something in the way routes are resolved at build time, which conflicts with the way nx or any other monorepos manage dependencies.

Maybe there is a better way to do this, but for the moment what worked for me (apart of applying the patch) was to manually map modules in podfile like:

  post_install do |installer|
    react_native_post_install(installer)
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.4'
        config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited) "
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon "
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios/ "
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/react/nativemodule/core/ "
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/react/renderer"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga "
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/config"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/algorithm"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/node"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/algorithm"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/bits"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/config"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/debug"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/enums"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/event"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/numeric"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga/style"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/ReactCommon/yoga/yoga"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/React"
        config.build_settings["HEADER_SEARCH_PATHS"] << "${PODS_ROOT}/../../node_modules/react-native/React/Base"
      end
      if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
        target.build_configurations.each do |config|
            config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
        end
      end
    end
    ```

@Nantris
Copy link

Nantris commented Sep 5, 2024

Thank you so much for sharing @dieguezz! This issue has been plaguing us and I'm excited to try your approach.

Would you mind sharing your React Native version? I noticed sometimes even patch-level version differences affect these workarounds.

@dieguezz
Copy link
Contributor

dieguezz commented Sep 6, 2024

@Nantris i was using 0.73.6, but this also works in 0.74.xx. In the end i freezed 0.72.x because i was having problems with other dependencies we use (like react-native-contacts, which is not prepared for the new platform), but the yoga and all other react-native module import problems were solved.

@dieguezz
Copy link
Contributor

dieguezz commented Oct 2, 2024

So finally i needed to upgrade react native so i had to find a different workaround. What i did is remove use_frameworks! (which removed the file not found errors) except for the case contemplated in

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

And then add :modular_headers for packages that need it like:

  pod 'GoogleUtilities', :modular_headers => true
  pod 'FirebaseCore', :modular_headers => true
  pod 'nanopb', :modular_headers => true
  pod 'FirebaseInstallations', :modular_headers => true
  pod 'GoogleDataTransport', :modular_headers => true
  pod 'FirebaseCoreExtension', :modular_headers => true

@Nantris let me know if this works for you

@Nantris
Copy link

Nantris commented Oct 2, 2024

Thanks very much for sharing @dieguezz!

Invertase super-strongly recommends you do not rely on modular_header - but I wonder, are you using use_frameworks AND modular_headers? I wonder if that might be an acceptable solution @mikehardy.

I think there was another approach in one of these many threads that I haven't had time to try but now I can't even find it :(

I'll certainly report back with my findings as soon as I get a chance to try this. There always seems to be some other fire to fight first. Thank you again!

@dieguezz
Copy link
Contributor

dieguezz commented Oct 2, 2024

@Nantris I am just using use_frameworks for the case i pasted, when linkage != nil. In my case it will be nil so yeah, i just removed them completely. My podfile looks like the upgrade helper one but with a pair of things we are using (widgets and quantummetric conf), so the only substantial difference is what i posted in my last comment.

BTW, why should i not rely on modular_header?

@Nantris
Copy link

Nantris commented Oct 2, 2024

@dieguezz I think you're probably in the clear with this approach? I'm the furthest thing from an expert though.

I think modular_headers is okay as long as you're using it in addition to use_frameworks rather than instead of use_frameworks but I'm not sure how brittle this approach might be.

I'm certainly looking forward to giving it a try!

@bengsfort
Copy link

We started having this exact same issue after adding firebase to a project, and the only thing that fixed it for us was @dieguezz 's modular headers fix for the affected packages. Thank you so much!

One thing that may or may not contribute to any ongoing investigation into the issue though; in our case it was odd because the mentioned build errors only happened on some of our devs machines, while for others everything was totally fine. After merging the podfile changes though our project is working for everybody on the team, so not really sure what happened there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Triage 🔍 Platform: iOS iOS applications. Type: Upgrade Issue Issues reported from upgrade issue form
Projects
None yet
Development

No branches or pull requests