expo: Upgrading to expo@44.0.0 breaks iOS build of amazon-cognito-identity-js

Summary

I use amazon-cognito-identity-js@5.1.0 in my project as well as expo. I tried upgrading to expo@44.0.0, but the iOS build then fails with a lot of errors, e.g:

error: duplicate interface definition for class 'RCTCallableJSModules'
error: duplicate interface definition for class 'RCTViewRegistry'
error: duplicate interface definition for class 'RCTBundleManager'
error: conflicting types for 'RCTMakeError'

Build log is attached: expo-44-build-error.txt

This build error does not occur with expo@43.0.3

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

bare

What platform(s) does this occur on?

iOS

SDK Version (managed workflow only)

No response

Environment

  Expo CLI 5.0.1 environment info:
    System:
      OS: macOS 12.0.1
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 14.18.1 - ~/.nvm/versions/node/v14.18.1/bin/node
      npm: 6.14.15 - ~/.nvm/versions/node/v14.18.1/bin/npm
      Watchman: 2021.11.15.00 - /usr/local/bin/watchman
    Managers:
      CocoaPods: 1.11.2 - /usr/local/bin/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 21.0.1, iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0
      Android SDK:
        API Levels: 23, 24, 26, 28, 29, 30
        Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2, 31.0.0
        System Images: android-24 | Google Play Intel x86 Atom, android-29 | Intel x86 Atom_64, android-30 | Google Play Intel x86 Atom
    IDEs:
      Android Studio: 2020.3 AI-203.7717.56.2031.7621141
      Xcode: 13.1/13A1030d - /usr/bin/xcodebuild
    npmPackages:
      expo: >=44.0.0-* <45.0.0 => 44.0.0 
      react: 17.0.2 => 17.0.2 
      react-native: 0.66.4 => 0.66.4 
    npmGlobalPackages:
      expo-cli: 5.0.1
    Expo Workflow: bare

Reproducible demo

I created a minimal reproducer here: https://github.com/schiller-manuel/expo-issue

The project was created using these steps:

  1. npx react-native init ExpoIssue --template react-native-template-typescript
  2. npm install amazon-cognito-identity-js && npx pod-install
  3. npx install-expo-modules

Run npm run ios to reproduce the build errors.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 72 (37 by maintainers)

Commits related to this issue

Most upvoted comments

I found that I had 2 different versions of expo-modules-core installed when I upgraded expo. I used the yarn resolutions to force to the version from within expo and it fixed this issue.

// package.json

{
  "resolutions": {
    "expo-modules-core": "^0.6.3"
  }
}

The long description about how these build errors happen to SDK 44.

In SDK 44, we introduced more Swift integration in expo-modules-core for the upcoming Swift native module support. And we encountered a lot of problems from mixing Objective-C and Swift. From my study, Swift does not honor the header search paths like Objective-C. Under the hood, Swift only knows to Clang Modules or Frameworks. Although react-native nowadays has DEFINES_MODULE in React-Core.podspec, most of external code still access to sub-headers, e.g. #import <React/RCTBridge.h> but not #import <React/React-Core-umbrella.h>. In this case, we are still not using React as a Clang Module. Technically, Clang can automatically transform #import <React/RCTBridge.h> to submodule based @import React.RCTBridge;; Unfortunately, there’s some issue from React-Core.podspec or CocoaPods, which submodules did not generate correctly. So we still have not accessed React as a Clang Module.

In #15299, we patched the React-Core.podspec to make sub-modules generation right; In the description of #15299, you can find when Swift cannot access to Clang Modules, the compiler will internally create a submodule under the hood. There will be multiple RCTViewManager, e.g. ExpoModulesCore.RCTViewManager or AnotherModule.RCTViewManager, making weird errors like ExpoModulesCore cannot access the RCTViewManager in AnotherModule because they are different RCTViewManager. If submodules generate right, there should be only one React.RCTViewManager there.

A side effect came after #15299 when we did right for Clang submodules. #import <React/RCTBridge.h> which has the submodule under the hood is not compatible #import "RCTBridge.h" anymore. Xcode also suggests not to use double-quoted for Module/Framework imports. It is just that there’s so much double-quoted code out from Expo and may also introduce new & unexpected issues. That’s why I am hesitant to create a React-Core.podspec PR for react-native upstream.

Formal solution for the build errors

React headers should always use the #import <React/*.h> form. We should create PR to third-party libraries for this update.

Can we safely transform the double-quoted React header imports?

As far as I can tell, after react-native 0.60 or 0.61, which fully adopt CocoaPods, we can safely do #import <React/*.h>. The old style import might be for react-native < 0.40; The upstream code also changed to the new style far longer before.

Workaround 1 - patch-package

There are much more third-party libraries with double-quoted imports than I expected. If we cannot update them all from upstreams, a workaround would be patch-package. It is good to know that Expo managed apps also support patch-package on EAS Build.

Workaround 2 - "USE_HEADERMAP" = "NO"

This only targets the

#if __has_include("RCTBridgeModule.h")
#import "RCTBridgeModule.h"
#else
#import <React/RCTBridgeModule.h>
#endif

pattern where disabling headermap makes double-quoted header unavailable and goes to the else block in #import <React/*.h> form. You can patch ios/Podfile like this to disable headermap for most modules.

--- a/ios/Podfile
+++ b/ios/Podfile
@@ -25,6 +25,15 @@ target 'sdk44' do
   post_install do |installer|
     react_native_post_install(installer)

+    # Workaround build error for classic quoted imports
+    installer.pods_project.targets.each do |target|
+      target.build_configurations.each do |config|
+        unless ['React-Core', 'React-RCTText'].include? target.name
+          config.build_settings["USE_HEADERMAP"] = "NO"
+        end
+      end
+    end
+

Please let me know if you find any modules that rely on headermap to work. It is also good to know that disabling headermap may increase a little building time.

i tend to find a workaround for the problem if we cannot update all 3rd party libraries in the meantime, could you help to verify with this?

applying this patch into ios/Podfile and rm -rf ios/Pods && npx pod-install

--- a/ios/Podfile
+++ b/ios/Podfile
@@ -25,6 +25,15 @@ target 'sdk44' do
   post_install do |installer|
     react_native_post_install(installer)

+    # Workaround build error for classic quoted imports
+    installer.pods_project.targets.each do |target|
+      target.build_configurations.each do |config|
+        unless ['React-Core', 'React-RCTText'].include? target.name
+          config.build_settings["USE_HEADERMAP"] = "NO"
+        end
+      end
+    end
+

hi there! as with #15626, nowadays we strictly require importing react headers with #import <React/*.h> form. however, amazon-cognito-identity-js still uses the old style imports there. i will create a pr for them. in the meantime, you could probably use patch-package for it.

patches/amazon-cognito-identity-js+5.2.3.patch

diff --git a/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h b/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
index a28e3c1..ab6fdce 100644
--- a/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
+++ b/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
@@ -1,20 +1,6 @@
-#if __has_include("RCTBridgeModule.h")
-#import "RCTBridgeModule.h"
-#else
#import <React/RCTBridgeModule.h>
-#endif
-
-#if __has_include("RCTLog.h")
-#import "RCTLog.h"
-#else
#import <React/RCTLog.h>
-#endif
-
-#if __has_include("RCTUtils.h")
-#import "RCTUtils.h"
-#else
#import <React/RCTUtils.h>
-#endif

#import "JKBigInteger.h"

thanks for reporting the issue to us.

I found that I had 2 different versions of expo-modules-core installed when I upgraded expo. I used the yarn resolutions to force to the version from within expo and it fixed this issue.

// package.json

{
  "resolutions": {
    "expo-modules-core": "^0.6.3"
  }
}

Thanks! This worked for me now.

expo_patch_react_imports didn’t work for us.

Projects like instabug-react-native that extended RCTConvert (Example: RCTConvert+InstabugEnums.m) still made the project build fail.

There is also problem with react-native-auth0 - https://github.com/auth0/react-native-auth0

Here is patch-package which fixes it:

diff --git a/node_modules/react-native-auth0/ios/A0Auth0.h b/node_modules/react-native-auth0/ios/A0Auth0.h
index 8323510..798ba97 100644
--- a/node_modules/react-native-auth0/ios/A0Auth0.h
+++ b/node_modules/react-native-auth0/ios/A0Auth0.h
@@ -1,8 +1,4 @@
-#if __has_include("RCTBridgeModule.h")
-#import "RCTBridgeModule.h"
-#else
 #import <React/RCTBridgeModule.h>
-#endif
 
 @interface A0Auth0 : NSObject <RCTBridgeModule>
 
diff --git a/node_modules/react-native-auth0/ios/A0Auth0.m b/node_modules/react-native-auth0/ios/A0Auth0.m
index f9c9a4e..59d71e8 100644
--- a/node_modules/react-native-auth0/ios/A0Auth0.m
+++ b/node_modules/react-native-auth0/ios/A0Auth0.m
@@ -6,11 +6,7 @@
 #endif
 #import <CommonCrypto/CommonCrypto.h>
 
-#if __has_include("RCTUtils.h")
-#import "RCTUtils.h"
-#else
 #import <React/RCTUtils.h>
-#endif
 
 #define ERROR_CANCELLED @{@"error": @"a0.session.user_cancelled",@"error_description": @"User cancelled the Auth"}
 #define ERROR_FAILED_TO_LOAD @{@"error": @"a0.session.failed_load",@"error_description": @"Failed to load url"}

hi there! thank you for reporting this issue and also help to create tons of prs to other libraries. people from the community are awesome 🔥 since the broken libraries are much more from my expectation, i was thinking if there are something we can do from our side and #15655 is our temporarily solution. in a nutshell, we try to transform all the double-quoted import on the fly; hopefully this solution can help people adopt sdk 44 smoothly.

  • for new project, we already updated the solution for you. you can simply install packages and build apps as it is.
  • for managed project, ~the solution will automatically setup during expo prebuild for you. you can also install packages and build apps as it is~, please upgrade expo packages to latest: yarn add expo@~44.0.3.
  • for sdk44 bare project, it requires some more steps. perhaps doing expo prebuild again can help.

please let us know if this works for you. thanks.

We have some other deps still using the old import style @Kudo mentioned, like

Is there any way we can disable Expo’s importing restriction? I’ll try to send PRs to those libs but may need some time. I think people will have this problem if they are using bare workflow with other native libs.

@yvbeek because the special rule to opt out /react-native/ from patching imports automatically, the @amplitude/react-native is excluded. i’ve sent a pr anyway: https://github.com/amplitude/Amplitude-ReactNative/pull/108

interesting! i am curious which package makes to multiple expo-modules-core versions. maybe it’s worth to run yarn why expo-modules-core to have more information for us.

Hi @Kudo, not sure if its related but @schiller-manuel mentioned that he also got the error ../node_modules/expo/ios/EXAppDefinesLoader.m:13:4: Use of undeclared identifier 'EXAppDefines'. Got this when trying to build iOS in bare after upgrading to SDK 44.

@Pnickolas1 thanks for your detailed information. yep, the problem is amazon-cognito-identity-js not in the top level dependencies. or you could also use expo-random by expo install expo-random. amazon-cognito-identity-js also integrates expo-random under the hood.

thanks @leejunhui. it seems the repo is too old to even for autolinking and pod install. since the repo is archived, maybe the way you forked is the right solution in the mean time.

[!] The `RNSiriWaveView` pod failed to validate due to 1 error:
    - ERROR | attributes: Missing required attribute `homepage`.
    - WARN  | source: The version should be included in the Git tag.
    - WARN  | description: The description is equal to the summary.

Nice out of the box experience…

Get Outlook for Androidhttps://aka.ms/AAb9ysg


From: Abhishek Sah @.> Sent: Tuesday, February 15, 2022 6:24:18 AM To: expo/expo @.> Cc: Sean O’Leary @.>; Mention @.> Subject: [External]Re: [expo/expo] Upgrading to @.*** breaks iOS build of amazon-cognito-identity-js (Issue #15622)

@sean-m-olearyhttps://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fsean-m-oleary&data=04|01|soleary%40venterra.com|c99cd31a26334e141abc08d9f075b549|e22aea6d0cf848038e12edaecd4fa3f2|0|0|637805210640660775|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D|3000&sdata=HvI6VTtpUuodcAdwRFbFh4zTUuj8SoyPxdknyHaaEjQ%3D&reserved=0 what is a NOOBE?

— Reply to this email directly, view it on GitHubhttps://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fexpo%2Fexpo%2Fissues%2F15622%23issuecomment-1040158005&data=04|01|soleary%40venterra.com|c99cd31a26334e141abc08d9f075b549|e22aea6d0cf848038e12edaecd4fa3f2|0|0|637805210640660775|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D|3000&sdata=9ilGeeklsLgq4q2eIA%2Be8YiD9Zb%2B4%2Fr4%2Fqu9gUmdxts%3D&reserved=0, or unsubscribehttps://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAAYXDBMPV2CYHOL5D3Q7SM3U3IZWFANCNFSM5KJ5WOMQ&data=04|01|soleary%40venterra.com|c99cd31a26334e141abc08d9f075b549|e22aea6d0cf848038e12edaecd4fa3f2|0|0|637805210640660775|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D|3000&sdata=DrmAZj0Lu2%2BcHUyCV2wqDbcw5PbnZYam7VqdbsJMXss%3D&reserved=0. Triage notifications on the go with GitHub Mobile for iOShttps://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapps.apple.com%2Fapp%2Fapple-store%2Fid1477376905%3Fct%3Dnotification-email%26mt%3D8%26pt%3D524675&data=04|01|soleary%40venterra.com|c99cd31a26334e141abc08d9f075b549|e22aea6d0cf848038e12edaecd4fa3f2|0|0|637805210640660775|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D|3000&sdata=ST0RB4mG%2Bu3twW%2FRFXHNUKOI19f1cHNpG3vIBQlvkWA%3D&reserved=0 or Androidhttps://can01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.github.android%26referrer%3Dutm_campaign%253Dnotification-email%2526utm_medium%253Demail%2526utm_source%253Dgithub&data=04|01|soleary%40venterra.com|c99cd31a26334e141abc08d9f075b549|e22aea6d0cf848038e12edaecd4fa3f2|0|0|637805210640660775|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D|3000&sdata=yoEE6EiEjPvA1S3h5oRqWZQNNDMQvHmiHIUTKRx2dp8%3D&reserved=0. You are receiving this because you were mentioned.Message ID: @.***>

This email is from an external sender. DO NOT click links, open attachments, or provide sensitive information if the sender is unknown.

I would like to note, that this solution:

https://github.com/expo/expo/issues/15622#issuecomment-999609806

add expo_patch_react_imports! to ios/Podfile

Works perfectly

hi there! i am sorry that my workaround broke some EAS builds. so we rollbacked, fixed the issue and re-deployed today. please try again when you get a chance. for existing sdk 44 projects (both managed and bare), please make sure you upgrade the expo package to latest by yarn add expo@~44.0.3. the instruction is also updated. please try it and let us know if that works for you.

@schiller-manuel there’s an issue for react-native 0.66 integration and we fixed it in expo@44.0.3. however, we had a known issue from an optimization to exclude expo- prefixed directories. after renaming your repo from expo-issue to some-other-repo. it should work for you.

@jesuscovam that definitely helps. thanks a lot 🙏

Can anyone share a working snippet for using patch-package on eas build to fix amazon-cognito-identity-js?

I hope this helps https://youtu.be/Y_7ldOIP7So 🙇🏻‍♂️

hi there! as with #15626, nowadays we strictly require importing react headers with #import <React/*.h> form. however, amazon-cognito-identity-js still uses the old style imports there. i will create a pr for them. in the meantime, you could probably use patch-package for it.

patches/amazon-cognito-identity-js+5.2.3.patch

diff --git a/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h b/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
index a28e3c1..ab6fdce 100644
--- a/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
+++ b/node_modules/amazon-cognito-identity-js/ios/RNAWSCognito.h
@@ -1,20 +1,6 @@
-#if __has_include("RCTBridgeModule.h")
-#import "RCTBridgeModule.h"
-#else
#import <React/RCTBridgeModule.h>
-#endif
-
-#if __has_include("RCTLog.h")
-#import "RCTLog.h"
-#else
#import <React/RCTLog.h>
-#endif
-
-#if __has_include("RCTUtils.h")
-#import "RCTUtils.h"
-#else
#import <React/RCTUtils.h>
-#endif

#import "JKBigInteger.h"

thanks for reporting the issue to us.

patching the amazon-cognito-identity-js with patch-package works with EAS build Screen Shot 2021-12-19 at 15 25 45 Screen Shot 2021-12-19 at 15 26 43