This removes the need for a lot configuration in our `uniffi.toml`
files.
This commit is contained in:
Ben Dean-Kawamura 2023-05-19 16:30:47 -04:00 коммит произвёл bendk
Родитель 220af9af6c
Коммит 7625a2cecc
33 изменённых файлов: 83 добавлений и 138 удалений

Просмотреть файл

@ -14,6 +14,6 @@ dependencies {
testImplementation project(":syncmanager")
}
ext.configureUniFFIBindgen("../src/autofill.udl")
ext.configureUniFFIBindgen("autofill")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.autofill"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -5,6 +5,6 @@ android {
namespace 'org.mozilla.appservices.crashtest'
}
ext.configureUniFFIBindgen("../src/crashtest.udl")
ext.configureUniFFIBindgen("crashtest")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,7 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.crashtest"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -20,6 +20,6 @@ dependencies {
testImplementation libs.mozilla.glean.native.tests
}
ext.configureUniFFIBindgen("../src/fxa_client.udl")
ext.configureUniFFIBindgen("fxa_client")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,10 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.fxaclient"
cdylib_name = "megazord"
[bindings.kotlin.external_packages]
# Map from [External={crate-name}] into Kotlin package names
sync15 = "mozilla.appservices.sync15"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -26,6 +26,6 @@ dependencies {
testImplementation project(":syncmanager")
}
ext.configureUniFFIBindgen("../src/logins.udl")
ext.configureUniFFIBindgen("logins")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.logins"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -27,6 +27,6 @@ dependencies {
testImplementation libs.test.work
}
ext.configureUniFFIBindgen("../src/nimbus.udl")
ext.configureUniFFIBindgen("nimbus")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "org.mozilla.experiments.nimbus.internal"
cdylib = "megazord"
[bindings.kotlin.custom_types.JsonObject]
# Name of the type in the Kotlin code
@ -11,10 +10,6 @@ imports = [ "org.json.JSONObject" ]
into_custom = "JSONObject({})"
from_custom = "{}.toString()"
[bindings.kotlin.external_packages]
# Map from [External={crate-name}] into Kotlin package names
remote_settings = "mozilla.appservices.remotesettings"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"
ffi_module_filename = "nimbusFFI"

Просмотреть файл

@ -25,6 +25,6 @@ dependencies {
testImplementation project(':syncmanager')
}
ext.configureUniFFIBindgen("../src/places.udl")
ext.configureUniFFIBindgen("places")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -2,7 +2,6 @@
# Typically there'd be no `.uniffi` tail, but without it we see obscure
# kotlin errors about being unable to resolve which `rustCall` to use.
package_name = "mozilla.appservices.places.uniffi"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -5,6 +5,6 @@ android {
namespace 'org.mozilla.appservices.push'
}
ext.configureUniFFIBindgen("../src/push.udl")
ext.configureUniFFIBindgen("push")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.push"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -5,7 +5,7 @@ android {
namespace 'org.mozilla.appservices.remotesettings'
}
ext.configureUniFFIBindgen("../src/remote_settings.udl")
ext.configureUniFFIBindgen("remote_settings")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.remotesettings"
cdylib_name = "megazord"
[bindings.kotlin.custom_types.RsJsonObject]
# Name of the type in the Kotlin code

Просмотреть файл

@ -9,6 +9,6 @@ dependencies {
api project(":remotesettings")
}
ext.configureUniFFIBindgen("../src/suggest.udl")
ext.configureUniFFIBindgen("suggest")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,10 +1,6 @@
[bindings.kotlin]
package_name = "mozilla.appservices.suggest"
cdylib_name = "megazord"
[bindings.kotlin.external_packages]
remote_settings = "mozilla.appservices.remotesettings"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"
ffi_module_filename = "suggestFFI"

Просмотреть файл

@ -5,6 +5,6 @@ android {
namespace 'org.mozilla.appservices.errorsupport'
}
ext.configureUniFFIBindgen("../src/errorsupport.udl")
ext.configureUniFFIBindgen("error_support")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,8 +1,7 @@
[bindings.kotlin]
package_name = "mozilla.appservices.errorsupport"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"
ffi_module_filename = "errorFFI"
generate_module_map = false
generate_module_map = false

Просмотреть файл

@ -5,6 +5,6 @@ android {
namespace 'org.mozilla.appservices.rust_log_forwarder'
}
ext.configureUniFFIBindgen("../src/rust_log_forwarder.udl")
ext.configureUniFFIBindgen("rust_log_forwarder")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.rust_log_forwarder"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -5,6 +5,6 @@ android {
namespace 'org.mozilla.appservices.sync15'
}
ext.configureUniFFIBindgen("../src/sync15.udl")
ext.configureUniFFIBindgen("sync15")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,6 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.sync15"
cdylib_name = "megazord"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -28,6 +28,6 @@ dependencies {
testImplementation libs.test.work
}
ext.configureUniFFIBindgen("../src/syncmanager.udl")
ext.configureUniFFIBindgen("sync_manager")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,10 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.syncmanager"
cdylib_name = "megazord"
[bindings.kotlin.external_packages]
# Map from [External={crate-name}] into Kotlin package names
sync15 = "mozilla.appservices.sync15"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -12,6 +12,6 @@ dependencies {
testImplementation project(':syncmanager')
}
ext.configureUniFFIBindgen("../src/tabs.udl")
ext.configureUniFFIBindgen("tabs")
ext.dependsOnTheMegazord()
ext.configurePublish()

Просмотреть файл

@ -1,10 +1,5 @@
[bindings.kotlin]
package_name = "mozilla.appservices.remotetabs"
cdylib_name = "megazord"
[bindings.kotlin.external_packages]
# Map from [External={crate-name}] into Kotlin package names
sync15 = "mozilla.appservices.sync15"
[bindings.swift]
ffi_module_name = "MozillaRustComponents"

Просмотреть файл

@ -8,8 +8,7 @@ the things you'll need to do if adding a new component from scratch.
## The Rust Code
Your component should live under `./components` in this repo.
Use `cargo new --lib ./components/<your_crate_name>`to create a new library crate,
and please try to avoid using hyphens in the crate name.
Use `cargo new --lib ./components/<your_crate_name>`to create a new library crate.
See the [Guide to Building a Rust Component](./building-a-rust-component.md) for general
advice on designing and structuring the actual Rust code, and follow the
@ -17,14 +16,16 @@ advice on designing and structuring the actual Rust code, and follow the
introduces any new dependencies.
Use [UniFFI](https://mozilla.github.io/uniffi-rs/) to define how your crate's
API will get exposed to foreign-language bindings. By convention, put the interface
definition file at `./components/<your_crate_name>/<your_crate_name>.udl`. Use
the `builtin-bindgen` feature of UniFFI to simplify the build process, by
putting the following in your `Cargo.toml`:
API will get exposed to foreign-language bindings. Prefer using the
[proc-macro](https://mozilla.github.io/uniffi-rs/latest/proc_macro/index.html) approach to creating
a UDL file. Place the following entries in your `Cargo.toml`:
```
[dependencies]
uniffi = { workspace = true }
[build-dependencies]
uniffi_build = { version = "<latest version here>", features=["builtin-bindgen"] }
uniffi = { workspace = true }
```
Include your new crate in the `application-services` workspace, by adding
@ -51,8 +52,8 @@ Kotlin- and Android-specific code. This directory will contain a gradle
project for building your Kotlin bindings.
Copy the `build.gradle` file from `./components/crashtest/android/` into
your own component's directory, and edit it to replace the references to
`crashtest.udl` with your own component's `.udl` file.
your own component's directory. Update the `ext.configureUniFFIBindgen("crashtest")` line,
replacing "crashtest" with the crate name of your component.
Create a file `./components/<your_crate_name>/uniffi.toml` with the
following contents:
@ -60,7 +61,6 @@ following contents:
```toml
[bindings.kotlin]
package_name = "mozilla.appservices.<your_crate_name>"
cdylib_name = "megazord"
```
Create a file `./components/<your_crate_name>/android/src/main/AndroidManifest.xml`
@ -141,16 +141,13 @@ You will need to do the following steps to include the component in the megazord
```
1. Add the component as a dependency to the `Cargo.toml` in [`megazords/ios-rust/`](https://github.com/mozilla/application-services/blob/main/megazords/ios-rust/Cargo.toml)
1. Add a `pub use` declaration for the component in [`megazords/ios-rust/src/lib.rs`](https://github.com/mozilla/application-services/blob/main/megazords/ios-rust/src/lib.rs)
1. Add logic to the [`megazords/ios-rust/build-xcframework.sh`](https://github.com/mozilla/application-services/blob/main/megazords/ios-rust/build-xcframework.sh) to copy or generate its header file into the build
1. Add an `#import` for its header file to [`megazords/ios-rust/MozillaRustComponents.h`](https://github.com/mozilla/application-services/blob/main/megazords/ios-rust/MozillaRustComponents.h)
1. Add your component into the iOS ["megazord"](../design/megazords.md) through the Xcode project, which can only really by done using the Xcode application, which can only really be done if you're on a Mac.
1. Open `megazords/ios-rust/MozillaTestServices/MozillaTestServices.xcodeproj` in Xcode.
1. In the Project navigator, add a new Group for your new component, pointing to
the `./ios/` directory you created above. Add the following entries to the Group:
* The `.udl` file for you component, from `../src/<your_crate_name>.udl`.
* Any hand-written `.swift `files for your component
> Make sure that the "Copy items if needed" option is **unchecked**, and that
@ -162,11 +159,6 @@ The result should look something like this:
Click on the top-level "MozillaTestServices" project in the navigator, then go to "Build Phases".
> Double-check that `<your_crate_name>.udl` does **not** appear in the "Copy Bundle Resources" section.
Add `<your_crate_name>.udl` to the list of "Compile Sources". This will trigger an Xcode Build Rule that generates
the Swift bindings automatically. Also include any hand-written `.swift` files in this list.
Finally, in the Project navigator, add a sub-group named "Generated", pointing to the `./Generated/` subdirectory, and
containing entries for the files generated by UniFFI:
* `<your_crate_name>.swift`
@ -203,8 +195,6 @@ they're passing.
The Swift source code and generated UniFFI bindings are distributed to consumers (eg: Firefox iOS) through [`rust-components-swift`](https://github.com/mozilla/rust-components-swift).
A nightly taskcluster job prepares the `rust-component-swift` packages from the source code in the application-services repository. To distribute your component with `rust-component-swift`, add the following to the taskcluster script in `taskcluster/scripts/build-and-test-swift.py`:
- Add the path to the `<your_crate_name>.udl` file to `BINDINGS_UDL_PATHS`
- Optionally also to `FOCUS_UDL_PATHS` if your component is also targeting Firefox Focus
- Add the path to the directory containing any hand-written swift code to `SOURCE_TO_COPY`
- Optionally also to `FOCUS_SOURCE_TO_COPY` if your component is also targeting Firefox Focus

Просмотреть файл

@ -139,37 +139,22 @@ cp "$WORKING_DIR/DEPENDENCIES.md" "$COMMON/DEPENDENCIES.md"
mkdir -p "$COMMON/Headers"
# First we move the files that are common between both
# firefox-ios and Focus
# Library to generate the UniFFI bindings with. We use an arbitrary target, since that doesn't
# affect the bindings.
UNIFFI_BINDGEN_LIBRARY="$TARGET_DIR/aarch64-apple-ios/$BUILD_PROFILE/$LIB_NAME"
# First move the non-generated headers (these are all common between both firefox-ios and Focus)
cp "$WORKING_DIR/$FRAMEWORK_NAME.h" "$COMMON/Headers"
cp "$REPO_ROOT/components/viaduct/ios/RustViaductFFI.h" "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/remote_settings/src/remote_settings.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/nimbus/src/nimbus.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/support/error/src/errorsupport.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/support/rust-log-forwarder/src/rust_log_forwarder.udl" -l swift -o "$COMMON/Headers"
# Next, move the generated headers.
#
# TODO: https://github.com/mozilla/uniffi-rs/issues/1060
#
# It would be neat if there was a single UniFFI command that would generate headers-only, but for
# now we generate both the `.h` and `.swift` files, then delete the `.swift`. Bleh.
# We now only move/generate the rest of the headers if we are generating a full
# iOS megazord
if [ -z $IS_FOCUS ]; then
# TODO: https://github.com/mozilla/uniffi-rs/issues/1060
# it would be neat if there was a single UniFFI command that would spit out
# all of the generated headers for all UniFFIed dependencies of a given crate.
# For now we generate the Swift bindings to get the headers as a side effect,
# then delete the generated Swift code. Bleh.
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/crashtest/src/crashtest.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/fxa-client/src/fxa_client.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/logins/src/logins.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/autofill/src/autofill.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/push/src/push.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/tabs/src/tabs.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/places/src/places.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/suggest/src/suggest.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/sync_manager/src/syncmanager.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/sync15/src/sync15.udl" -l swift -o "$COMMON/Headers"
$CARGO uniffi-bindgen generate "$REPO_ROOT/components/as-ohttp-client/src/as_ohttp_client.udl" -l swift -o "$COMMON/Headers"
fi
$CARGO uniffi-bindgen generate --library "$UNIFFI_BINDGEN_LIBRARY" -l swift -o "$COMMON/Headers"
rm -rf "$COMMON"/Headers/*.swift

Просмотреть файл

@ -185,25 +185,47 @@ ext.configurePublish = { jnaForTestConfiguration = null ->
// A convenience function for configuring a `uniffi-bindgen` task,
// with appropriate dependency info. This fill call `uniffi-bindgen`
// on the provided `.udl` file in order to generate Kotlin language
// A convenience function for configuring a `uniffi-bindgen` task, with appropriate dependency info.
// This will call `uniffi-bindgen` with the provided crate in order to generate Kotlin language
// bindings and include them in the source set for the project.
ext.configureUniFFIBindgen = { udlFilePath ->
ext.configureUniFFIBindgen = { crateName ->
android.libraryVariants.all { variant ->
def uniffiGeneratedPath = "generated/source/uniffi/${variant.name}/java"
def t = tasks.register("generate${variant.name.capitalize()}UniFFIBindings", Exec) {
workingDir project.rootDir
commandLine '/usr/bin/env', 'cargo', 'uniffi-bindgen', 'generate', "${project.projectDir}/${udlFilePath}", '--language', 'kotlin', '--out-dir', "${buildDir}/${uniffiGeneratedPath}"
def megazordPathCandidates = [
"${project.rootDir}/target/release/libmegazord.so",
"${project.rootDir}/target/release/libmegazord.dylib",
"${project.rootDir}/target/release/libmegazord.dll"
]
def taskName = "generate${variant.name.capitalize()}UniFFIBindings";
def t = tasks.register(taskName) {
doLast {
def megazordPath = null
for (path in megazordPathCandidates) {
def file = new File(path)
if (file.exists()) {
megazordPath = path
break
}
}
if (megazordPath == null) {
throw new GradleException("libmegazord dynamic library path not found")
}
exec {
workingDir project.rootDir
commandLine '/usr/bin/env', 'cargo', 'uniffi-bindgen', 'generate', '--library', megazordPath, "--crate", crateName, '--language', 'kotlin', '--out-dir', "${buildDir}/${uniffiGeneratedPath}"
}
}
outputs.dir "${buildDir}/${uniffiGeneratedPath}"
// Re-generate if the interface definition changes.
inputs.file "${project.projectDir}/${udlFilePath}"
// Re-generate when the megazord is rebuilt, which should happen if any components
// change
it.inputs.files megazordPathCandidates
// Re-generate if our uniffi-bindgen tooling changes.
inputs.dir "${project.rootDir}/tools/embedded-uniffi-bindgen/"
// Re-generate if our uniffi-bindgen version changes.
inputs.file "${project.rootDir}/Cargo.lock"
}
variant.registerJavaGeneratingTask(t.get(), new File(buildDir, uniffiGeneratedPath))
tasks[taskName].dependsOn(":full-megazord:assembleRelease")
}
}

Просмотреть файл

@ -8,31 +8,6 @@ import os
# Repository root dir
ROOT_DIR = pathlib.Path(__file__).parent.parent.parent
# List of udl_paths to generate bindings for
BINDINGS_UDL_PATHS = [
"components/as-ohttp-client/src/as_ohttp_client.udl",
"components/autofill/src/autofill.udl",
"components/fxa-client/src/fxa_client.udl",
"components/logins/src/logins.udl",
"components/nimbus/src/nimbus.udl",
"components/places/src/places.udl",
"components/push/src/push.udl",
"components/remote_settings/src/remote_settings.udl",
"components/suggest/src/suggest.udl",
"components/support/error/src/errorsupport.udl",
"components/sync15/src/sync15.udl",
"components/sync_manager/src/syncmanager.udl",
"components/tabs/src/tabs.udl",
"components/support/rust-log-forwarder/src/rust_log_forwarder.udl",
]
# List of udl_paths to generate bindings for
FOCUS_UDL_PATHS = [
"components/nimbus/src/nimbus.udl",
"components/remote_settings/src/remote_settings.udl",
"components/support/error/src/errorsupport.udl",
"components/support/rust-log-forwarder/src/rust_log_forwarder.udl",
]
# List of globs to copy the sources from
SOURCE_TO_COPY = [
@ -162,13 +137,20 @@ def generate_uniffi_bindings(args):
ensure_dir(out_dir)
generate_uniffi_bindings_for_target(out_dir, BINDINGS_UDL_PATHS)
generate_uniffi_bindings_for_target(focus_out_dir, FOCUS_UDL_PATHS)
# Generate sources for Firefox
generate_uniffi_bindings_for_target(out_dir, "megazord_ios")
def generate_uniffi_bindings_for_target(out_dir, bindings_path):
for udl_path in bindings_path:
log(f"generating sources for {udl_path}")
run_uniffi_bindgen(['generate', '-l', 'swift', '-o', out_dir, ROOT_DIR / udl_path])
# Generate sources for Focus
generate_uniffi_bindings_for_target(focus_out_dir, "megazord_focus")
def generate_uniffi_bindings_for_target(out_dir, library_name):
log(f"generating sources for {library_name}")
# Use a megazord library that was built for the XCFramework. Pick an arbitrary target, since
# the target doesn't affect the UniFFI bindings.
lib_path = f'target/aarch64-apple-ios/release/lib{library_name}.a'
cmdline = ['generate', '--library', lib_path, '-l', 'swift', '-o', out_dir]
run_uniffi_bindgen(cmdline)
def run_uniffi_bindgen(bindgen_args):
all_args = [

Просмотреть файл

@ -7,7 +7,7 @@ edition = "2021"
publish = false
[[bench]]
name = "places"
name = "places-bench"
harness = false
path = "src/bench.rs"