android: the binding generator gets its own crate, free of the app's deps
Third Android run got further than either before it — all four ABIs cross-compiled, vendored OpenSSL and all — then the generator died: error: failed to run custom build command for `openssl-sys v0.9.117` That is the HOST build. The generator was a [[bin]] inside thoughtsync-ffi, so building it compiled that crate and therefore the core, reqwest, native-tls and openssl-sys for linux. The vendored-OpenSSL block is scoped to `cfg(target_os = "android")`, so the host build went looking for a system OpenSSL that ci-rust-android has no reason to carry. Adding libssl-dev to the image would have fixed it and been wrong: a code generator has no business linking the app's TLS stack to emit Kotlin. Splitting it into thoughtsync-uniffi-bindgen, whose only dependency is uniffi, removes the entire chain. Verified from the dependency graph rather than from a build that happened to succeed — `cargo tree -p thoughtsync-uniffi-bindgen` contains none of openssl-sys, native-tls, reqwest, thoughtsync-core or rusqlite. It stays a WORKSPACE MEMBER on purpose. Sharing one lockfile is what keeps uniffi here and uniffi linked into the .so at one version; they are two halves of one ABI, and a separate lockfile is precisely how they would drift apart. The cost is that the desktop lane now compiles ~15 generator crates it never runs — cheap next to Tauri, and better than leaving the crate unlinted. Drops the `bindgen` feature and required-features bin from thoughtsync-ffi, which existed only to keep those crates off the desktop lane and now have nothing to gate. Local fmt + clippy + test all green before pushing (107 tests). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Generated
+7
@@ -4213,6 +4213,13 @@ dependencies = [
|
|||||||
"uniffi",
|
"uniffi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thoughtsync-uniffi-bindgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"uniffi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.55"
|
version = "0.3.55"
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
# module inside the desktop app (Scribe note 2730).
|
# module inside the desktop app (Scribe note 2730).
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["core", "desktop/src-tauri", "android/ffi"]
|
members = ["core", "desktop/src-tauri", "android/ffi", "android/bindgen"]
|
||||||
|
|
||||||
# Shared pins, so two consumers of the core cannot drift onto different versions of
|
# Shared pins, so two consumers of the core cannot drift onto different versions of
|
||||||
# the same dependency and resolve differently.
|
# the same dependency and resolve differently.
|
||||||
|
|||||||
@@ -92,10 +92,8 @@ abstract class UniffiBindgen : DefaultTask() {
|
|||||||
"cargo",
|
"cargo",
|
||||||
"run",
|
"run",
|
||||||
"--locked",
|
"--locked",
|
||||||
"--features",
|
"-p",
|
||||||
"bindgen",
|
"thoughtsync-uniffi-bindgen",
|
||||||
"--bin",
|
|
||||||
"uniffi-bindgen",
|
|
||||||
"--",
|
"--",
|
||||||
"generate",
|
"generate",
|
||||||
"--library",
|
"--library",
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
[package]
|
||||||
|
name = "thoughtsync-uniffi-bindgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Generates the Kotlin bindings for thoughtsync-ffi"
|
||||||
|
authors = ["bvandeusen"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# A crate whose ONLY dependency is uniffi itself.
|
||||||
|
#
|
||||||
|
# This started life as a `[[bin]]` inside thoughtsync-ffi, which failed: building
|
||||||
|
# it compiled that crate and therefore the core, reqwest, native-tls and
|
||||||
|
# openssl-sys — for the HOST. The vendored-OpenSSL block in core/Cargo.toml is
|
||||||
|
# scoped to `cfg(target_os = "android")`, so a host build looks for a system
|
||||||
|
# OpenSSL that ci-rust-android has no reason to carry, and the generator died
|
||||||
|
# with "failed to run custom build command for openssl-sys".
|
||||||
|
#
|
||||||
|
# Adding libssl-dev to the image would have worked and been wrong: a code
|
||||||
|
# generator should not link the app's TLS stack to emit Kotlin. Splitting it out
|
||||||
|
# means the generator compiles ~15 small crates and nothing else.
|
||||||
|
#
|
||||||
|
# Still a WORKSPACE MEMBER, deliberately. That is what keeps `uniffi` here and
|
||||||
|
# `uniffi` linked into the .so on one version from one lockfile — they are two
|
||||||
|
# halves of one ABI, and a separate lockfile is exactly how they would drift.
|
||||||
|
[dependencies]
|
||||||
|
uniffi = { version = "0.32", features = ["cli"] }
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//! The Kotlin generator.
|
||||||
|
//!
|
||||||
|
//! Invoked by Gradle (see android/app/build.gradle.kts) as:
|
||||||
|
//!
|
||||||
|
//! ```text
|
||||||
|
//! cargo run --locked -p thoughtsync-uniffi-bindgen -- \
|
||||||
|
//! generate --library <path/to/libthoughtsync_ffi.so> \
|
||||||
|
//! --language kotlin --out-dir <build/generated/uniffi>
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! `--library` mode reads uniffi's metadata straight out of the compiled artifact,
|
||||||
|
//! so the generated bindings can never describe a different version of the Rust
|
||||||
|
//! than the one being packaged.
|
||||||
|
fn main() {
|
||||||
|
uniffi::uniffi_bindgen_main()
|
||||||
|
}
|
||||||
@@ -29,21 +29,3 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
|
|||||||
# Display + Error impls for the error enum uniffi turns into a Kotlin exception.
|
# Display + Error impls for the error enum uniffi turns into a Kotlin exception.
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
|
||||||
[features]
|
|
||||||
# The Kotlin generator, off by default.
|
|
||||||
#
|
|
||||||
# uniffi's `cli` feature drags in clap, askama and goblin — ~15 crates that exist
|
|
||||||
# only to serve a three-line binary. Until the Android lane lands, this crate is
|
|
||||||
# compiled on every DESKTOP push (it is a workspace member, so `cargo clippy
|
|
||||||
# --all-targets` picks it up), and paying for a code generator on a lane that never
|
|
||||||
# runs one is the wrong trade. `required-features` on the bin means
|
|
||||||
# `--all-targets` skips it rather than failing.
|
|
||||||
#
|
|
||||||
# Generate bindings with:
|
|
||||||
# cargo run --features bindgen --bin uniffi-bindgen -- generate ...
|
|
||||||
bindgen = ["uniffi/cli"]
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "uniffi-bindgen"
|
|
||||||
path = "src/bin/uniffi-bindgen.rs"
|
|
||||||
required-features = ["bindgen"]
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
//! The Kotlin generator, as a binary in THIS workspace.
|
|
||||||
//!
|
|
||||||
//! uniffi's generated bindings and the `uniffi` runtime crate linked into the `.so`
|
|
||||||
//! have to be the same version — they are two halves of one ABI. Running the
|
|
||||||
//! generator from here guarantees that by construction, because it compiles against
|
|
||||||
//! the very same dependency. A `cargo install uniffi-bindgen` in the CI image would
|
|
||||||
//! instead be a second version that has to be kept in step by hand, which is why
|
|
||||||
//! ci-rust-android deliberately doesn't ship one.
|
|
||||||
//!
|
|
||||||
//! Invoked as: cargo run --bin uniffi-bindgen -- generate --library <path/to/.so> \
|
|
||||||
//! --language kotlin --out-dir <app/src/main/java>
|
|
||||||
fn main() {
|
|
||||||
uniffi::uniffi_bindgen_main()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user