-
Notifications
You must be signed in to change notification settings - Fork 271
Add a relatively simple way to compile and generate Swift bindings. #1647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7fa2515
d080333
9f7fa5b
b28fe4b
6abdfca
baf1810
4761d6c
062e7db
7ceca5a
4c87075
e7b95c6
8e6f413
7386c6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,85 @@ | ||||
# Rust project as individual iOS framework | ||||
|
||||
Wrap the Rust crate into an iOS Framework, allowing separate modifications to the related Rust code and UniFFI-generated program configurations for easier integration management and usage in the future. | ||||
|
||||
Overall, you need: | ||||
|
||||
1. Generate an Xcode project file for the Rust crate and compile it into a static library. | ||||
2. Create a new iOS Framework project and import the generated target dependencies. | ||||
3. Compile UDL file to generate related Swift bindings. | ||||
4. Import the generated binding header file into the public header files of the Framework. | ||||
|
||||
## Compile Rust crate using `cargo-xcode` | ||||
|
||||
First, you need to install `cargo-xcode`. This tool generates Xcode project files to compile your | ||||
Rust porject into a static library. | ||||
|
||||
``` | ||||
cargo install cargo-xcode | ||||
``` | ||||
|
||||
We need to modify the `Cargo.toml` file and add crate-type = ["lib", "staticlib"] in the [lib] section. Here you can add other types according to your needs, but only `staticlib` and `cdylib` can be recognized by `cargo-xcode`. | ||||
|
||||
To generate the project run: | ||||
|
||||
``` | ||||
cargo xcode | ||||
``` | ||||
|
||||
This will generate a `<rust-project-name>.xcodeproj` file. | ||||
|
||||
## Create a Framework and add dependencies | ||||
|
||||
* Create a new iOS Framework project and drag the `<rust-project-name>.xcodeproj` mentioned above into it. | ||||
* Add `<rust-project-name>-staticlib` to `Build Phases - Target Dependencies` in the iOS Framework. | ||||
* Add `lib<rust-project-name>_static.a` to the `Link Binary With Libraries` in your iOS Framework project. | ||||
|
||||
## Generate bindings | ||||
|
||||
In the iOS Framework's `Build Rules`, add a `Run Script` to handle `*.udl` and generate the corresponding bindings. | ||||
|
||||
* Add a build rule processing files with names matching `*.udl`. | ||||
* Use something like the following as the custom script: | ||||
* `$HOME/.cargo/bin/uniffi-bindgen-cli generate $INPUT_FILE_PATH --language swift --out-dir $INPUT_FILE_DIR/Generated` | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't ship this CLI anymore. See https://mozilla.github.io/uniffi-rs/tutorial/foreign_language_bindings.html There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but this binary won't be installed into |
||||
* Add both the Swift file and the generated bridging header as output files: | ||||
* `$(INPUT_FILE_DIR)/Generated/$(INPUT_FILE_BASE).swift` | ||||
* `$(INPUT_FILE_DIR)/Generated/$(INPUT_FILE_BASE)FFI.h` | ||||
|
||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
* Add your `.udl` file to the `Compile Sources` build phase for your framework, so that Xcode will process it using the new build rule and will include the resulting outputs in the build. | ||||
|
||||
You do not need to add the generated Swift code to the list of `Compile Sources` and should not attempt to compile it explicitly; Xcode will figure out what it needs to do with this code based on it being generated from the Build Rule for your `.udl` file. | ||||
|
||||
## Import header files | ||||
|
||||
Import the generated header file in `<framework-name>.h` of iOS Framework. | ||||
|
||||
```c | ||||
#import <Foundation/Foundation.h> | ||||
|
||||
//! Project version number for <framework-name>. | ||||
FOUNDATION_EXPORT double <framework-name>VersionNumber; | ||||
|
||||
//! Project version string for <framework-name>. | ||||
FOUNDATION_EXPORT const unsigned char <framework-name>VersionString[]; | ||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <framework-name>/PublicHeader.h> | ||||
|
||||
#import "Generated/<rust-project-name>FFI.h" | ||||
``` | ||||
|
||||
As a last step add the generated header file as a Public header in the "Headers" build phase of your project. | ||||
|
||||
## Use the framework in an application | ||||
|
||||
After completing the above steps, you can now use your Framework by dragging it into your project and importing `<framework-name>`. | ||||
|
||||
It also provides an [ios-with-framework](examples/app/ios-with-framework/) that you can check out under examples/app/ios-with-framework/. | ||||
|
||||
* `ios-with-framework`: Root directory of the sample project | ||||
|
||||
* `iOS-UniFFI-Framework`: Includes handling of compiling Rust crates into static libraries and generating bindings. | ||||
* `iOS-UniFFI-App`: Includes the use of the generated framework. | ||||
Comment on lines
+76
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The project does not build as is for me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it's caused by the inability to invoke There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I actually fixed that. |
||||
|
||||
## Known issues | ||||
|
||||
* If you encounter an error when generating bindings, please check if `uniffi-bindgen-cli` is installed. If the path is incorrect, please modify the script path in `Build Rules`. | ||||
Comment on lines
+83
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above we don't ship that CLI anymore as is. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your suggestion, I am reviewing the relevant changes. I have found some issues with the description here.
staticlib
andcdylib
correspond to*.a
and*.dylib
libraries respectively. Thestaticlib
in thecrate-type
section does not match the describedcdylib
on documentation, so it needs to be modified.Details:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops, yes. That should of course be the same in text and code.