Part 4: macOS specific instructions
FRB Template App: Applying the modified Workflow.
macOS steps
Generate the Dart Interface
Our next task is to create the generated code. This will also copy the C header file bridge_generated.h
into the folder macos/Runner/. Use this command (you need to be in the root of your project):
flutter_rust_bridge_codegen \
--rust-input rust/src/api.rs \
--dart-output ./lib/bridge_generated.dart \
--dart-decl-output ./lib/bridge_definitions.dart \
--c-output macos/Runner/bridge_generated.h
Create the subproject
How is a subproject created in Xcode?
Simply open the macos/Runner.xcodeproj in Xcode, open the rust/ directory in Finder and drag the rust.xcodeproj into the Runner folder. The next images will illustrate the steps.
Adjust the Runner Target's Build Phases
For macOS, FRB recommends to include the dynamic library.
a) In Runner Target's Build Phase -> Target Dependencies:
Click on "+" and select rust-cdylib
.
b) In Runner Target's Build Phase -> Link Binary with Libraries:
Click on "+" and select rust.dylib
.
Adjust the Runner Target's Build Settings
Start typing "Objective-C Bridging Header" in the filter... the hard-to-find setting is in the Swift Compiler - General section of the settings.
As value, insert:
Runner/bridge_generated.h
Adjust Minimum Deployments
To ensure that your app can run on your host computer and Xcode version, you may only be able to support newer macOS versions. To set the minimum supported macOS version for your app, go to the General tab and select macOS version 13.1
as the Minimum Deployments target.
Adjust the AppDelegate.swift
file
Switch to Visual Studio Code and open the file macos/Runner/AppDelegate.swift
. We need to call the function dummy_method_to_enforce_bundling() (from FRB) somewhere to avoid that Xcode handles our library as dead code.
Add:
dummy_method_to_enforce_bundling()
Your file should look like:
import Cocoa
import FlutterMacOS
@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
dummy_method_to_enforce_bundling()
return true
}
}
Just for your information
When it comes to building the libraries, you might be curious about the process. When you use the cargo-xcode
command to create the Rust Xcode project, it also installs build rules. These build rules tell Xcode how to create the libraries during the build process. So, when Xcode builds the application, it first builds the subproject and then follows the build rules to create the necessary libraries.
Look twice! It's not the target of the Runner Project, but the target of the Rust subproject!
Problem: Flutter doesn't find the dynamic library
When you have installed the version 1.5.0 from cargo-xcode
(as you can see in the Build rules image above), Flutter will not be able to find the dynamic library. You'll get an error like this:
Launching lib/main.dart on macOS in debug mode...
--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:00008103-001251441A62001E }
{ platform:macOS, arch:x86_64, id:00008103-001251441A62001E }
Building macOS application...
dyld[64001]: Library not loaded: /usr/local/lib/rust.dylib
Referenced from: <29A02B41-EAF9-315B-977F-429B4DD80404> /Users/kaimueller/Documents/iota_for_flutter/example2/build/macos/Build/Products/Debug/example2.app/Contents/MacOS/example2
Reason: tried: '/usr/local/lib/rust.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/rust.dylib' (no such file), '/usr/local/lib/rust.dylib' (no such file), '/usr/lib/rust.dylib' (no such file, not in dyld cache)
Error waiting for a debug connection: The log reader stopped unexpectedly, or never started.
Error launching application on macOS.
To find out the version of cargo-xcode, you can run the command
cargo install --list
to list all installed Cargo subcommands along with their versions.
Solution 1
Here's a first solution:
- In VS Code, open file rust/rust.xcodeproj/project.pbxproj.
- Search for the 2 lines with the text
CARGO_XCODE_FEATURES = "";
- Insert a new line after each of these lines and insert
DYLIB_INSTALL_NAME_BASE = "$(TARGET_BUILD_DIR)";
Solution 2
After completing this chapter, another solution emerged.
The alternative solution is outlined in the tutorial's chapter titled Building a Simple App, see Building for macOS.