Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.59k stars 597 forks source link

Doesn't work with use_frameworks! / Include of non-modular header #1285

Open hrahul2605 opened 2 years ago

hrahul2605 commented 2 years ago

Facing error while setting up in iOS.

Tried, -> Allow Non-Modular includes in Framework Module to Yes

Versions

"react-native": "0.63.4",
"@nozbe/watermelondb": "^0.24.0",

Error

image

Podfile

source 'https://github.com/cocoapods/specs.git'
platform :ios, '10.0'
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
use_frameworks!

def firebase_pods
  pod 'Firebase/Core', '7.6.0'
  pod 'Firebase/RemoteConfig'
  pod 'Firebase/Analytics'
  pod 'Firebase/Crashlytics'
end

def payment_pods
  pod 'Stripe', '19.4.1'
  pod 'Frames', '3.2.0'
end

def common_pods
  pod 'ReachabilitySwift', '4.3.0'
  pod 'Alamofire', '4.7.3'
  pod 'SDWebImage', '5.0.6'
  pod 'SDWebImageWebPCoder'
  pod 'SwiftyBeaver', '1.8.2'
end

def notification_extension_pods
  pod 'WebEngageAppEx'
end

target 'ceres' do

   $static_framework = ['FlipperKit', 'Flipper', 'Flipper-Folly',
     'CocoaAsyncSocket', 'ComponentKit', 'Flipper-DoubleConversion',
     'Flipper-Glog', 'Flipper-PeerTalk', 'Flipper-RSocket',
     'CocoaLibEvent', 'OpenSSL-Universal', 'boost-for-react-native',
     'RNScreens']

   pre_install do |installer|
     Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
     installer.pod_targets.each do |pod|
         if $static_framework.include?(pod.name)
           def pod.build_type;
             Pod::BuildType.static_library
           end
         end
       end
   end
  pod 'SwiftyJSON', '4.2.0'
  pod 'GoogleAppIndexing', '2.0.3'
  pod 'ReSwift', '2.1.0'
  pod 'TTTAttributedLabel', '2.0.0'
  firebase_pods
  payment_pods
  common_pods
  pod 'GoogleAnalytics', '3.17.0' 
  pod 'GoogleMaps'
  pod 'KeychainAccess', '3.1.2'
  pod 'JTAppleCalendar', '7.1.6'
  pod 'LiveChat', '2.0.18'
  pod 'WebEngage'
  pod 'PhoneNumberKit', '3.2.0'
  pod 'FlagKit', '2.2'
  pod 'Down', '0.9.3'
  pod 'Branch', '0.37.0'

  # watermelondb
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi', :modular_headers => true
  pod 'simdjson', path: '../node_modules/@nozbe/simdjson'

  config = use_native_modules!
  use_react_native!(:path => config["reactNativePath"])
  use_flipper!({ 'Flipper-Folly' => '2.5.3', 'Flipper' => '0.87.0', 'Flipper-RSocket' => '1.3.1' })
  post_install do |installer|
    flipper_post_install(installer)
  end
end

target 'CeresNotificationServiceExtension' do
  common_pods
  notification_extension_pods
end

target 'CeresNotificationContentExtension' do
  common_pods
  notification_extension_pods
end

Error Log

<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/WatermelonDB-umbrella.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:9: note: in file included from /Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:
#import "Bridging.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/Bridging.h:2:9: error: include of non-modular header inside framework module 'WatermelonDB.Bridging': '/Users/rahul/workspace/proteus/node_modules/@nozbe/watermelondb/native/ios/WatermelonDB/FMDB/src/fmdb/FMDB.h'
#import "FMDB.h"
        ^
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/WatermelonDB-umbrella.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:9: note: in file included from /Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:
#import "Bridging.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/Bridging.h:10:9: error: include of non-modular header inside framework module 'WatermelonDB.Bridging': '/Users/rahul/workspace/proteus/node_modules/@nozbe/watermelondb/native/ios/WatermelonDB/JSIInstaller.h'
#import "JSIInstaller.h"
        ^
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/WatermelonDB-umbrella.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:9: note: in file included from /Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/WatermelonDB-umbrella.h:13:
#import "Bridging.h"
        ^
/Users/rahul/Library/Developer/Xcode/DerivedData/ceres-fzfftmpyfdjscwchoicxfplvzssd/Build/Products/Debug-iphonesimulator/WatermelonDB/WatermelonDB.framework/Headers/Bridging.h:16:9: error: include of non-modular header inside framework module 'WatermelonDB.Bridging': '/Users/rahul/workspace/proteus/node_modules/@nozbe/watermelondb/native/ios/WatermelonDB/DatabaseDeleteHelper.h'
#import "DatabaseDeleteHelper.h"
        ^
<unknown>:0: error: could not build Objective-C module 'WatermelonDB'
regalstreak commented 2 years ago

@radex do you have any context on this?

johnmikel commented 2 years ago

As a workaround, I run a ruby script that modifies the .podspec file of this library, changing the public headers from

/native/ios/WatermelonDB/SupportingFiles/Bridging.h/

to

native/ios/**/*.h

This ruby script is ran before doing pod install. Afterwards, proper public headers are exposed for a successful build.

regalstreak commented 2 years ago

@johnmikel Thank you! Will try and report back. I'm currently trying to remove use_frameworks to solve the issue and see if it works out.

regalstreak commented 2 years ago

Removing use_frameworks works for us!

use_modular_headers for independent dependencies wherever use_frameworks is needed

jadonhansen commented 2 years ago

Removing use_frameworks works for us!

use_modular_headers for independent dependencies wherever use_frameworks is needed

This worked for me as well. Thanks!

bharatkevadiya commented 2 years ago

Removing use_frameworks works for us!

use_modular_headers for independent dependencies wherever use_frameworks is needed

Yes, it will resolved this error for module, but then Xcode app build gives KeyChainHelper not in scope error.

can you suggest any solution for this?

SaltedBlowfish commented 2 years ago

@regalstreak

Removing use_frameworks works for us!

use_modular_headers for independent dependencies wherever use_frameworks is needed

I know it's been a while but can you add some context for your solution to this thread? (A code example, perhaps?) I'm running into the exact same issue and I'm sure others are as well. Thanks!

scob7 commented 2 years ago

Is there a way to make WatermelonDB work with use_frameworks?

I also have react-native-firebase for messaging in my app and it requires use_frameworks. See https://rnfirebase.io/#altering-cocoapods-to-use-frameworks

My preferred setup would be to use use_frameworks! :linkage => :static but then I get errors in iOS build for WatermelonDB.

fivecar commented 2 years ago

Update: The preferred, less complicated fix is now @johnf's below. Note that if you're using RN 0.71+, you'll also need to be on at least Watermelon v0.25.1+, in order to also fix #1469 .

= = = original post for nostalgia = = =

There's a way to get this all working with react-native-firebase and use_frameworks!. It took me a while, but here's how to do it (@scob7).

KrisLau commented 1 year ago

@fivecar I tried following your steps but i keep running into: image

fivecar commented 1 year ago

@fivecar I tried following your steps but i keep running into:

Sorry to hear that, @KrisLau . I unfortunately don't have any insight into what's causing your specific error. I can only report what worked for me — and it took hours to get it working, and I still don't fully have confidence it'll hold together.

KrisLau commented 1 year ago

@fivecar Makes sense that really blows but I appreciate you taking the time to get back to me, I'll comment over here if I manage to figure something out!

KrisLau commented 1 year ago

Ok so for anyone who might find themselves in a similar position, the difference for me is that I had an Expo workaround applied too so for the WatermelonDB.podspec file I had to change this:

s.public_header_files = [
  'native/ios/**/*.h',
  'native/ios/*/*.h',
]

Then I had to do step 1 & 2 only from the comment that @fivecar linked before: https://github.com/Nozbe/WatermelonDB/issues/1078#issuecomment-1286157927

Re run patch-package @nozbe/watermelondb

Cleaned the pod cache using pod cache clean --all, deleted the .xcworkspace folder, closed Xcode, pod update, reopened XCode. I had some other packages that caused issues as well but those were separate from this issue haha

Dallas62 commented 1 year ago

@radex you should take a look to this one if you find some times, I know there is a lot of work in other issues, but this one could block developers at installation step.

rhathas commented 1 year ago

Doesn't the all solutions here involves in modifing the node_packages? All issues are closed but does something prevents a PR?

johnf commented 1 year ago

This solution worked for me https://github.com/react-native-maps/react-native-maps/issues/3597#issuecomment-1168582636

$static_framework = [ 
    'WatermelonDB',
      'simdjson',
  ]
  pre_install do |installer|
    Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
      installer.pod_targets.each do |pod|
        if $static_framework.include?(pod.name)
          def pod.build_type;
          Pod::BuildType.static_library # >= 1.9
        end
      end
    end
  end
radex commented 1 year ago

@Dallas62 @KrisLau Can you confirm that @johnf's solution works for you? I'm not sure that putting everything in public_header_files is actually the correct solution to enabling 🍉 to work with use_frameworks (BTW: If you can, I highly recommend that you DO NOT use use_frameworks - in most cases, it's unnecessary and detrimental to startup performance)

Dallas62 commented 1 year ago

Unfortunately, rnfirebase doesn't allow us to remove use_frameworks.

For the public_header_files I agree with you, I will make a list of required header in the next few days.

For the solution of @johnf, I not a big fan since it's a workaround to make every things work together. It doesn't work without this step in the Podfile.

KrisLau commented 1 year ago

@radex I'll give it a test whenever I finish up my current feature and will update here. However, it seems more like a workaround. Would it not be better to have WatermelonDB work both with and without use_frameworks! since react-native-firebase is a widely used library and will not remove the use_frameworks! requirement in the foreseeable future?

radex commented 1 year ago

Yes, of course. I'm all for making 🍉 work with use_frameworks!, it's just that I think public_header_files = everything is a workaround, not the right fix, since internal headers shouldn't be needed for the user app. I'm very much interested in PRs fixing this once and for all

KrisLau commented 1 year ago

@radex Makes sense! I'm not quite sure what a permanent fix would be then since I have no experience with podspec files. If there are any ideas you or anyone else in the thread might have, I will try to test them out on my personal files and see if anything sticks. I'll also look into some ideas on my own

fivecar commented 1 year ago

@johnf's fix works for me as well, and I verified by backing out my recommended changes, deleting node_modules and ios/Pods, and rebuilding everything. In my case, I had moved to RN 0.71, so also needed to upgrade to Watermelon v0.25.1 (see #1469).

I've edited my original comment above to now recommend @johnf's fix instead. Thank you all!

radex commented 1 year ago

@fivecar @KrisLau @Dallas62 @johnf Hi, check out 0.26.0-1 prerelease, I think Watermelon should work there in the use_frameworks! mode. Please note that you should now delete the Bridging.h import from your Bridging header.

Please do confirm/deny if this works for you

Dallas62 commented 1 year ago

Hi @radex, The v0.26.0-1 partially solve some imports since Bridging.h is not imported. But for simdjson.h still got an issue.

image

Copy and paste simdjson.h into shared folder solve the issue, but not the optimal solution.

radex commented 1 year ago

@Dallas62 can you show your Podfile? Also, which RN version?

Dallas62 commented 1 year ago
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '12.4'
install! 'cocoapods', :deterministic_uuids => false

$RNFirebaseAnalyticsWithoutAdIdSupport = true
$RNFirebaseAsStaticFramework = true

target 'Monstera' do
  config = use_native_modules!

  # 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.
    # Upcoming versions of React Native may rely on get_default_flags(), but
    # we make it explicit here to aid in the React Native upgrade process.
    :hermes_enabled => false,
    :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 => FlipperConfiguration.disabled,
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  use_frameworks! :linkage => :static

  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi', :modular_headers => true
  pod 'simdjson', path: '../node_modules/@nozbe/simdjson'

  post_install do |installer|
    react_native_post_install(
      installer,
      # Set `mac_catalyst_enabled` to `true` in order to apply patches
      # necessary for Mac Catalyst builds
      :mac_catalyst_enabled => false
    )

    __apply_Xcode_12_5_M1_post_install_workaround(installer)

    installer.generated_projects.each do |project|
        project.targets.each do |target|
            target.build_configurations.each do |config|
                config.build_settings["DEVELOPMENT_TEAM"] = "*******"
             end
        end
    end
  end
end

RN v0.70.6

Dallas62 commented 1 year ago

Also got an issue, even with a full clean of cache, node_modules and ios/Pods but still here.

error: Error: While trying to resolve module `@nozbe/watermelondb` from file `/Users/***/Projects/***/database/repository/my-repository.js`, the package `/Users/***/Projects/***/node_modules/@nozbe/watermelondb/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/***/Projects/***/node_modules/@nozbe/watermelondb/index`. Indeed, none of these files exist:

  * /Users/***/Projects/***/node_modules/@nozbe/watermelondb/index(.native|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)
  * /Users/***/Projects/***/node_modules/@nozbe/watermelondb/index/index(.native|.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)

In the previous version, didn't see difference on package.json, might be related to babel or metro configuration.

radex commented 1 year ago

Okay, I can reproduce the simdjson issue

radex commented 1 year ago

@fivecar @KrisLau @Dallas62 @johnf Hi, check out 0.26.0-2 prerelease. Two extra steps need to be done:

I tested on this demo project (RN 0.71) to confirm that it really works: https://github.com/radex/WatermelonDB_tester

Before I checked on 🍉's internal project where due to different project structure the simdjson issue didn't occur

Dallas62 commented 1 year ago

Hi @radex,

Thanks for your quick feedback ! ✅ Build is now working fine with changes

Only the import which is failling now : https://github.com/Nozbe/WatermelonDB/issues/1285#issuecomment-1405828888 Will take a look later on the exemple project to see if there is differences.

Dallas62 commented 1 year ago

Found the issue, since it's a dependency from github, the library isn't builded. I have run yarn run build and replaced the content of the @nozbe/watermelondb with the one in @nozbe/watermelondb/dist, it's working fine.

radex commented 1 year ago

@Dallas62 Hmm, you put GitHub path in package.json? If you used 0.26.0-2, this should just work

KrisLau commented 1 year ago

Sorry for the late response, I was trying to make a logical commit before testing! I'm on RN 0.70.6 because 0.71 has compatibility issues with some other packages in my project. Tested on iOS (testing Android later cause build time is crazy) and it works great however it seems like I'm getting a bunch of new errors whenever I close and relaunch the app:

Record table#uuid-12345 is cached, but full raw object was sent over the bridge

I need to do a full pull of all records related to the user every time they reopen the app just in case there's any unsynced data that may have gotten missed. I also do the same thing when the user is added to a new team to sync up all data for that new team (which would be before the lastPulledAt timestamp).

radex commented 1 year ago

@KrisLau I’ll fix it, but it’s just a warning and it’s safe to ignore. I just want to know if this version compiled without workarounds in the use_frameworks. If you use an older RN version and/or Expo, that’s even better. And if some workarounds are still needed, let me know which ones

KrisLau commented 1 year ago

@radex I do use Expo (bare workflow) and the new update does not seem to break any of the expo packages I use:


I didn't need any other workarounds but I didn't delete the Bridging Header, just cleared the text leaving just the comment. Also, to match the other line that WatermelonDB uses in the Podfile from the original installation steps I used :modular_headers => true instead of the modular_headers: true for simdjson change you commented. So my Podfile has these lines:

# NOTE: Do not remove, needed to keep WatermelonDB compiling:
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi', :modular_headers => true

# NOTE: This is required as of v0.23
pod 'simdjson', path: '../node_modules/@nozbe/simdjson', :modular_headers => true

Not sure if it matters at all but just thought i'd mention it in case.

Almost forgot to mention but I had changes I made for react-native-firebase when I added the use_frameworks!. This is from their docs (ignore Hermes part - it's fixed) but if anyone else plans to use use_frameworks! they would need to comment out the:flipper_configuration line completely since it doesn't play nice with flipper yet. For it to work with Hermes, the linkage has to be static like this:

use_frameworks! :linkage => :static

It also doesn't work with the new architecture yet.. Might be worth adding that to the documentation as a warning for anyone using use_frameworks! whenever this release comes out.


I’ll fix it, but it’s just a warning and it’s safe to ignore.

Okie sounds good! It would be nice to be able to turn it off since it logs hundreds of those warnings for me since it is logging it for individual records haha. Using LogBox.ignoreLogs for now 😆

Thanks for the awesome work again, I really enjoy the package!

KrisLau commented 1 year ago

@radex Updated my comment above with more info on my environment and setup.

Also just tested Android and it seems to be working but I'm not sure why the warning:

The writer you're trying to run (sync-synchronize-apply) can't be performed yet, because there are 1 other readers/writers in the queue.

only shows up for Android. The writer and readers are running fine tho

radex commented 1 year ago

Sorry, I had to temporarily revert the fix, because it causes some new issues in some other configurations (possibly related to Expo and interactions with RN66)…

Forcing WatermelonDB to build as a static library as per https://github.com/Nozbe/WatermelonDB/issues/1285#issuecomment-1381323060 is currently the official/recommended way of dealing with this issue :)

I do have another idea for a much more reliable, long-term fix, but it will take me more time to develop.

rafaellupo commented 1 year ago

Hey guys I've forked @morrowdigital/watermelondb-expo-plugin and added support for useFrameworks by adding @johnf solution, which @radex stated as currently recommended fix. Here it is: (Tested against SDK48) @rafaellupo/watermelondb-firebase-expo-plugin

Disclaimer: I don't pretend to be updating this plugin, it's only a handy thing I did to help a little while the definitive solution doesn't show up.

jakehasler commented 1 year ago

@rafaellupo wow, thanks so much. I'm still on Managed Expo and I've just been reading through this thread starting to fret reverting to bare. I installed your plugin and swapped it out in my app.js and it worked like a charm. Appreciate you making that 👍

3210jr commented 1 year ago

@johnf Thanks for the solution and linking to the source of it! Literally spent tens of hours trying to figure it out, your solution is what ended up working for me.

radex commented 1 year ago

Hey, can y'all try out the latest 0.27.0-1 pre-release version? It contains changes that hopefully should fix use_frameworks/Expo/other integration issues once and for all

KrisLau commented 1 year ago

@radex Can do! Would we still need to force WatermelonDB to build as a static library as per https://github.com/Nozbe/WatermelonDB/issues/1285#issuecomment-1381323060?

radex commented 1 year ago

@KrisLau No. You can if you want to, but it should work perfectly fine as a dynamic framework

KrisLau commented 1 year ago

@radex Tested it without the static workaround and it seems to work great!