Skip to content

Commit e240c89

Browse files
authored
Update documentation for new SPM flow for firefox-ios (#6898)
1 parent 2f3f9cd commit e240c89

File tree

7 files changed

+159
-105
lines changed

7 files changed

+159
-105
lines changed

docs/build-and-publish-pipeline.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ For iOS consumers the corresponding steps are:
7373
* TODO: could a malicious dev dependency from step (3) influence the build environment here?
7474
5. CircleCI uses [dpl](https://github.com/travis-ci/dpl) to publish to GitHub as a release artifact.
7575
* See [Authentication and secrets below](#authentication-and-secrets)
76-
6. Consumers add Application services as a dependency from the [Rust Components Swift](https://github.com/mozilla/rust-components-swift/) repo using Apple's Swift Package Manager.
76+
6. Consumers can add the Application Services rust components as a dependency in their corresponding swift package by replicating the firefox-ios integration [here](https://github.com/mozilla-mobile/firefox-ios/tree/main/MozillaRustComponents).
7777

7878
For consuming in mozilla-central, see [how to vendor components into mozilla-central
7979
](./howtos/vendoring-into-mozilla-central.md)

docs/design/swift-package-manager.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The strategy includes two main parts:
1212
- The [xcframework](https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages) that is built from a [megazord](./megazords.md). The xcframework contains the following, built for all our target iOS platforms.
1313
- The compiled Rust code for all the crates listed in `Cargo.toml` as a static library
1414
- The C header files and [Swift module maps](https://clang.llvm.org/docs/Modules.html) for the components
15-
- The [`rust-components-swift`](https://github.com/mozilla/rust-components-swift) repository which has a `Package.swift` that includes the `xcframework` and acts as the swift package the consumers import
15+
- The firefox-ios repo uses a local [swift package](https://github.com/mozilla-mobile/firefox-ios/blob/main/MozillaRustComponents/Package.swift) and an example of how they consume the xcframework [here](https://github.com/mozilla/application-services/pull/6898).
1616

1717

1818
## The xcframework and `application-services`
@@ -30,7 +30,35 @@ In `application-services`, in the [`megazords/ios-rust`](https://github.com/mozi
3030

3131
> It's a little unusual that we're building the xcframework by hand, rather than defining it as the build output of an Xcode project. It turns out to be simpler for our purposes, but does risk diverging from the expected format if Apple changes the details of xcframeworks in future Xcode releases.
3232
33+
34+
## Consuming Application Services in a Swift package (Firefox iOS)
35+
Firefox iOS consumes the XCFramework via a local swift package: [MozillaRustComponents/Package.swift](https://github.com/mozilla-mobile/firefox-ios/blob/main/MozillaRustComponents/Package.swift).
36+
37+
Core requirements:
38+
- A `binaryTarget` for `MozillaRustComponents` (URL+checksum for published zips, or a local `path:` for testing).
39+
- A location for UniFFI-generated Swift bindings in your package targets.
40+
- A target app that supports swift packages to consume the above binary + files.
41+
42+
Example (URL-based):
43+
```swift
44+
.binaryTarget(
45+
name: "MozillaRustComponents",
46+
url: "<artifact-url>/MozillaRustComponents.xcframework.zip",
47+
checksum: "<sha256>"
48+
)
49+
50+
.target(
51+
name: "MozillaAppServices",
52+
dependencies: ["MozillaRustComponents"],
53+
path: "Sources/MozillaRustComponentsWrapper"
54+
),
55+
```
56+
3357
## The `rust-components-swift` repository
58+
59+
> [!WARNING]
60+
> rust-components-swift has been deprecated and is only around until there are no more potential uplifts to already-landed versions of firefox-ios. firefox-ios now consumes application-services via [local swift package](https://github.com/mozilla-mobile/firefox-ios/tree/main/MozillaRustComponents)
61+
3462
The 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 `application-services`
3563

3664
The `rust-components-swift` repo mainly includes the following:

docs/howtos/adding-a-new-component.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ You will end up with a directory structure something like this:
114114

115115
> *For more information on our how we ship components using the Swift Package Manager, check the [ADR that introduced the Swift Package Manager](../adr/0003-swift-packaging.md)*
116116
117-
Add your component into the iOS ["megazord"](../design/megazords.md) through the local Swift Package Manager (SPM) package `MozillaRustComponentsWrapper`. Note this SPM is for easy of local testing of APIs locally. The official SPM that is consumed by firefox-ios is [rust-components-swift](https://github.com/mozilla/rust-components-swift?tab=readme-ov-file).
117+
> [!CRITICAL]
118+
> This section will be soon outdated as all swift wrappers and related tests will be moving to the firefox-ios repository.
119+
120+
Add your component into the iOS ["megazord"](../design/megazords.md) through the local Swift Package Manager (SPM) package `MozillaRustComponentsWrapper`. Note this SPM is for ease of testing APIs locally. The official SPM that is consumed by firefox-ios is a [local package in their repo](https://github.com/mozilla-mobile/firefox-ios/tree/main/MozillaRustComponents).
118121

119122
1. Place any hand-written Swift wrapper code for your component in:
120123
```

docs/howtos/breaking-changes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ Do not merge any PRs until all are approved. Once they are all approved then:
1818
- Merge the `application-services` PR into `main`
1919
- Manually trigger a new nightly build using the taskcluster hook:
2020
https://firefox-ci-tc.services.mozilla.com/hooks/project-releng/cron-task-mozilla-application-services%2Fnightly
21-
- Once the nightly task completes, trigger a new rust-components-swift build using the github action:
22-
https://github.com/mozilla/rust-components-swift/actions/workflows/update-as-nightly.yml
21+
- Once the nightly task completes, trigger a new build in firefox-ios using the github action:
22+
https://github.com/mozilla-mobile/firefox-ios/actions/workflows/update-appservices-nightly.yml
2323
- Update the `firefox-android` and `firefox-ios` PRs to use the newly built nightly:
2424
* [example of firefox-android changes](https://github.com/mozilla-mobile/firefox-android/pull/4056/files)
2525
* [example of firefox-ios changes](https://github.com/mozilla-mobile/firefox-ios/pull/16783/files)
Lines changed: 118 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,140 @@
11
# How to locally test Swift Package Manager components on Firefox iOS
2-
> This is a guide on testing the Swift Package Manager component locally against a local build of Firefox iOS. For more information on our Swift Package Manager design, read the [ADR that introduced it](../adr/0003-swift-packaging.md)
32

4-
> This guide assumes the component you want to test is already distributed with the [`rust-components-swift`](https://github.com/mozilla/rust-components-swift) repository, you can read [the guide for adding a new component](./adding-a-new-component.md#including-the-component-in-the-swift-package-manager-megazord) if you would like to distribute a new component.
3+
> This guide explains how to build and test **Firefox iOS against a local Application Services** checkout.
4+
> For background on our Swift Package approach, see the [ADR](../adr/0003-swift-packaging.md).
55
6+
---
67

7-
**The goal for this document is to be able to build a local firefox iOS against a local application-services**. On a high level, that requires the following:
8+
## At a glance
89

9-
1. Build an xcframework in a local checkout of `application-services`
10-
1. Include the xcframework in a local checkout of `rust-components-swift`
11-
1. Run the `generate` script in `rust-components-swift` using a local checkout of `application-services`
12-
1. Include the local checkout of `rust-components-swift` in `firefox-ios`
10+
**Goal:** Build a local Firefox iOS against a local Application Services.
1311

12+
**Current workflow (recommended):**
1413

15-
## Prerequisites:
16-
1. A local checkout of [`firefox-ios` that is ready to build](https://github.com/mozilla-mobile/firefox-ios#building-the-code)
17-
1. A local checkout of [`rust-components-swift`](https://github.com/mozilla/rust-components-swift)
18-
1. A local checkout of [`application-services` that is ready to build for iOS](../building.md#building-for-firefox-ios)
14+
1. Build an **XCFramework** from your local `application-services`.
15+
2. Point **Firefox iOS’s local Swift package** (`MozillaRustComponents/Package.swift`) at that artifact (either an HTTPS URL + checksum, **or** a local `path:`).
16+
3. Reset package caches in Xcode and build Firefox iOS.
1917

20-
## Using the automated flow
21-
For convenience, there is a script that will do all the necessary steps to configure your local `firefox-ios` build with a local `application-services` repository. You do **not** need to do the [manual steps](#using-the-manual-flow) if you follow those steps.
18+
A legacy flow that uses the **`rust-components-swift`** package is documented at the end while we're in mid-transition to the new system.
2219

23-
1. Run the following to execute the script, the example below assumes all of `firefox-ios`, `rust-components-swift` and `application-services` are in the same directory. Adjust the paths according to where they are on your filesystem.
20+
---
2421

25-
```bash
26-
$ cd firefox-ios # This is your local checkout of firefox-ios
27-
$ ./rust_components_local.sh -a ../application-services ../rust-components-swift
28-
```
22+
## Prerequisites
2923

30-
1. Using Xcode, open `Client.xcodeproj` in `firefox-ios`
24+
1. A local checkout of **Firefox iOS** that builds: <https://github.com/mozilla-mobile/firefox-ios#building-the-code>
25+
2. A local checkout of **Application Services** prepared for iOS builds: see [Building for Firefox iOS](../building.md#building-for-firefox-ios)
3126

32-
1. Then, make sure to reset packages cache in Xcode. This forces Xcode to remove any previously cached versions of the Rust components.
33-
- You can reset package caches by going to `File -> Packages -> Reset Package Caches`
34-
1. If this is not the first time you run the script, make sure to also update package versions. This forces Xcode to pull the latest changes in the `rust-components-swift` branch.
35-
- You can update package versions by going to `File -> Packages -> Update To Latest Package Versions`
36-
- If this step fails, it's possible that the `Reset Package Caches` step above left some cruft behind. You can force this step by manually removing `~/Library/Caches/org.swift.swiftpm` and `~/Library/Developer/Xcode/DerivedData/Client-{some-long-string}`
37-
1. Once the above steps are done, attempt building firefox ios. If you face problems, feel free to [contact us](../index.md#contact-us)
27+
---
3828

39-
### Disabling local development
40-
The easiest way to disable local development is to simply revert any changes to `firefox-ios/Client.xcodeproj/project.pbxproj`.
29+
## Step 1 — Build the XCFramework from Application Services
4130

42-
However, if there are other changes to the file that you would like to preserve, you can use the same script. To use the same script, you will need to:
43-
1. Know what version of `rust-components-swift` was used beforehand. You can find this by checking the git diff on `firefox-ios/Client.xcodeproj/project.pbxproj`.
44-
1. Run:
45-
```bash
46-
$ ./rust_components_local.sh --disable <VERSION> ../rust-components-swift
47-
```
48-
1. Then, make sure to reset packages cache in Xcode. This forces Xcode to remove any previously cached versions of the Rust components.
49-
- You can reset package caches by going to `File -> Packages -> Reset Package Caches`
31+
From your `application-services` checkout:
5032

33+
```bash
34+
cd megazords/ios-rust
35+
./build-xcframework.sh
36+
```
5137

52-
> If you happen to change branches in `rust-components-swift`, you will need to disable then re-enable local development. The script is not currently smart enough to switch branches. Alternatively, keep the branch in `rust-components-swift` the same. `rust-components-swift` serves only as a release surface so there is little use to switching branches and pushing changes to it, unless you are changing something related to the release process.
38+
This produces MozillaRustComponents.xcframework.zip (and you can also unzip it to get MozillaRustComponents.xcframework) containing:
5339

54-
## Using the manual flow
55-
**It's important to note the automated flow runs through all the necessary steps in a script, so if possible use the script as it's a tedious manual process**
40+
- The compiled Rust code as a static library (for all iOS targets)
41+
- C headers and Swift module maps for the components
5642

57-
However, if the script is failing or you would like to run the manual process for any other reason follow the following steps.
43+
> Tip: If you plan to use the URL-based approach below, compute the checksum once you have the zip:
5844
59-
### Building the xcframework
60-
To build the [xcframework](https://developer.apple.com/documentation/swift_packages/distributing_binary_frameworks_as_swift_packages) do the following:
61-
1. In your local checkout of `application-services`, navigate to [`megazords/ios-rust/`](https://github.com/mozilla/application-services/tree/main/megazords/ios-rust)
62-
1. Run the `build-xcframework.sh` script:
6345
```bash
64-
$ ./build-xcframework.sh
46+
swift package compute-checksum MozillaRustComponents.xcframework.zip
47+
```
48+
49+
## Step 2 — Point Firefox iOS to your local artifact
50+
51+
Firefox iOS consumes Application Services via a local Swift package in-repo at:
52+
53+
```
54+
{path-to-firefox-ios}/MozillaRustComponents/Package.swift
55+
```
56+
57+
update it in one of two ways:
58+
59+
### Option A: URL + checksum (zip artifact)
60+
61+
1. Host your MozillaRustComponents.xcframework.zip at an HTTPS-accessible URL (e.g., a Taskcluster or GitHub artifact URL).
62+
2. Edit MozillaRustComponents/Package.swift and set the binaryTarget to the zip URL and checksum:
63+
64+
```swift
65+
// In firefox-ios/MozillaRustComponents/Package.swift
66+
.binaryTarget(
67+
name: "MozillaRustComponents",
68+
url: "https://example.com/path/MozillaRustComponents.xcframework.zip",
69+
checksum: "<sha256 from `swift package compute-checksum`>"
70+
)
71+
```
72+
73+
> Note: Every time you produce a new zip, you must update the checksum.
74+
75+
### Option B: Local path (fastest for iteration)
76+
77+
1. Unzip the XCFramework near the package (or anywhere on disk).
78+
2. Switch the binaryTarget to a local path:
79+
80+
```swift
81+
// In firefox-ios/MozillaRustComponents/Package.swift
82+
.binaryTarget(
83+
name: "MozillaRustComponents",
84+
path: "./MozillaRustComponents.xcframework"
85+
)
6586
```
66-
This will produce a file name `MozillaRustComponents.xcframework.zip` that contains the following, built for all our target iOS platforms.
67-
- The compiled Rust code for all the crates listed in `Cargo.toml` as a static library
68-
- The C header files and [Swift module maps](https://clang.llvm.org/docs/Modules.html) for the components
69-
70-
### Include the xcframework in a local checkout of `rust-components-swift`
71-
After you generated the `MozillaRustComponents.xcframework.zip` in the previous step, do the following to include it in a local checkout of `rust-components-swift`. The file will be in the `megazords/ios-rust` directory.
72-
1. Unzip the `MozillaRustComponents.xcframework.zip` into the `rust-components-swift` repository: (Assuming you are in the root of the `rust-components-swift` directory and `application-services` is a neighbor directory)
73-
```sh
74-
unzip -o ../application-services/megazords/ios-rust/MozillaRustComponents.xcframework.zip -d .
75-
```
76-
1. Change the `Package.swift`'s reference to the xcframework to point to the unzipped `MozillaRustComponents.xcframework` that was created in the previous step. You can do this by uncommenting the following line:
77-
```swift
78-
path: "./MozillaRustComponents.xcframework"
79-
```
80-
and commenting out the following lines:
81-
```swift
82-
url: url,
83-
checksum: checksum,
84-
```
85-
86-
### Run the generation script with a local checkout of application services
87-
For this step, run the following script from inside the `rust-components-swift` repository (assuming that `application-services` is a neighboring directory to `rust-components-swift`).
88-
89-
```sh
90-
./generate.sh ../application-services
87+
88+
> UniFFI bindings: If your component requires UniFFI-generated Swift, ensure the package targets reference the directory where generated Swift files are emitted (same pattern used in the repo’s Package.swift today).
89+
90+
## Step 3 — Reset caches and build
91+
92+
In Xcode:
93+
94+
- File → Packages → Reset Package Caches
95+
- (If needed) File → Packages → Update to Latest Package Versions
96+
- Product → Clean Build Folder, then build and run Firefox iOS.
97+
98+
If you still see stale artifacts, delete:
99+
100+
```swift
101+
~/Library/Caches/org.swift.swiftpm
102+
~/Library/Developer/Xcode/DerivedData/*
91103
```
92-
Once that is done, **stage and commit** the changes the script ran. Xcode can only pick up committed changes.
93-
94-
### Include the local checkout of `rust-components-swift` in `firefox-ios`
95-
This is the final step to include your local changes into `firefox-ios`. Do the following steps:
96-
1. Open `Client.xcodeproj` in Xcode
97-
1. Navigate to the Swift Packages in Xcode:
98-
![Screenshot of where to find the setting for Client](./img/xcode-client-package-settings.png)
99-
1. Remove the dependency on `rust-components-swift` as listed on Xcode, you can click the dependency then click the `-`
100-
1. Add a new swift package by clicking the `+`:
101-
102-
1. On the top right, enter the full path to your `rust-components-swift` checkout, preceded by `file://`. If you don't know what that is, run `pwd` in while in `rust-components-swift`. For example: `file:///Users/tarikeshaq/code/rust-components-swift`
103-
1. Change the branch to be the checked-out branch of rust-component-swift you have locally. This is what the dialog should look like:
104-
![Dialog for including the `rust-components-swift` package](./img/xcode-include-packages-firefox-ios.png)
105-
> Note: If Xcode prevents you from adding the dependency to reference a local package, you will need to manually modify the `Client.xcodeproj/project.pbxproj` and replace every occurrence of `https://github.com/mozilla/rust-components-swift` with the full path to your local checkout.
106-
1. Click `Add Package`
107-
1. Now include the packages you would like to include, choose `MozillaAppServices`
108-
1. Finally, attempt to build firefox-ios, and if all goes well it should launch with your code. If you face problems, feel free to [contact us](../index.md#contact-us)
104+
105+
…and build again.
106+
107+
---
108+
109+
## Disabling local development
110+
111+
To revert quickly:
112+
113+
1. Restore your changes to MozillaRustComponents/Package.swift (e.g., git checkout -- MozillaRustComponents/Package.swift).
114+
2. Reset Package Caches in Xcode.
115+
3. Build Firefox iOS.
116+
117+
## Troubleshooting
118+
119+
- Old binary still in use: Reset caches and clear DerivedData, then rebuild.
120+
- Branch switches in application-services: Rebuild the XCFramework and update the package reference (URL/checksum or path:).
121+
- Checksum mismatch (URL mode): Run swift package compute-checksum on the new zip and update Package.swift.
122+
- Build script issues: Re-run ./build-xcframework.sh from megazords/ios-rust.
123+
124+
## Legacy: using rust-components-swift (remote package)
125+
126+
[!WARNING]
127+
Status: rust-components-swift is deprecated for Firefox iOS. Prefer the local package at MozillaRustComponents/ unless you must validate against the legacy package for a specific task.
128+
129+
Some teams may still need the legacy flow temporarily. Historically, Firefox iOS consumed Application Services through the rust-components-swift package. To test locally with that setup:
130+
131+
1. Build the XCFramework from application-services.
132+
2. In a local checkout of rust-components-swift, point its Package.swift to the local path of the unzipped XCFramework:
133+
```swift
134+
.binaryTarget(
135+
name: "MozillaRustComponents",
136+
path: "./MozillaRustComponents.xcframework"
137+
)
138+
```
139+
3. Commit the changes in rust-components-swift (Xcode only reads committed package content).
140+
4. In Firefox iOS, replace the package dependency with a local reference to your rust-components-swift checkout (e.g., via Xcode’s “Add Local…” in Package Dependencies).

0 commit comments

Comments
 (0)