Swift Package for Mozilla's Rust Components
This repository is a Swift Package for distributing releases of Mozilla's various Rust-based application components. It provides the Swift source code packaged in a format understood by the Swift package manager, and depends on a pre-compiled binary release of the underlying Rust code published from mozilla/application-services.
For more information, please consult:
- application-services ADR-0003, which describes the overall plan for distributing Rust-based components as Swift packages.
- The Swift Package Manager docs and GitHub repo, which explain the details of how Swift Packages work (and hence why this repo is set up the way it is).
- The
ios-rustcrate which is currently responsible for publishing the pre-builtMozillaRustComponents.xcframework.zipbundle on which this repository depends.
Overview
Here's a diagram of how this repository relates to the application-services repository and its release artifacts:
Key points:
- The
application-servicesrepo publishes a binary artifactMozillaRustComponents.xcframework.zipcontaining the Rust code and FFI definitions for all components, compiled together into a single library. - The
Package.swiftfile referencesMozillaRustComponents.xcframework.zipas a Swift binary target. - The
Package.swiftfile defines an individual module for the Swift wrapper code of each component.- Each module references its Swift source code directly as files in the repo.
- Each module depends on
MozillaRustComponentsWrapperwhich wrapsMozillaRustComponentsto provide the pre-compiled Rust code.
Cutting a new release
Whenever a new release of the underlying components is availble, we need to tag a new release in this repo to make them available to Swift components. To do so:
- Edit
Package.swiftto update the URL and checksum ofMozillaRustComponents.xcframework.zip. - Run
./make_tag.sh --as-version {APP_SERVICES_VERSION} X.Y.Zto create the new tag. - Run
git push origin X.Y.Zto publish it to GitHub.
Adding a new component
To add a new component to be distributed via this repo, you'll need to:
- Add its Rust code and
.hfiles to the build for theMozillaRustComponents.xcframework.zipbundle, following the docs for theios-rustcrate. - If the component needs to dynamically generate any Swift code (e.g. for UniFFI bindings, or Glean metrics), add logic for doing so to the
./generate.shscript in this repository.- Swift packages can't dynamically generate code at build time, so we use the
./generate.shscript to do it ahead-of-time when publishing a release.
- Swift packages can't dynamically generate code at build time, so we use the
- Edit
./Package.swiftto add the new component.- Add a new library product for the component under "products".
- Add a corresponding target for the component under "targets".
- Make sure it depends on "MozillaRustComponentsWrapper" to pull in the pre-compiled Rust code, as well as on any third-party Swift packages that it may require.
- Follow the instructions below to test it out locally.
That's it! The component will be included in the next release of this package.
Testing locally
Swift Packages can only be installed from a git repository, but luckily it is possible to use a local checkout for a git repository for local testing.
You may also need to follow the instructions for locally testing the ios-rust crate if you need to test changes in the underlying Rust code.
To test out some local changes to this repo:
- Make your changes in a local checkout and commit them.
- Make a new tag via
./make_tag.sh -f 0.0.1.- (You won't push this tag anywhere, but using a very low version number helps guard against any adverse consequences if it does accidentally escape your local machine).
- In a consuming application, delete the Swift Package dependency on
https://github.com/mozilla/rust-components-swiftand replace it with a dependency onfile:///path/to/your/local/checkout/rust-components-swiftat the0.0.release.
Testing against a local application-services checkout
To run against a local application services checkout, the make_tag.sh script supports setting a local path using a -l flag, for example:
./make_tag -l ../application-services 0.0.1
That's it! The consuming application should be able to import the package from your local checkout.