Skip to content

Commit f803922

Browse files
committed
Initial Swift Package infra for Rust Components.
Consult README.md for details of what we're up to here.
0 parents  commit f803922

23 files changed

+3904
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
.build
3+
.swiftpm
4+
Package.resolved
5+
6+
# From the Glean sdk generator
7+
.venv

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "external/application-services"]
2+
path = external/application-services
3+
url = https://github.com/mozilla/application-services

CODE_OF_CONDUCT.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Community Participation Guidelines
2+
3+
This repository is governed by Mozilla's code of conduct and etiquette guidelines.
4+
For more details, please read the
5+
[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/).
6+
7+
## How to Report
8+
For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.

LICENSE

Lines changed: 373 additions & 0 deletions
Large diffs are not rendered by default.

Package.swift

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// swift-tools-version:5.4
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "MozillaRustComponentsSwift",
6+
platforms: [.iOS(.v11)],
7+
products: [
8+
.library(name: "RustLog", targets: ["RustLog"]),
9+
.library(name: "Viaduct", targets: ["Viaduct"]),
10+
.library(name: "Nimbus", targets: ["Nimbus"]),
11+
.library(name: "CrashTest", targets: ["CrashTest"]),
12+
// TODO: more of our components here, once they support M1 builds.
13+
//.library(name: "Logins", targets: ["Logins"]),
14+
//.library(name: "FxAClient", targets: ["FxAClient"]),
15+
],
16+
dependencies: [
17+
// TODO: ship Glean via this same bundle?
18+
.package(name: "Glean", url: "https://github.com/mozilla/glean-swift", from: "39.0.4"),
19+
// TODO: this external dependency is required for FxAClient,
20+
// leaving it here as an example for now.
21+
//.package(name: "SwiftKeychainWrapper", url: "https://github.com/jrendel/SwiftKeychainWrapper", from: "4.0.1")
22+
],
23+
targets: [
24+
.target(
25+
name: "Sync15",
26+
path: "external/application-services/components/sync15/ios"
27+
),
28+
.target(
29+
name: "RustLog",
30+
dependencies: ["MozillaRustComponents"],
31+
path: "external/application-services/components/rc_log/ios"
32+
),
33+
.target(
34+
name: "Viaduct",
35+
dependencies: ["MozillaRustComponents"],
36+
path: "external/application-services/components/viaduct/ios"
37+
),
38+
.target(
39+
name: "Nimbus",
40+
dependencies: ["MozillaRustComponents", "Glean"],
41+
path: "generated/nimbus"
42+
),
43+
.target(
44+
name: "CrashTest",
45+
dependencies: ["MozillaRustComponents"],
46+
path: "generated/crashtest"
47+
),
48+
// TODO: other components will go here over time.
49+
//.target(
50+
// name: "Logins",
51+
// dependencies: ["MozillaRustComponents", "Sync15"],
52+
// path: "external/application-services/components/logins/ios"
53+
//),
54+
//.target(
55+
// name: "FxAClient",
56+
// dependencies: ["MozillaRustComponents", "SwiftKeychainWrapper"],
57+
// path: "external/application-services/components/fxa-client/ios"
58+
//),
59+
.binaryTarget(
60+
name: "MozillaRustComponents",
61+
//
62+
// For release artifacts, reference the MozillaRustComponents as a URL with checksum.
63+
//
64+
url: "https://111955-129966583-gh.circle-artifacts.com/0/dist/MozillaRustComponents.xcframework.zip",
65+
checksum: "f6807476ab4dd850290f4f87850719dfb9601deaee42b202ff8860480bdf1a42"
66+
//
67+
// For local testing, you can point at an (unzipped) XCFramework that's part of the repo.
68+
// Note that you have to actually check it in and make a tag for it to work correctly.
69+
//
70+
//path: "./MozillaRustComponents.xcframework"
71+
)
72+
]
73+
)

README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Swift Package for Mozilla's Rust Components
2+
3+
This repository is a Swift Package for distributing releases of Mozilla's various
4+
Rust-based application components. It provides the Swift source code packaged in
5+
a format understood by the Swift package manager, and depends on a pre-compiled
6+
binary release of the underlying Rust code published from [mozilla/application-services](
7+
https://github.com/mozilla/application-service).
8+
9+
For more information, please consult:
10+
11+
* [application-services ADR-0003](https://github.com/mozilla/application-services/blob/main/docs/adr/0003-swift-packaging.md),
12+
which describes the overall plan for distributing Rust-based components as Swift packages.
13+
* The [Swift Package Manager docs](https://swift.org/package-manager/) and [GitHub repo](https://github.com/apple/swift-package-manager),
14+
which explain the details of how Swift Packages work (and hence why this repo is set up the way it is).
15+
* The [`ios-rust` crate](https://github.com/mozilla/application-services/tree/main/megazords/ios) which is currently
16+
responsible for publishing the pre-built `MozillaRustComponents.xcframework.zip` bundle on which this
17+
repository depends.
18+
19+
## Overview
20+
21+
Here's a diagram of how this repository relates to the application-services repository
22+
and its release artifacts:
23+
24+
<!--
25+
N.B. you can edit this image in Google Docs and changes will be reflected automatically:
26+
27+
https://docs.google.com/drawings/d/1tX05I-e6hNBQxch7PescDH7k4G7ddAJwXDPoIqp1RYk/edit
28+
-->
29+
<img src="https://docs.google.com/drawings/d/e/2PACX-1vRnyxy7VjdD3bYTso8V3AL5FpIQ4_S54dOCDI6fxfZEbG3_CVBwZZP1uLYbUVE9M54GSXUkNgewzOQm/pub?w=720&h=540" width="720" height="540" alt="A box diagram describing how the rust-components-swift repo, applicaiton-services repo, and MozillaRustComponents XCFramework interact">
30+
31+
Key points:
32+
33+
* The `rust-components-swift` repo includes the `application-services` repo as a git submodule.
34+
* The `application-services` repo publishes a binary artifact `MozillaRustComponents.xcframework.zip` containing
35+
the Rust code and FFI definitions for all components, compiled together into a single library.
36+
* The `Package.swift` file references `MozillaRustComponents.xcframework.zip` as a Swift binary target.
37+
* The `Package.swift` file defines an individual module for the Swift wrapper code of each component.
38+
* Each module references its Swift source code directly as files in the repo.
39+
* Each module depends on `MozillaRustComponents` to provide the pre-compiled Rust code.
40+
41+
## Cutting a new release
42+
43+
Whenever a new release of the underlying components is availble, we need to tag a new release
44+
in this repo to make them available to Swift components. To do so:
45+
46+
* Update the git submodule under `./external` to the new release of the underlying components.
47+
* Edit `Package.swift` to update the URL and checksum of `MozillaRustComponents.xcframework.zip`.
48+
* Run `./make_tag.sh X.Y.Z` to create the new tag.
49+
* Run `git push origin X.Y.Z` to publish it to GitHub.
50+
51+
## Adding a new component
52+
53+
To add a new component to be distributed via this repo, you'll need to:
54+
55+
* Add its Rust code and `.h` files to the build for the `MozillaRustComponents.xcframework.zip` bundle,
56+
following the docs for the [`ios-rust` crate](https://github.com/mozilla/application-services/tree/main/megazords/ios).
57+
* Add the source for the component to this repository as a git submodule under `./external`.
58+
* If the component needs to dynamically generate any Swift code (e.g. for UniFFI bindings, or Glean metrics),
59+
add logic for doing so to the `./generate.sh` script in this repository.
60+
* Swift packages can't dynamically generate code at build time, so we use the `./generate.sh` script
61+
to do it ahead-of-time when publishing a release.
62+
* Edit `./Package.swift` to add the new component.
63+
* Add a new library product for the component under "products".
64+
* Add a corresponding target for the component under "targets".
65+
* Make sure it depends on "MozillaRustComponents" to pull in the pre-compiled Rust code,
66+
as well as on any third-party Swift packages that it may require.
67+
* Follow the instructions below to test it out locally.
68+
69+
That's it! The component will be included in the next release of this package.
70+
71+
## Testing locally
72+
73+
Swift Packages can only be installed from a git repository, but luckily it is possible to use a
74+
local checkout for a git repository for local testing.
75+
76+
You may also need to follow the instructions for [locally testing the `ios-rust` crate](
77+
https://github.com/mozilla/application-services/blob/f3228cf1295154d144be64fc0945c9b3e93a07de/megazords/ios-rust/README.md#testing-locally)
78+
if you need to test changes in the underlying Rust code.
79+
80+
To test out some local changes to this repo:
81+
82+
* Make your changes in a local checkout and commit them.
83+
* Make a new tag via `./make_tag.sh -f 0.0.1`.
84+
* (You won't push this tag anywhere, but using a very low version number helps guard against
85+
any adverse consequences if it does accidentally escape your local machine).
86+
* In a consuming application, delete the Swift Package dependency on `https://github.com/mozilla/rust-components-swift`
87+
and replace it with a dependency on `file:///path/to/your/local/checkout/rust-components-swift` at the `0.0.` release.
88+
89+
That's it! The consuming application should be able to import the package from your local checkout.
90+

external/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subdirectory for git submodules.

external/application-services

Submodule application-services added at 3b676ef

generate.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Script to generate any artifacts required when building the Swift packages.
4+
#
5+
# Swift packages can't run arbitrary comments at build time (well, not in a well-supported manner anyway)
6+
# so we need to have everything required to build the swift code checked in to the repo and included
7+
# in the release tag. This is a little ad-hoc script for doing so, at least until we find a better
8+
# way.
9+
10+
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
11+
12+
UNIFFI_BINDGEN=(cargo run --manifest-path "$THIS_DIR/external/application-services/tools/embedded-uniffi-bindgen/Cargo.toml")
13+
GLEAN_GENERATOR="$THIS_DIR/external/application-services/components/external/glean/glean-core/ios/sdk_generator.sh"
14+
15+
set -euvx
16+
17+
###
18+
#
19+
# Nimbus
20+
#
21+
###
22+
23+
NIMBUS_DIR="$THIS_DIR/generated/nimbus"
24+
rm -rf "$NIMBUS_DIR" && mkdir -p "$NIMBUS_DIR"
25+
# Glean metrics.
26+
# Run this first, because it appears to delete any other .swift files in the output directory.
27+
# Also, it wants to be run from inside Xcode, so we set some env vars to fake it out.
28+
SOURCE_ROOT="$THIS_DIR" PROJECT="nimbus" "$GLEAN_GENERATOR" -o "$NIMBUS_DIR/Generated" "$THIS_DIR/external/application-services/components/nimbus/metrics.yaml"
29+
# UniFFI bindings.
30+
"${UNIFFI_BINDGEN[@]}" generate -l swift -o "$NIMBUS_DIR/Generated" "$THIS_DIR/external/application-services/components/nimbus/src/nimbus.udl"
31+
# Copy the hand-written Swift, since it all needs to be together in one directory.
32+
cp -r "$THIS_DIR/external/application-services/components/nimbus/ios/Nimbus" "$NIMBUS_DIR/Nimbus"
33+
34+
###
35+
#
36+
# CrashTest
37+
#
38+
###
39+
40+
CRASHTEST_DIR="$THIS_DIR/generated/crashtest"
41+
rm -rf "$CRASHTEST_DIR" && mkdir -p "$CRASHTEST_DIR"
42+
"${UNIFFI_BINDGEN[@]}" generate -l swift -o "$CRASHTEST_DIR" "$THIS_DIR/external/application-services/components/crashtest/src/crashtest.udl"

0 commit comments

Comments
 (0)