fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.29k stars 301 forks source link

iOS Failed to load dynamic library 'tms_infra.framework/tms_infra' #2347

Closed CJBuchel closed 2 weeks ago

CJBuchel commented 1 month ago

Describe the bug

I'm fairly certain this issue is related to my project not being setup correctly for iOS but I can't find much information on setting up for an iOS app using FRB with a rust library.

For context, I have a Flutter app project which compiles to Android, Web and iOS. And I have a rust library that just holds structures and a small amount of logic for those structures.

For iOS I used FRB to generate the dart code, then I switched out the crate-type from cdylib to static lib. crate-type = ["rlib", "staticlib"]

I compile using cargo lipo --release --targets aarch64-apple-ios-sim x86_64-apple-ios and I place the generated universal static binary litms_infra.a inside my iOS/Runner directory.

I've also modified my pod file to search and link this binary

ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    # remove microphone permission (not needed for this app)
    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        'AUDIO_SESSION_MICROPHONE=0'
      ]
      actual_project_dir = File.expand_path('..', __FILE__) # Adjust this if needed
      config.build_settings['LIBRARY_SEARCH_PATHS'] ||= ["#{actual_project_dir}/Runner"]
      config.build_settings['OTHER_LDFLAGS'] ||= ['-ltms_infra', '-lc++']
    end
  end
  puts "Library Search Paths: #{installer.pods_project.targets.map { |t| t.build_configurations.map { |c| c.build_settings['LIBRARY_SEARCH_PATHS'] } }}"
  # signing config
  installer.pods_project.build_configurations.each do |config|
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
  end
end

Likewise in the xcworkspace opened in Xcode, I've added the libtms_infra.a as a library to be linked in the build phase for Runner.

When doing this, it seems to compile. But when running the simulator I get the runtime error, and the app just displays white.

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to load dynamic library 'tms_infra.framework/tms_infra': dlopen(tms_infra.framework/tms_infra, 0x0001)

I'm not particularly sure why this is occurring. I'm not the biggest iOS developer so I'm unsure why it's trying to get a tms_infra.framework file, or where this file would even be created. Or even why it's trying to link against it. From a small amount of reading, it seems like a dynamic library it's trying to load, which is confusing to me. Because everything I've done I have thought is static.

I have found parts of the FRB documentation that specifies the setup for an iOS project, but I'm not really sure if it applies to me or not, as one seems to be for a pure dart library (not an app) https://cjycode.com/flutter_rust_bridge/manual/integrate/library/platform-setup/ios-and-macos

And the other seems focused on crating a crate xcodeproj https://cjycode.com/flutter_rust_bridge/manual/integrate/existing/ios

So I haven't specifically tried those methods out. I wanted to check if there was a specific method/documentation for actually setting up a flutter app integrating a rust binary from FRB. Or what my issue might be related to?

Steps to reproduce

Hint: Clone https://github.com/CJBuchel/TMS

  1. Build tms-infra crate for static lib aarch64-apple-ios-sim
  2. Place binary in tms-client/iOS/Runner
  3. Build & Sim Flutter App

Logs

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to load dynamic library 'tms_infra.framework/tms_infra': dlopen(tms_infra.framework/tms_infra, 0x0001): tried: '/Users/connorbuchel/Library/Developer/Xcode/DerivedData/Runner-cewwfhxtxlskcaewhdbokzqbujec/Build/Products/Debug-iphonesimulator/tms_infra.framework/tms_infra' (no such file), '/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoottms_infra.framework/tms_infra' (no such file), '/Users/connorbuchel/Library/Developer/CoreSimulator/Devices/A0EDAE9A-BC44-492C-AF2C-D9D19400203A/data/Containers/Bundle/Application/DBFE7429-D06B-4AED-B9A5-EA0A28178632/Runner.app/tms_infra.framework/tms_infra' (no such file), '/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/tms_infra.framework/tms_infra' (no such file), '/usr/lib/swift/tms_infra.framework/tms_infra' (no such file, not in dyld cache), '/Users/connorbuchel/Library/Developer/CoreSimulator/Devices/A0EDAE9A-BC44-492C-AF2C-D9D19400203A/data/Containers/Bundle/Application/DBFE7429-D06B-4AED-B9A5-EA0A28178632/Runner.app/Frameworks/tms_infra.framework/tms_infra' (no such file), '/Users/connorbuchel/Library/Developer/CoreSimulator/Devices/A0EDAE9A-BC44-492C-AF2C-D9D19400203A/data/Containers/Bundle/Application/DBFE7429-D06B-4AED-B9A5-EA0A28178632/Runner.app/Frameworks/tms_infra.framework/tms_infra' (no such file), '/usr/lib/tms_infra.framework/tms_infra' (no such file, not in dyld cache), 'tms_infra.framework/tms_infra' (no such file), '/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/tms_infra.framework/tms_infra' (no such file)
#0      _open (dart:ffi-patch/ffi_dynamic_library_patch.dart:11:43)
#1      new DynamicLibrary.open (dart:ffi-patch/ffi_dynamic_library_patch.dart:22:12)
#2      new ExternalLibrary.open (package:flutter_rust_bridge/src/platform_types/_io.dart:42:47)
#3      loadExternalLibraryRaw.<anonymous closure>.<anonymous closure> (package:flutter_rust_bridge/src/loader/_io.dart:72:29)
#4      _tryOpen (package:flutter_rust_bridge/src/loader/_io.dart:93:20)
#5      loadExternalLibraryRaw.<anonymous closure> (package:flutter_rust_bridge/src/loader/_io.dart:68:22)
#6      loadExternalLibraryRaw.tryAssumingNonPackaged (package:flutter_rust_bridge/src/loader/_io.dart:49:22)
#7      loadExternalLibraryRaw (package:flutter_rust_bridge/src/loader/_io.dart:66:12)
#8      loadExternalLibrary (package:flutter_rust_bridge/src/loader/_io.dart:14:10)
#9      BaseEntrypoint._loadDefaultExternalLibrary (package:flutter_rust_bridge/src/main_components/entrypoint.dart:129:13)
#10     BaseEntrypoint.initImpl (package:flutter_rust_bridge/src/main_components/entrypoint.dart:48:31)
#11     TmsRustLib.init (package:tms/generated/frb_generated.dart:72:20)
#12     main (package:tms/main.dart:42:20)
#13     _runMain.<anonymous closure> (dart:ui/hooks.dart:301:23)
#14     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#15     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Expected behavior

No response

Generated binding code

No response

OS

No response

Version of flutter_rust_bridge_codegen

2.1.0

Flutter info

No response

Version of clang++

No response

Additional context

No response

fzyzcjy commented 1 month ago

Hi, could you please try frb v2's default approach (use cargokit) and see whether it works?

CJBuchel commented 1 month ago

I'm not completely familiar with cargokit, but I'll try hunt down the documentation for it and try it's approach.

fzyzcjy commented 1 month ago

If you use v2, you do not need to setup anything about compilation. Just run the commands in https://cjycode.com/flutter_rust_bridge/quickstart.

fzyzcjy commented 2 weeks ago

Close since this seems to be solved, but feel free to reopen if you have any questions!

github-actions[bot] commented 3 days ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.