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

[🐛] @react-native-firebase/firestore fails to build on Xcode 16 - BoringSSL-GRPC issue unsupported option '-G' #8020

Open
2 of 10 tasks
alfjesus opened this issue Sep 17, 2024 · 25 comments
Labels

Comments

@alfjesus
Copy link

alfjesus commented Sep 17, 2024

Issue

Getting the following "unsupported option -G" build error when trying to build with Expo 51 and Xcode 16.
I'm guessing that the dependency for pod BoringSSL-GRPC needs an update.
CleanShot 2024-09-17 at 10 35 22@2x


Project Files

Javascript

Click To Expand

package.json:

# N/A

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
# N/A

AppDelegate.m:

// N/A


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:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->


Environment

Click To Expand

react-native info output:

 System:
  OS: macOS 15.0
  CPU: (12) arm64 Apple M2 Pro
  Memory: 465.64 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.17.0
    path: /var/folders/jn/92972fv55qdc10m6nk8nps3w0000gn/T/yarn--1726562737749-0.4741444639345749/node
  Yarn:
    version: 1.22.21
    path: /var/folders/jn/92972fv55qdc10m6nk8nps3w0000gn/T/yarn--1726562737749-0.4741444639345749/yarn
  npm:
    version: 10.8.2
    path: /opt/homebrew/opt/node@20/bin/npm
  Watchman:
    version: 2024.07.08.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.0
      - iOS 18.0
      - macOS 15.0
      - tvOS 18.0
      - visionOS 2.0
      - watchOS 11.0
  Android SDK: Not Found
IDEs:
  Android Studio: 2023.2 AI-232.10300.40.2321.11567975
  Xcode:
    version: 16.0/16A242d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.74.5
    wanted: 0.74.5
  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
    • 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:
    • 20.5.0
  • Firebase module(s) you're using that has the issue:
    • firestore
  • Are you using TypeScript?
    • Y & 5.3.3


@joaqo
Copy link
Contributor

joaqo commented Sep 17, 2024

Same here.

@itsjustjo96
Copy link

Same for me. Apparently this issue was fixed in BoringSSL 0.36.

grpc/grpc#36904

@itsjustjo96
Copy link

This fix indeed seems to work. Adding this code piece to the podfile and then reinstalling the pods is a temporary fix.

https://stackoverflow.com/a/78633109

@alfjesus
Copy link
Author

This fix indeed seems to work. Adding this code piece to the podfile and then reinstalling the pods is a temporary fix.

https://stackoverflow.com/a/78633109

@itsjustjo96 Yes, that fix works. However, when using Expo Prebuild i.e CNG (Continuous Native Generation ), the podfile gets overwritten every time.

@russellwheatley
Copy link
Member

Thank you for the workaround, @itsjustjo96 🙏 . Unfortunately, I'll be away for a week. If there is someone who is able to raise a PR in the meanwhile, I can take a look when I get back. Otherwise, I can get a fix up next week 👍

@mikehardy
Copy link
Collaborator

mikehardy commented Sep 17, 2024

Upstream firebase-ios-sdk specifies a version range for the transitive gRPC dependency with the problem:

https://github.com/firebase/firebase-ios-sdk/blob/b5e2c182c83db543829f2a712f5cff7e6ad1ce1e/FirebaseFirestoreInternal.podspec#L107-L108

Here's the upstream issue firebase/firebase-ios-sdk#13115

When I do a fresh install using firebase-ios-sdk 11.2.0 it works to bring in a version of gRPC with the fix, that is a gRPC with version >= 1.65.2:

run pod install and check output, here's a snippet:

Installing gRPC-C++ (1.65.5)
Installing gRPC-Core (1.65.5)

gRPC and Firestore compile fine for me

So I do not believe this is an issue. You may need to remove your Podfile.lock and reinstall Pods to get the updated transitive dependency?


(I'm having other compile failures at the moment, notably the crashlytics init provider I worked on recently in #7837 but I will hopefully have that working shortly)

[RNFBCrashlytics] Compiling RNFBCrashlyticsInitProvider.m
❌ /Users/mike/work/invertase/rnfbdemo/rnfbdemo/node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.m:135:21: no known class method for selector 'componentWithProtocol:instantiationTiming:dependencies:creationBlock:'
  135 |       [FIRComponent componentWithProtocol:@protocol(RNFBCrashlyticsInitProviderProtocol)
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@mikehardy mikehardy changed the title [🐛] @react-native-firebase/firestore fails to build on Xcode 16 - BoringSSL-GRPC issue [🐛] @react-native-firebase/firestore fails to build on Xcode 16 - BoringSSL-GRPC issue unsupported option '-G' Sep 17, 2024
@mikehardy
Copy link
Collaborator

Note that if you are using the pre-compiled / binary Firebase from firestore-ios-sdk-frameworks they do not appear to have the fix but that is not a bug in react-native-firebase, it should be logged tracked over there.

Appears they are still on gRPC 1.65.1 which does not have the fix: https://github.com/search?q=repo%3Ainvertase%2Ffirestore-ios-sdk-frameworks+gRPC&type=code

A workaround would be to deintegrate the pre-compiled version and build firestore from current source with current transitive deps, and if compile speed is an issue you might try ccache

@alfjesus
Copy link
Author

@mikehardy If I spawn up a new Expo project and add @react-native-firebase/firestore the same build failure is happening so I think this is still an issue?

@mikehardy
Copy link
Collaborator

@alfjesus I don't use Expo so I cannot comment.
I build things from scratch in order to make my assertions though, and I cannot reproduce - my build rig: https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh

(I have local changes in that one to do the test, but it shows what I'm doing - init of bare react-native project, scripted integration of react-native-firebase, build test)

@alfjesus
Copy link
Author

@mikehardy Okay I see. It's just that my Expo project was building fine on Xcode 15.4 and as soon I upgraded to Xcode 16 this build issue started to happen.

@mikehardy
Copy link
Collaborator

mikehardy commented Sep 17, 2024

I believe I see the problem - just noticed that react-native-firebase hasn't adopted firebase-ios-sdk v11+ yet

It is only in firebase-ios-sdk v11+ that the gRPC version was updated, you can see the commit that did the bump and expand the tag list to see it is only SDK v11+ tags: firebase/firebase-ios-sdk@89a0ab3

My build rig specifically overrides firebase-ios-sdk in order to compile test with newer versions in order to find problems before users do, but that means it doesn't always see problems with interop in older versions

Unfortunately if you use firebase-ios-sdk v11+ via an override, you'll have a new problem which is that the crashlytics init provider API signature upstream changed and is not compatible across the firebase-ios-sdk v10 / v11 boundary

dependencies:@[] // note this will go away in firebase-ios-sdk v11+

(with a local patch that implements #8025, and a patch that implements #8021 which I just posted, firebase-ios-sdk v11.2.0 appears to work fine with gRPC and crashlytics in build testing at least)

@alfjesus
Copy link
Author

@mikehardy Nice to hear that you have nailed down the root cause of the issue. Hopefully react-native-firebase can be adotped soon to use firebase-ios-sdk v11+. I believe that the number of users impacted by this issue will increase by every day that passed by when people upgrade to Xcode 16, unaware of this issue. Rollback is also not so easy since after upgrading to Xcode 16 on MacOS Sequoia, you can't roll back to Xcode 15.4.

@alfjesus
Copy link
Author

Figured out a temporary patch to adopt in firebase-ios-sdk v11+. Builds successfully after patching.

Attaching the patch files
@react-native-firebase+firestore+20.5.0.patch
@react-native-firebase+app+20.5.0.patch

@mikehardy
Copy link
Collaborator

If you need crashlytics and firebase-ios-sdk v11+ you'll also want this:

diff --git a/node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.m b/node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.m
index b815df9..4e4961d 100644
--- a/node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.m
+++ b/node_modules/@react-native-firebase/crashlytics/ios/RNFBCrashlytics/RNFBCrashlyticsInitProvider.m
@@ -134,7 +134,6 @@ NSString *const KEY_CRASHLYTICS_JAVASCRIPT_EXCEPTION_HANDLER_CHAINING_ENABLED =
   FIRComponent *crashlyticsInitProvider =
       [FIRComponent componentWithProtocol:@protocol(RNFBCrashlyticsInitProviderProtocol)
                       instantiationTiming:FIRInstantiationTimingEagerInDefaultApp
-                             dependencies:@[]  // note this will go away in firebase-ios-sdk v11+
                             creationBlock:creationBlock];
 
   return @[ crashlyticsInitProvider ];

(I have it as patches/@react-native-firebase+crashlytics+20.5.0.patch) --> https://github.com/mikehardy/rnfbdemo/blob/main/patches/%40react-native-firebase%2Bcrashlytics%2B20.5.0.patch

@oskaremilsson
Copy link

Thank you! 🙏 I just want to confirm that with these 3 patches our Expo-project now builds again. 🎉

@tibbe

This comment was marked as resolved.

@IbraheemShawhnee

This comment was marked as duplicate.

@enmanuelmag

This comment was marked as duplicate.

@mikehardy
Copy link
Collaborator

mikehardy commented Sep 18, 2024

Hey everyone! 👋

+1s, reports that it is also affecting you: that does not help
it really makes the issue hard to read for others that want a workaround

The workaround right now is to patch react-native-firebase with the above patches:

  • one to bump firebase-ios-sdk to 11.2.0,
  • one to fix firestore
  • optional one to fix crashlytics build if you use crashlytics

And then we have to wait for an official release

If you subscribe to this issue using the button on the right of the github web UI you will be notified when it is closed so you know there is new information

Until then, we all have to use the patches or wait for a release.

@terrafant
Copy link

terrafant commented Sep 18, 2024

This fix indeed seems to work. Adding this code piece to the podfile and then reinstalling the pods is a temporary fix.

https://stackoverflow.com/a/78633109

For Expo project this solution works for me:

  1. Add withBoringSSLFix.js to the root of the project:
// withBoringSSLFix.js

const { withDangerousMod } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

const withBoringSSLFix = (config) => {
  return withDangerousMod(config, [
    'ios',
    (config) => {
      const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
      let podfileContents = fs.readFileSync(podfilePath, 'utf-8');

      //  Fix for the Podfile
      const fix = `
  pre_install do |installer|
    installer.pod_targets.each do |pod|
      if pod.name.eql?('BoringSSL-GRPC')
        def pod.build_type;
          Pod::BuildType.static_library
        end
      end
    end
  end
`;

      // Adding the fix before the first 'post_install' occurrence
      if (!podfileContents.includes("pod.name.eql?('BoringSSL-GRPC')")) {
        const postInstallIndex = podfileContents.indexOf('post_install do |installer|');
        if (postInstallIndex !== -1) {
          podfileContents = podfileContents.slice(0, postInstallIndex) + fix + podfileContents.slice(postInstallIndex);
        } else {
          // If there's no post_install, append the fix at the end
          podfileContents += fix;
        }
        fs.writeFileSync(podfilePath, podfileContents);
      }

      return config;
    },
  ]);
};

module.exports = withBoringSSLFix;
  1. Update app.config.js (or if you don't have app.config.js, then convert app.json to app.config.js):
import withBoringSSLFix from './withBoringSSLFix';

export default {
  expo: {
    //... expo configs
     plugins: [
  // ... other existing plugins
  withBoringSSLFix,
   ]}
}
  1. Regenerate the native iOS project
    npx expo prebuild -p ios --clean
  2. Run iOS project:
    npx expo run:ios

@alfjesus
Copy link
Author

This fix indeed seems to work. Adding this code piece to the podfile and then reinstalling the pods is a temporary fix.
https://stackoverflow.com/a/78633109

For Expo project this solution works for me:

  1. Add withBoringSSLFix.js to the root of the project:
// withBoringSSLFix.js

const { withDangerousMod } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

const withBoringSSLFix = (config) => {
  return withDangerousMod(config, [
    'ios',
    (config) => {
      const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
      let podfileContents = fs.readFileSync(podfilePath, 'utf-8');

      //  Fix for the Podfile
      const fix = `
  pre_install do |installer|
    installer.pod_targets.each do |pod|
      if pod.name.eql?('BoringSSL-GRPC')
        def pod.build_type;
          Pod::BuildType.static_library
        end
      end
    end
  end
`;

      // Adding the fix before the first 'post_install' occurrence
      if (!podfileContents.includes("pod.name.eql?('BoringSSL-GRPC')")) {
        const postInstallIndex = podfileContents.indexOf('post_install do |installer|');
        if (postInstallIndex !== -1) {
          podfileContents = podfileContents.slice(0, postInstallIndex) + fix + podfileContents.slice(postInstallIndex);
        } else {
          // If there's no post_install, append the fix at the end
          podfileContents += fix;
        }
        fs.writeFileSync(podfilePath, podfileContents);
      }

      return config;
    },
  ]);
};

module.exports = withBoringSSLFix;
  1. Update app.config.js (or if you don't have app.config.js, then convert app.json to app.config.js):
import withBoringSSLFix from './withBoringSSLFix';

export default {
  expo: {
    //... expo configs
     plugins: [
  // ... other existing plugins
  withBoringSSLFix,
   ]}
}
  1. Regenerate the native iOS project
    npx expo prebuild -p ios --clean
  2. Run iOS project:
    npx expo run:ios

This fix indeed seems to work. Adding this code piece to the podfile and then reinstalling the pods is a temporary fix.
https://stackoverflow.com/a/78633109

For Expo project this solution works for me:

  1. Add withBoringSSLFix.js to the root of the project:
// withBoringSSLFix.js

const { withDangerousMod } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

const withBoringSSLFix = (config) => {
  return withDangerousMod(config, [
    'ios',
    (config) => {
      const podfilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile');
      let podfileContents = fs.readFileSync(podfilePath, 'utf-8');

      //  Fix for the Podfile
      const fix = `
  pre_install do |installer|
    installer.pod_targets.each do |pod|
      if pod.name.eql?('BoringSSL-GRPC')
        def pod.build_type;
          Pod::BuildType.static_library
        end
      end
    end
  end
`;

      // Adding the fix before the first 'post_install' occurrence
      if (!podfileContents.includes("pod.name.eql?('BoringSSL-GRPC')")) {
        const postInstallIndex = podfileContents.indexOf('post_install do |installer|');
        if (postInstallIndex !== -1) {
          podfileContents = podfileContents.slice(0, postInstallIndex) + fix + podfileContents.slice(postInstallIndex);
        } else {
          // If there's no post_install, append the fix at the end
          podfileContents += fix;
        }
        fs.writeFileSync(podfilePath, podfileContents);
      }

      return config;
    },
  ]);
};

module.exports = withBoringSSLFix;
  1. Update app.config.js (or if you don't have app.config.js, then convert app.json to app.config.js):
import withBoringSSLFix from './withBoringSSLFix';

export default {
  expo: {
    //... expo configs
     plugins: [
  // ... other existing plugins
  withBoringSSLFix,
   ]}
}
  1. Regenerate the native iOS project
    npx expo prebuild -p ios --clean
  2. Run iOS project:
    npx expo run:ios

@terrafant Even though your fix works, I don't understand why this option is preferable compared to patches? I mean once a new version of react-native-firebase is out, you will need to modify app.config.js again to remove the fix. A patch on the other hand is only bound and applied to a specific version, hence no code change is necessary when a new release is out.

@terrafant
Copy link

@alfjesus because this way I don't have to reapply patches again if I need to redo npm install

@alfjesus
Copy link
Author

@alfjesus because this way I don't have to reapply patches again if I need to redo npm install

https://github.com/ds300/patch-package to the rescue! This is want I use. Applies patches automatically every time you do npm install

@mikehardy
Copy link
Collaborator

mikehardy commented Sep 18, 2024

It may be that adopting new versions requires some sort of coordination / certification process for users such that even a release of react-native-firebase does not really help them quickly as someone may not be able to adopt it, and patches may not be allowed for certification reasons too 🤷 .

So I appreciate the Expo plugin workaround from @terrafant even if I also personally use + love the patch-package module.

You never know which workaround people will need.

I believe the fixes required to adopt firebase-ios-sdk v11+ are in process though and there will be a release soon.

Until then, patch it, do a plugin, whichever works but hopefully everyone is able to continue working despite the yearly disruption that is the Xcode release day :-)

@PavelShev
Copy link

PavelShev commented Sep 18, 2024

same here. ReactNative CLI
Edit the Podfile, and the project started build like a charm

post_install do |installer|
    installer.pods_project.targets.each do |target|
      if target.name == 'BoringSSL-GRPC'
        target.source_build_phase.files.each do |file|
          if file.settings && file.settings['COMPILER_FLAGS']
            flags = file.settings['COMPILER_FLAGS'].split
            flags.reject! { |flag| flag == '-GCC_WARN_INHIBIT_ALL_WARNINGS' }
            file.settings['COMPILER_FLAGS'] = flags.join(' ')
          end
        end
      end
    end
    $RNMapboxMaps.post_install(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 => true
    )
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests