Skip to content

[馃悰] [iOS] Build error - confusion about useFrameworks and disable SPM#9161

Description

@d-laskowski-trojmiasto

After upgrading to v26 I have a following error during build

[!] [react-native-firebase] SPM + static linkage is not supported (target(s): Pods-Trojmiastopl).
firebase-ios-sdk's Swift Package only ships dynamic library products, so `use_frameworks! :linkage => :static` causes every react-native-firebase pod that resolves Firebase via SPM to embed its own copy of the same Firebase frameworks -- this produces duplicate-symbol linker errors at build time instead of a clear error here.
Fix one of the following in your Podfile, then run `pod install` again:
  - Use dynamic linkage: `use_frameworks! :linkage => :dynamic`
  - Opt out of SPM: set `$RNFirebaseDisableSPM = true` before any target block, then use the static or dynamic linkage your project requires.

This is my expo-build-properties config for iOS that worked fine before upgrade:

"useFrameworks": "static",
"buildReactNativeFromSource": true,
"forceStaticLinking": [
  "RNFBAnalytics",
  "RNFBApp",
  "RNFBCrashlytics",
  "RNFBFirestore",
  "RNFBMessaging"
]

I checked documentation and it says in Getting started section:

For iOS only, since firebase-ios-sdk requires use_frameworks then you want to configure expo-build-properties app.json by adding "useFrameworks": "static".

which is what I have. But iOS SPM Support section says

Do not use RNFB's SPM mode with use_frameworks! :linkage => :static.

and

To use CocoaPods mode in a generated project, pass disableSPM to the @react-native-firebase/app config plugin

so I guess these two options are required together to make things work. I tried add disableSPM to my plugin config but it doesn't solve the problem. However I made custom plugin using AI that disables SPM and it works correctly (no errors during build and app seems to work):

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

module.exports = function withDisableSPM(config) {
  return withDangerousMod(config, [
    "ios",
    async (config) => {
      const podfilePath = path.join(config.modRequest.platformProjectRoot, "Podfile");
      let podfile = fs.readFileSync(podfilePath, "utf-8");

      if (!podfile.includes("$RNFirebaseDisableSPM = true")) {
        podfile = `$RNFirebaseDisableSPM = true\n${podfile}`;
        fs.writeFileSync(podfilePath, podfile);
      }

      return config;
    },
  ]);
};

So my question is how to correctly configure app to make successful build? I guess custom plugin shouldn't be required. Also I think documentation should be more clear about that.

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