Skip to content

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

Closed

Description

@evelant

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

Activity

  1. iron-leo commented on Dec 14, 2023

    @iron-leo

    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'.

  2. evelant commented on Dec 14, 2023

    @evelant
    Author

    @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.

  3. kelset commented on Dec 15, 2023

    @kelset
    Contributor
  4. cipolleschi commented on Dec 15, 2023

    @cipolleschi
    Contributor

    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.

  5. birdofpreyru commented on Dec 15, 2023

    @birdofpreyru
    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.

  6. birdofpreyru commented on Dec 15, 2023

    @birdofpreyru
    Contributor
  7. evelant commented on Dec 15, 2023

    @evelant
    Author

    @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.

  8. cipolleschi commented on Dec 15, 2023

    @cipolleschi
    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. :(

  9. heath-clink commented on Dec 15, 2023

    @heath-clink

    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

  10. NickGerleman commented on Dec 16, 2023

    @NickGerleman
    Contributor

    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

  11. NickGerleman commented on Dec 16, 2023

    @NickGerleman
    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.

  12. cipolleschi commented on Dec 16, 2023

    @cipolleschi
    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.
  13. 43 remaining items

  14. cipolleschi commented on Jun 27, 2024

    @cipolleschi
    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.

  15. caustin24345 commented on Jun 28, 2024

    @caustin24345

    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?

  16. evelant commented on Jun 28, 2024

    @evelant
    Author

    @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?

  17. cipolleschi commented on Jun 28, 2024

    @cipolleschi
    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.

  18. Nantris commented on Jun 28, 2024

    @Nantris

    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}"]
        }
      }
    }
    
  19. dieguezz commented on Sep 3, 2024

    @dieguezz
    Contributor

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

  20. Nantris commented on Sep 4, 2024

    @Nantris

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

  21. dieguezz commented on Sep 5, 2024

    @dieguezz
    Contributor

    @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
        ```
    
  22. Nantris commented on Sep 5, 2024

    @Nantris

    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.

  23. dieguezz commented on Sep 6, 2024

    @dieguezz
    Contributor

    @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.

  24. dieguezz commented on Oct 2, 2024

    @dieguezz
    Contributor

    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

  25. Nantris commented on Oct 2, 2024

    @Nantris

    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!

  26. dieguezz commented on Oct 2, 2024

    @dieguezz
    Contributor

    @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?

  27. Nantris commented on Oct 2, 2024

    @Nantris

    @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!

  28. bengsfort commented on Oct 14, 2024

    @bengsfort

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions