react-native: Error 'ReactCommon/TurboModuleBinding.h' file not found on react native 0.72.0 on iOS

Description

After upgrading my react native to version 0.72.0, I can’t run my react native app on iOS properly as it logs an error saying: “Error ‘ReactCommon/TurboModuleBinding.h’ file” as show in the picture below.

I tried executing with the suggestions described here but unfortunately the error is still here.

Here is my Podfile:

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '13.0'

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def fix_library_search_paths(installer)
  def fix_config(config)
    lib_search_paths = config.build_settings["LIBRARY_SEARCH_PATHS"]
    if lib_search_paths
      if lib_search_paths.include?("$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)") || lib_search_paths.include?("\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"")
        # $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) causes problem with Xcode 12.5 + arm64 (Apple M1)
        # since the libraries there are only built for x86_64 and i386.
        lib_search_paths.delete("$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)")
        lib_search_paths.delete("\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"")
        if !(lib_search_paths.include?("$(SDKROOT)/usr/lib/swift") || lib_search_paths.include?("\"$(SDKROOT)/usr/lib/swift\""))
          # however, $(SDKROOT)/usr/lib/swift is required, at least if user is not running CocoaPods 1.11
          lib_search_paths.insert(0, "$(SDKROOT)/usr/lib/swift")
        end
      end
    end
  end

  def __apply_Xcode_14_3_RC_post_install_workaround(installer)
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        current_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET']
        minimum_target = min_ios_version_supported
        if current_target.to_f < minimum_target.to_f
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = minimum_target
        end
      end
    end
  end

  projects = installer.aggregate_targets
    .map{ |t| t.user_project }
    .uniq{ |p| p.path }
    .push(installer.pods_project)

  projects.each do |project|
    project.build_configurations.each do |config|
      fix_config(config)
    end
    project.native_targets.each do |target|
      target.build_configurations.each do |config|
        fix_config(config)
      end
    end
    project.save()
  end
end

target 'Equitazone' do
  config = use_native_modules!

  use_frameworks! :linkage => :static
  $RNFirebaseAsStaticFramework = true

  use_react_native!(:path => config[:reactNativePath], :hermes_enabled => false)



  pod 'react-native-config/Extension', :path => '../node_modules/react-native-config'

  target 'EquitazoneTests' do
    inherit! :complete
    # Pods for testing
  end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  # use_flipper!
  post_install do |installer|
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
    installer.pods_project.build_configuration_list.build_configurations.each do |configuration|
      configuration.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
    end
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings["ONLY_ACTIVE_ARCH"] = "NO"
        config.build_settings['CODE_SIGN_IDENTITY'] = ''
      end
    end
    fix_library_search_paths(installer)
    __apply_Xcode_14_3_RC_post_install_workaround(installer)
  end
end

target 'Equitazone-tvOS' do
  # Pods for Equitazone-tvOS

  target 'Equitazone-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end

workspace 'Equitazone.xcworkspace'

React Native Version

0.72.0

Output of npx react-native info

System: OS: macOS 13.4 CPU: (8) arm64 Apple M1 Pro Memory: 89.31 MB / 16.00 GB Shell: version: “5.9” path: /bin/zsh Binaries: Node: version: 20.2.0 path: /usr/local/bin/node Yarn: Not Found npm: version: 9.6.6 path: /usr/local/bin/npm Watchman: Not Found Managers: CocoaPods: version: 1.12.1 path: /usr/local/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 22.4 - iOS 16.4 - macOS 13.3 - tvOS 16.4 - watchOS 9.4 Android SDK: API Levels: - “28” - “29” - “30” - “31” - “32” - “33” Build Tools: - 29.0.2 - 30.0.2 - 30.0.3 - 31.0.0 - 32.0.0 - 33.0.0 - 34.0.0 System Images: - android-28 | Google APIs ARM 64 v8a - android-28 | Google ARM64-V8a Play ARM 64 v8a - android-29 | Google APIs ARM 64 v8a - android-29 | Google Play ARM 64 v8a - android-30 | Google APIs ARM 64 v8a - android-31 | Google Play ARM 64 v8a - android-32 | Google APIs ARM 64 v8a - android-33 | Google APIs ARM 64 v8a - android-33 | Google Play ARM 64 v8a Android NDK: 22.1.7171670 IDEs: Android Studio: 2022.2 AI-222.4459.24.2221.10121639 Xcode: version: 14.3.1/14E300c path: /usr/bin/xcodebuild Languages: Java: version: 17.0.1 path: /usr/bin/javac Ruby: version: 3.2.2 path: /usr/local/opt/ruby/bin/ruby npmPackages: “@react-native-community/cli”: Not Found react: installed: 18.2.0 wanted: 18.2.0 react-native: installed: 0.72.0 wanted: ^0.72.0 react-native-macos: Not Found npmGlobalPackages: “react-native”: Not Found Android: hermesEnabled: true newArchEnabled: false iOS: hermesEnabled: false newArchEnabled: false

Steps to reproduce

  • npm i
  • arch -x86_64 pod install (or tried with pod install only)
  • press run from Xcode on emulator or real device

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

Screenshot 2023-06-25 at 23 33 47

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 1
  • Comments: 49 (15 by maintainers)

Most upvoted comments

Ok I found the problem, hopefully if someone ends up here this will provide some pointers:

the problem came from the RN post install not being run, this part:

  post_install do |installer|
    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end

I barely understand how RN works but it seems like config[:reactNativePath] not being run was causing the files not found problem

thanks @cipolleschi for your time, have a great day!

@cipolleschi I have applied the changes your recommended (except a few, I had to keep that end that is required by its above def, code wasn’t formatted well, keeping the Firebase pods because removing those trigger a lot of pod install errors) and I can confirm that right now the build process goes well beyond the phase it used to crash before.

Right now it’s crashing inside the Didomi native code (I will have to replace that with react-native-didomi). Probably it will crash in the StreamAMG native code too, that one will have to be replaced with rn-jwplayer.

Upgrading RN in my project from 0.69 to 0.72.x will be a huge effort. I will come back here immediately after I have a fully functional Podfile.

Big thank you for all your suggestions!

The reason why it is failing is probably because there is some library that is not configured properly. I’m working on that actively and already found a couple of libraries that were not set up correctly and submitted PRs for them.

The root cause of this problem is the same as #38283 so, please, keep an eye on that issue for a solution.

For the time being:

  • remove all the custom pod 'podname' dependencies from your podfile. For example, all the React-XXX pods are already installed by the use_react_native! function, you should not double define them.
  • remove all the other dependencies from there and use yarn add with auto-linking to add those dependencies. There is logic to configure those dependencies when autolinking run. By bypassing that mechanism, you are basically bypassing all our automations
  • You podfile should look like this. All the other bits of customisation you add is likely to introduce issues, as we test against that template.

Please, try to reproduce the issue on a clean app. If you can’t reproduce it, it is likely that your setup is not correct and it is not a React Native issue.

@assadminhas we are also facing the same issue. Not sure what’s going wrong. We are also not upgrading to the New Architecture, not using Flipper and it always gives the error for turbo module file not found. If anyone has worked out a solution for this, please let us know over here 😪

@cipolleschi thanks a lot for your empathy and willingness to help!

I could solve the issue by updating .podspec file of react-native-jsi-cpr : I had to remove s.dependency 'ReactCommon/turbomodule/core' and add s.dependency 'React' to make it work

With react-native-quick-crypto I found that we were launching one script which was needed in the past updating .podspec to replace s.dependency 'React' to 'React-core', so it ended up with two 'React-core' dependencies, which was the issue

Thanks a lot! Hope it might help somebody in future with similar issues to double check .podspec of libs they have such issue with 😃

Hum… your Podfile is definitely complicated and that would likely be the problem. As far as I can see, your app is not a pure React Native app, but you have a lot of Native code, right? I can see several pods that are not React Native libraries but general swift/iOS ones.

As a rule of thumb, if a library is distributed on npm, it should not appear in the Podfile, but you should install it with yarn add <name of the library>.

In this way, autolinking will take care of adding the library to your app and it will configure it properly.

Secondly, you are mixing static and dynamic frameworks with a cocoapods plugin. This is an unofficial configuration which is not a standard in iOS and we do not support it directly. I have evidence of people being successful with it, but it definitely make things more complicated.

Looking at your Podfile, section by section:

# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
  'require.resolve(
    "react-native/scripts/react_native_pods.rb",
    {paths: [process.argv[1]]},
  )', __dir__]).strip

platform :ios, min_ios_version_supported
prepare_react_native_project!

flipper_config = FlipperConfiguration.disabled
-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

install! 'cocoapods', :deterministic_uuids => false
use_frameworks! :linkage => :static
inhibit_all_warnings!

$RNFirebaseAnalyticsWithoutAdIdSupport = true

source 'https://cdn.cocoapods.org/'

you can remove this section because you are setting use_frameworks! :linkage => :static manually.

target 'WonderPushNotificationServiceExtension' do
  platform :ios, '12.0'

  pod 'WonderPushExtension', '~> 4.0'
end

# We need to switch StreamAMGSDK and its dependancy YouboraLib to a dynamic linking
# else we get duplicate symbols and can't compile the app
# however the React code requires / is set up with static linkage ^^ see use_frameworks
# therefore we are sorting the problem native pods and leaving them dynamic, rather than changing the entire project
$dynamic_library = ['StreamAMGSDK/PlayKit', 'YouboraLib']
pre_install do |installer|
  Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
  installer.pod_targets.each do |pod|
    bt = pod.send(:build_type)
    if $dynamic_library.include?(pod.name)
      puts "** #{pod.name} left as dynamic **"
    else
      puts "#{pod.name} static_library"
      def pod.build_type;
      Pod::BuildType.static_library
    end
  end
end
- end

This last end seems to be an extra end. Which statement is it closing? Probably it is a typo as the Podfile would not work otherwise. Also, Youbora does not specify anything related to frameworks. What happen if we remove the all patch from $dynamic_library to the second end?

target 'MYAPP' do
  config = use_native_modules!
 # Flags change depending on the env values.
  flags = get_default_flags()
  permissions_path = '../node_modules/react-native-permissions/ios'

  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => flags[:hermes_enabled],
    :fabric_enabled => flags[:fabric_enabled],
    :flipper_configuration => FlipperConfiguration.disabled,
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  pod 'SwiftLint'
  pod 'GoogleAds-IMA-iOS-SDK', '~> 3.18.1'
  pod 'StreamAMGSDK/PlayKit', '1.3.0'
  pod 'XCGLogger', :modular_headers => true
  pod 'ObjcExceptionBridging', :modular_headers => true
- pod 'react-native-google-cast/NoBluetooth', path: '../node_modules/react-native-google-cast/'
- pod 'google-cast-sdk-no-bluetooth'
  pod 'DailymotionPlayerSDK', '4.0.4'

- pod 'Didomi-XCFramework', '1.95.2'

-  pod 'Permission-AppTrackingTransparency', :path => "#{permissions_path}/AppTrackingTransparency"
- pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"

- pod 'Firebase', '~> 10.17.0', :modular_headers => true
- pod 'FirebaseCore', '~> 10.17.0', :modular_headers => true
- pod 'FirebaseCoreInternal', '~> 10.17.0', :modular_headers => true
- pod 'FirebaseCoreExtension', '~> 10.17.0', :modular_headers => true
- pod 'FirebaseInstallations', '~> 10.17.0', :modular_headers => true
- pod 'Firebase/Performance', '~> 10.17.0', :modular_headers => true
- pod 'Firebase/Crashlytics', '~> 10.17.0', :modular_headers => true
- pod 'Firebase/DynamicLinks', '~> 10.17.0', :modular_headers => true
- pod 'FirebaseABTesting', :modular_headers => true
- pod 'FirebaseRemoteConfig', :modular_headers => true
- pod 'GoogleDataTransport', :modular_headers => true
  pod 'nanopb', :modular_headers => true
- pod 'GoogleUtilities', :modular_headers => true

For react-native-google-cast/NoBluetooth, use the react-native-google-cast library (you are already picking it from node_modules, so just remove the line. For Didomi, use the react-native-package as described here For Permissions, install react-native-permissions from here

For all the Firebase packages, use the React Native Firebase implementation as described here. This should also install the GoogleDataTransport and the GoogleUtilities pods.


- def append_header_search_path(target, path)
-      target.build_configurations.each do |config|
-          # Note that there's a space character after `$(inherited)`.
-          config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited) "
-          config.build_settings["HEADER_SEARCH_PATHS"] << path
-      end
-  end


  post_install do |installer|
     react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
    
-    installer.pods_project.targets.each do |target|
-      target.build_configurations.each do |config|
-        config.build_settings["CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"] = true
-        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"
-        if ["React-cxxreact", "React-NativeModulesApple", "React-runtimescheduler", "React-utils", "StreamAMGSDK/PlayKit"].any? { |t| t == target.name }
-        end
-        config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
-      end
-    end
  end

end

Our cocoapods infra should take care of all these steps.

Now, after these changes, your project might be quite dirty.

  1. Navigate back to the root of your project and run the yarn add for all the libraries you were managing manually
  2. Let’s do a bit of cleanup by, navigating to the iOS folder and then:
bundle install
bundle exec pod deintegrate # this cleans up all the pods and remove all the dirt
bundle exec pod install

Let me know if this work. We have CI jobs that create React Native apps using Static Frameworks, so I am sure that they work.

Your setup is complex and does not follow all the suggested practices, so it will be hard to fix it, but we can make it work.

@assadminhas Do we have to use config[:reactNativePath]?? Is there something special happening there?

Or can I use a path string "../path/to/project"

I should have specified that the path to the project is not the normal path and would not be just one level up. How do I make sure config[:reactNativePath] has the correct path?

  • Moving “use_frameworks! :linkage => :static” outside of target

  • Remove all the custom pod ‘podname’ dependencies from your podfile. For example, all the React-XXX pods are already installed by the use_react_native! function, you should not double define them.

  • and add

    post_install do |installer|
    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
     react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false
    )
    __apply_Xcode_12_5_M1_post_install_workaround(installer)
    
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
      end
    end
  end

inside of target.

Basically “react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false )” adds needed turbo files. but It may cause other issue with Folly or reanimated libs, which can be fixed using patches.

Can someone please explain what the resolution of the issue was for fatal error: 'ReactCommon/TurboModuleBinding.h' file not found

I am still having the issue and tried RN versions 0.72.2 - 0.72.7

I tried to implement the post install process like this and the app built successfully with me also, I am using firebase libraries and I’m not using flipper:

Add this block above the target block:

config = use_native_modules!

post_install do |installer_representation|
    react_native_post_install(
    installer_representation,
    config[:reactNativePath],
    :mac_catalyst_enabled => false
  )
  __apply_Xcode_12_5_M1_post_install_workaround(installer_representation)
  installer_representation.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
        if target.name == 'image-slider'
           config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
        end
        config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'No'
        config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'No'
    end
    end
  end

Also I ran pod install like this: NO_FLIPPER=1 npx pod-install and I adjusted the react-native-config.js to be like this: dependencies: { …(process.env.NO_FLIPPER ? { ‘react-native-flipper’: { platforms: { ios: null } } } : {}), }

Actually, in your podfile, you used to have:

post_install do |installer|
  installer.pods_project.build_configurations.each do |config|
      config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
  end
end

with no call to the react_native_post_install! function.

This is not really a React Native (RN) specific thing, but it is how React Native is integrated with Cocoapods (CP) .

CP is mainly used to install dependencies: you specify the dependencies needed in your project and CP downloads and install them, creating a separate Pods project and a workspace for your code to work with the new Pods project.

Then, there could be the need to customize the Pods project and the workspace. CP offers pre_install and post_install hooks to do these customisations.

RN exposes 2 functions:

  1. use_react_native to streamline the dependencies that an app needs from React Native itself. In this way we can encapsulate the complexity of adding all the RN dependencies
  2. react_native_post_install which is a post_install hook that is used to finalize the project and workspace with all the required flags and configurations. This function needs an installer object, so it has to be called in the post_install CP’s hook.

Both functions must be called to have a properly initialized project.

I hope this helps to shed some light on how the framework works! 😄