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-rust
crate which is currently responsible for publishing the pre-builtMozillaRustComponents.xcframework.zip
bundle on which this repository depends.
Here's a diagram of how this repository relates to the application-services repository and its release artifacts:
Key points:
- The
application-services
repo publishes a binary artifactMozillaRustComponents.xcframework.zip
containing the Rust code and FFI definitions for all components, compiled together into a single library. - The
Package.swift
file referencesMozillaRustComponents.xcframework.zip
as a Swift binary target. - The
Package.swift
file 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
MozillaRustComponentsWrapper
which wrapsMozillaRustComponents
to provide the pre-compiled Rust code.
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.swift
to update the URL and checksum ofMozillaRustComponents.xcframework.zip
. - Run
./make_tag.sh --as-version {APP_SERVICES_VERSION} X.Y.Z
to create the new tag. - Run
git push origin X.Y.Z
to publish it to GitHub.
To add a new component to be distributed via this repo, you'll need to:
- Add its Rust code and
.h
files to the build for theMozillaRustComponents.xcframework.zip
bundle, following the docs for theios-rust
crate. - 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.sh
script in this repository.- Swift packages can't dynamically generate code at build time, so we use the
./generate.sh
script 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.swift
to 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.
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-swift
and replace it with a dependency onfile:///path/to/your/local/checkout/rust-components-swift
at the0.0.
release.
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.