invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.74k stars 2.22k forks source link

[🔥][🐛][IOS] StoreKit undefined symbols error after react-native-firebase 21+ upgrade #8078

Closed antFrancon closed 1 month ago

antFrancon commented 1 month ago

Issue

The iOS build is failing after upgrading to react-native-firebase 21+.

When running npx expo run:ios, the build process fails with the following error (using Expo bare workflow):

❌  Undefined symbols for architecture arm64
┌─ Symbol: _$s8StoreKit11TransactionV5OfferV11PaymentModeV9freeTrialAGvgZ
└─ Referenced from: _$sSo12FIRAnalyticsC17FirebaseAnalyticsE14logTransactionyy8StoreKit0E0VFZ in FirebaseAnalytics(Analytics+StoreKit.o)

❌  ld: symbol(s) not found for architecture arm64

❌  clang: error: linker command failed with exit code 1 (use -v to see invocation)
› 3 error(s), and 11 warning(s)

CommandError: Failed to build iOS project. "xcodebuild" exited with error code 65

The error suggests undefined StoreKit symbols are causing the build failure. I'm using RevenueCat for in-app purchases, which might be relevant to this StoreKit-related issue.

A similar issue has been reported on StackOverflow recently.


Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "my-app", "version": "0.0.1", "private": true, "scripts": { "start:android": "npx expo run:android", "start:ios": "npx expo run:ios", "postinstall": "patch-package" }, "dependencies": { "@formatjs/intl-datetimeformat": "^6.15.0", "@formatjs/intl-locale": "^4.1.0", "@gorhom/bottom-sheet": "^5.0.4", "@react-native-async-storage/async-storage": "^2.0.0", "@react-native-community/geolocation": "^3.4.0", "@react-native-community/netinfo": "^11.4.1", "@react-native-firebase/analytics": "^21.2.0", "@react-native-firebase/app": "^21.2.0", "@react-native-firebase/app-check": "^21.2.0", "@react-native-firebase/crashlytics": "^21.2.0", "@react-native-firebase/messaging": "^21.2.0", "@react-native-google-signin/google-signin": "^17.3.1", "@react-native-masked-view/masked-view": "^0.3.1", "@react-native-menu/menu": "^1.1.4", "@react-navigation/bottom-tabs": "^6.6.1", "@react-navigation/native": "^6.1.18", "@react-navigation/native-stack": "^6.11.0", "@sentry/react-native": "^6.1.0", "@shopify/flash-list": "^1.7.1", "@tanstack/react-query": "^5.59.15", "axios": "^1.7.7", "emoji-regex": "^10.4.0", "expo": "51.0.38", "expo-apple-authentication": "~6.4.2", "expo-blur": "~13.0.2", "expo-camera": "~15.0.16", "expo-image": "~1.13.0", "jwt-decode": "^4.0.0", "lottie-react-native": "^7.0.0", "luxon": "3.5.0", "node-polyglot": "^2.6.0", "react": "18.3.1", "react-native": "0.75.4", "react-native-adjust": "^5.0.2", "react-native-android-location-enabler": "^2.0.1", "react-native-blob-util": "^0.19.11", "react-native-bootsplash": "^6.2.2", "react-native-config": "^1.5.3", "react-native-date-picker": "^5.0.7", "react-native-device-info": "^13.1.0", "react-native-edge-to-edge": "^0.2.1", "react-native-fbsdk-next": "^13.1.3", "react-native-gesture-handler": "2.20.0", "react-native-get-random-values": "^1.11.0", "react-native-haptic-feedback": "^2.3.3", "react-native-image-crop-picker": "^0.41.4", "react-native-keyboard-controller": "^1.14.2", "react-native-linear-gradient": "^2.8.3", "react-native-localize": "^3.2.1", "react-native-mmkv-storage": "^0.10.3", "react-native-pager-view": "^6.4.1", "react-native-permissions": "^5.0.1", "react-native-purchases": "^8.2.4", "react-native-rate": "^1.2.12", "react-native-reanimated": "^3.16.1", "react-native-restart": "^0.0.27", "react-native-safe-area-context": "^4.11.1", "react-native-screens": "^3.34.0", "react-native-svg": "^15.8.0", "react-native-tracking-transparency": "^0.1.2", "react-native-url-polyfill": "^2.0.0", "react-native-video": "6.7.0", "rn-range-slider": "2.1.1", "scheduler": "^0.23.2", "sweet-sfsymbols": "^0.7.2", "use-context-selector": "^2.0.0", "use-sync-external-store": "^1.2.2", "uuid": "^10.0.0", "zustand": "^5.0.0" }, "devDependencies": { "@babel/core": "^7.25.8", "@babel/preset-env": "^7.25.8", "@babel/runtime": "^7.25.7", "@react-native/babel-preset": "0.75.4", "@react-native/eslint-config": "0.75.4", "@react-native/metro-config": "0.75.4", "@react-native/typescript-config": "0.75.4", "@tanstack/eslint-plugin-query": "^5.59.7", "@testing-library/jest-native": "^5.4.3", "@testing-library/react-native": "^12.7.2", "@tsconfig/strictest": "^2.0.5", "@types/jest": "^29.5.13", "@types/luxon": "^3.4.2", "@types/node-polyglot": "^2.5.0", "@types/react": "~18.3.11", "@types/react-test-renderer": "^18.3.0", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^8.11.0", "@typescript-eslint/parser": "^8.11.0", "babel-jest": "^29.7.0", "babel-plugin-module-resolver": "^5.0.2", "babel-plugin-transform-remove-console": "^6.9.4", "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-babel-module": "^5.3.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.1", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-native": "^4.1.0", "jest": "^29.7.0", "json-diff": "^1.0.6", "patch-package": "^8.0.0", "postinstall-postinstall": "^2.1.0", "prettier": "3.3.3", "react-test-renderer": "18.3.1", "typescript": "^5.6.3" }, "expo": { "autolinking": { "exclude": [ "expo-application", "expo-font", "expo-keep-awake" ] } }, "resolutions": { "@types/react": "~18.3.11", "@expo/metro-config": "0.18.11" }, "engines": { "node": ">=20 <21" }, "license": "UNLICENSED", "packageManager": "yarn@4.5.0" } ``` #### `firebase.json` for react-native-firebase v6: ```json { "$schema": "./node_modules/@react-native-firebase/app/firebase-schema.json", "react-native": { "crashlytics_debug_enabled": false, "crashlytics_disable_auto_disabler": true, "crashlytics_auto_collection_enabled": true, "crashlytics_ndk_enabled": true, "crashlytics_is_error_generation_on_js_crash_enabled": true, "crashlytics_javascript_exception_handler_chaining_enabled": false, "messaging_android_notification_color": "@color/notification_tint", "messaging_ios_auto_register_for_remote_messages": true } } ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") require 'json' podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {} def node_require(script) # Resolve script with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', "require.resolve( '#{script}', {paths: [process.argv[1]]}, )", __dir__]).strip end node_require('react-native/scripts/react_native_pods.rb') node_require('react-native-permissions/scripts/setup.rb') platform :ios, '14.0' prepare_react_native_project! setup_permissions([ 'AppTrackingTransparency', 'Camera', 'LocationWhenInUse', 'Microphone', 'Notifications', 'PhotoLibrary' ]) $RNFirebaseAsStaticFramework = true linkage = 'static' # ENV['USE_FRAMEWORKS'] if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_sym end target 'MyApp' do use_expo_modules! post_integrate do |installer| begin expo_patch_react_imports!(installer) rescue => e Pod::UI.warn e end end config = use_native_modules! use_react_native!( :path => config[:reactNativePath], # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/..", :privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false', ) target 'MyAppTests' do inherit! :complete # Pods for testing end 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, :ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true', ) installer.aggregate_targets.each do |aggregate_target| aggregate_target.user_project.native_targets.each do |target| target.build_configurations.each do |config| # Arch selection is needed to work across M1/Intel macs, became necessary when App Check was added config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' config.build_settings['EXCLUDED_ARCHS'] = 'i386' end end aggregate_target.user_project.save end end end target 'ImageNotification' do use_frameworks! :linkage => :static pod 'Firebase/Messaging', '~> 11.4.0' end ``` #### `AppDelegate.m`: ```objc #import "AppDelegate.h" #import "RNFBAppCheckModule.h" #import "Firebase.h" #import #import #import #import "RNFBMessagingModule.h" #import "RNBootSplash.h" #import #import #import #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.moduleName = @"MyApp"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. NSDictionary *appProps = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions]; self.initialProps = appProps ? appProps : @{}; [super application:application didFinishLaunchingWithOptions:launchOptions]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions]; [RNFBAppCheckModule sharedInstance]; [FIRApp configure]; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { return [self bundleURL]; } - (NSURL *)bundleURL { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } - (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary *)options { if ([[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options]) { return YES; } if ([GIDSignIn.sharedInstance handleURL:url]) { return YES; } return [RCTLinkingManager application:application openURL:url options:options]; } - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } - (void)customizeRootView:(RCTRootView *)rootView { [super customizeRootView:rootView]; [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; } @end ```


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 15.0 CPU: (12) arm64 Apple M2 Pro Memory: 77.73 MB / 32.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 20.17.0 path: ~/.local/state/fnm_multishells/84604_1729282581815/bin/node Yarn: version: 4.5.0 path: ~/.local/state/fnm_multishells/84604_1729282581815/bin/yarn npm: version: 10.8.2 path: ~/.local/state/fnm_multishells/84604_1729282581815/bin/npm Watchman: version: 2024.08.26.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.15.2 path: /Users/antoinefrancon/.rvm/gems/ruby-3.3.1/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 23.0 - iOS 17.0 - macOS 14.0 - tvOS 17.0 - watchOS 10.0 Android SDK: API Levels: - "33" - "34" Build Tools: - 30.0.3 - 33.0.0 - 33.0.1 - 33.0.2 - 34.0.0 System Images: - android-33 | Google Play ARM 64 v8a - android-34 | Google APIs ARM 64 v8a Android NDK: Not Found IDEs: Android Studio: 2024.1 AI-241.18034.62.2411.12169540 Xcode: version: 15.0.1/15A507 path: /usr/bin/xcodebuild Languages: Java: version: 17.0.12 path: /usr/bin/javac Ruby: version: 3.3.1 path: /Users/antoinefrancon/.rvm/rubies/ruby-3.3.1/bin/ruby npmPackages: "@react-native-community/cli": Not Found react: installed: 18.3.1 wanted: 18.3.1 react-native: installed: 0.75.4 wanted: 0.75.4 react-native-macos: Not Found npmGlobalPackages: "*react-native*": Not Found Android: hermesEnabled: true newArchEnabled: false iOS: hermesEnabled: true newArchEnabled: false ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [x] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `21.2.0` - **`Firebase` module(s) you're using that has the issue:** - `FirebaseAnalytics` - **Are you using `TypeScript`?** - `Y` & `5.6.3`


mikehardy commented 1 month ago

That's odd 🤔 thanks for reporting

I don't think this affects your issue however I don't think the version pin is necessary here as react-native-firebase should constrain this version to the one we expect automatically, so removing it could remove ongoing maintenance for you:

pod 'Firebase/Messaging', '~> 11.4.0'

simply

pod 'Firebase/Messaging' is, I think, sufficient

Not sure about this build break though, as we don't experience in our e2e test app, it builds fine here

I think I see it in your environment though:

iOS SDK 17.0 and Xcode 15.0 - all my build machines are on Xcode 16 now with iOS SDK 18 available

This symbol requires iOS 17.2+ and Xcode 15.1+

https://developer.apple.com/documentation/storekit/transaction/offer/paymentmode/4307062-freetrial

iOS 17.2+
iPadOS 17.2+
Mac Catalyst 17.2+
macOS 14.2+
tvOS 17.2+
visionOS 1.1+
watchOS 10.2+
Xcode 15.1+

Update your build environment - this was noted in the breaking changes section for the react-native-firebase v20 release

https://github.com/invertase/react-native-firebase/blob/main/CHANGELOG.md#-breaking-changes-1

antFrancon commented 1 month ago

Wow @mikehardy, you are absolutely right! The command line tool on my machine was still stuck on the Xcode 15 version. I didn't even notice - since I upgraded to Xcode 16 last month. I guess two versions were installed at the same time. I did some cleanup and it's working fine now. Sorry for the inconvenience and thanks for your help 😀