thebergamo / react-native-fbsdk-next

MIT License
633 stars 165 forks source link

Undefined symbols for architecture x86_64 #478

Closed short-dsb closed 5 months ago

short-dsb commented 5 months ago

🐛 Bug Report

I’m unable to build our project for iOS with this library using Xcode 14.3 and React Native 0.72.7 (Android works as intended). I’ve tried both workarounds in the README and those on StackOverflow to no avail. I’ve also looked at the example project but haven’t spotted any differences that would cause this error.

Any help would be greatly appreciated. 🙂

To Reproduce

  1. react-native run-ios
  2. Build fails with error code 65
    ❌ Undefined symbols for architecture x86_64
    ❌   "_FBLinkable_NSProcessInfo_MacCatalystDetermining", referenced from:
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKSendButtonManager.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKMessageDialog.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKAuthenticationToken.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKAppLink.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKGameRequestDialog.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKSettings.o)
    ⚠️       _FBLink_NSProcessInfo_MacCatalystDetermining in libreact-native-fbsdk-next.a(RCTFBSDKGraphRequestManager.o)
    ❌   "_FBLinkable_NSProcessInfo_OperatingSystemVersionComparing", referenced from:
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKSendButtonManager.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKMessageDialog.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKAuthenticationToken.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKAppLink.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKGameRequestDialog.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKSettings.o)
    ⚠️       _FBLink_NSProcessInfo_OperatingSystemVersionComparing in libreact-native-fbsdk-next.a(RCTFBSDKGraphRequestManager.o)
    ❌   "_FBLinkable_UIPasteboard_FBSDKPasteboard", referenced from:
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKSendButtonManager.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKMessageDialog.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKAuthenticationToken.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKAppLink.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKGameRequestDialog.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKSettings.o)
    ⚠️       _FBLink_UIPasteboard_FBSDKPasteboard in libreact-native-fbsdk-next.a(RCTFBSDKGraphRequestManager.o)
    ❌ ld: symbol(s) not found for architecture x86_64
    ❌ clang: error: linker command failed with exit code 1 (use -v to see invocation)

I’ve also tried #import <FBSDKCoreKit/FBSDKCoreKit-Swift.h> instead of #import <FBSDKCoreKit/FBSDKCoreKit.h>, but I get a different error:

[shortboxed] Compiling AppDelegate.mm
❌ /Users/dsb/quicksilver-app/ios/shortboxed/AppDelegate.mm:32:12: use of undeclared identifier 'FBSDKApplicationDelegate'
  return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options] ||
           ^
❌ /Users/dsb/quicksilver-app/ios/shortboxed/AppDelegate.mm:51:5: use of undeclared identifier 'FBSDKApplicationDelegate'
  [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
    ^

Expected Behavior

Build completes successfully.

Code Example

AppDelegate.mm:

#import "AppDelegate.h"

#import <Firebase.h>
#import <React/RCTLinkingManager.h>
#import <SDWebImageWebPCoder/SDImageWebPCoder.h>
#import "RNPaypal.h"
#import "RNSplashScreen.h"
#import "SDImageCodersManager.h"

#import <GoogleSignIn/GoogleSignIn.h>

#import <React/RCTBundleURLProvider.h>

#import <AuthenticationServices/AuthenticationServices.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <SafariServices/SafariServices.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  if ([url.scheme localizedCaseInsensitiveCompare:self.paymentsURLScheme] == NSOrderedSame) {
    return [BTAppSwitch handleOpenURL:url options:options];
  }

  if ([[RNPaypal sharedInstance] application:application openURL:url options:options]) {
    return YES;
  }

  return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options] ||
      [GIDSignIn.sharedInstance handleURL:url];

  return [RCTLinkingManager application:application openURL:url options:options];
}

- (BOOL)application:(UIApplication *)application
    continueUserActivity:(nonnull NSUserActivity *)userActivity
      restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> *_Nullable))restorationHandler
{
  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [[RNPaypal sharedInstance] configure];
  [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];

  [BTAppSwitch setReturnURLScheme:self.paymentsURLScheme];

  /**
   * Deletes all Keychain items accessible by this app if this is the first time
   * the user launches the app.
   */
  // Checks wether or not this is the first time the app is run.
  if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HAS_RUN_BEFORE"] == NO) {
    // Set the appropriate value so we don't clear next time the app is launched.
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HAS_RUN_BEFORE"];

    NSArray *secItemClasses = @[
      (__bridge id)kSecClassGenericPassword,
      (__bridge id)kSecClassInternetPassword,
      (__bridge id)kSecClassCertificate,
      (__bridge id)kSecClassKey,
      (__bridge id)kSecClassIdentity
    ];

    // Maps through all Keychain classes and deletes all items that match.
    for (id secItemClass in secItemClasses) {
      NSDictionary *spec = @{(__bridge id)kSecClass : secItemClass};
      SecItemDelete((__bridge CFDictionaryRef)spec);
    }
  }

  // Register WebP format support
  [SDImageCodersManager.sharedManager addCoder:SDImageWebPCoder.sharedCoder];

  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.
  self.initialProps = @{};
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSString *)paymentsURLScheme
{
  NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
  return [NSString stringWithFormat:@"%@.%@", bundleIdentifier, @"payments"];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

Podfile:

# 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
platform :ios, '13.0'
prepare_react_native_project!

# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
# ```js
# module.exports = {
#   dependencies: {
#     ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
# ```
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
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

# Toggle this to true for the no-ad-tracking Analytics subspec
# https://rnfirebase.io/analytics/usage#disable-ad-id-usage-on-ios
$RNFirebaseAnalyticsWithoutAdIdSupport = true

target 'OneSignalNotificationServiceExtension' do
  pod 'OneSignalXCFramework', '>= 3.0', '< 4.0'
end

target 'myapp' do
  config = use_native_modules!

  pod 'react-native-image-crop-tools', :path => '../node_modules/react-native-image-crop-tools'

  # Flags change depending on the env values.
  flags = get_default_flags()

  use_react_native!(
    :path => config[:reactNativePath],
    # Hermes is now enabled by default. Disable by setting this flag to false.
    :hermes_enabled => flags[:hermes_enabled],
    :fabric_enabled => flags[:fabric_enabled],
    # Enables Flipper.
    #
    # Note that if you have use_frameworks! enabled, Flipper will not work and
    # you should disable the next line.
    :flipper_configuration => flipper_config,
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

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

  post_install do |installer|
    # Mixing Swift and Objective-C in a react-native project may be problematic.
    # Workaround:  https://github.com/facebookarchive/react-native-fbsdk/issues/755#issuecomment-787488994
    installer.aggregate_targets.first.user_project.native_targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(inherited)', '$(SDKROOT)/usr/lib/swift']
      end
    end
    installer.aggregate_targets.first.user_project.save
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"
      end
    end
    # 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|
        # Support for Xcode v14, which requires code signing
        # https://github.com/CocoaPods/CocoaPods/issues/11402
        config.build_settings["DEVELOPMENT_TEAM"] = "BXVH3243KA"
        if target.name == "BraintreeDropIn"
          # Fixes build issue with the Braintree Drop-in UI
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
        end
      end
    end
  end
end

Environment

System:
  OS: macOS 13.6.1
  CPU: (8) x64 Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
  Memory: 2.21 GB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.18.0
    path: ~/.nvm/versions/node/v18.18.0/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.nvm/versions/node/v18.18.0/bin/yarn
  npm:
    version: 9.8.1
    path: ~/.nvm/versions/node/v18.18.0/bin/npm
  Watchman:
    version: 2023.10.02.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.12.1
    path: /Users/me/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 22.4
      - iOS 16.4
      - macOS 13.3
      - tvOS 16.4
      - watchOS 9.4
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.3 AI-223.8836.35.2231.10811636
  Xcode:
    version: 14.3/14E222b
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 11.0.20.1
    path: /usr/bin/javac
  Ruby:
    version: 2.7.6
    path: /Users/me/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.72.7
    wanted: 0.72.7
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false
mikehardy commented 5 months ago

with apologies, others are building fine (as are my projects) so this will not result in a change in this repository and so is not an issue, it's a project-specific problem

you and others may feel free to continue discussion here (and propose a PR to the docs if anything interesting is learned) but I don't have any time personally to troubleshoot project-specific problem

I suggest you build an example from scratch (starting with npx react-native init BuildTest or similar and proving it can work, then figuring out why your project is not working

short-dsb commented 5 months ago

This appears to be due to migrating from v14 of the official Facebook SDK to this package, resulting in an FBSDKCoreKit-Swift.h that was cached from the previous version. Running a clean build in Xcode resolved the issue.

However, this resulted in a new error:

❌ /Users/dsb/Library/Developer/Xcode/DerivedData/shortboxed-euoiztpisgpuzndyuevmudfutzne/Build/Products/Debug-iphonesimulator/XCFrameworkIntermediates/FBSDKCoreKit/FBSDKCoreKit.framework/Headers/FBSDKCoreKit-Swift.h:2519:146: cannot find protocol declaration for 'SFSafariViewControllerDelegate'
@interface _BridgeAPI : NSObject <FBSDKBridgeAPIRequestOpening, FBSDKApplicationObserving, FBSDKURLOpener, FBSDKContainerViewControllerDelegate, SFSafariViewControllerDelegate>

The problem was the order of the #import statements. SafariServices.h must be imported before FBSDKCoreKit-Swift.h. It was being placed after due to my ClangFormat configuration, which declared SortIncludes: true.

Hopefully this helps someone else. 🙂

short-dsb commented 5 months ago

@mikehardy You beat me to closing the issue. Thanks for your prompt response!