android: the binding generator gets its own crate, free of the app's deps
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m27s
Android / Kotlin + Rust (debug APK) (push) Failing after 3m51s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 4m55s
Desktop (Tauri) / Update manifest (push) Successful in 5s

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:
2026-08-18 15:54:10 -04:00
co-authored by Claude Opus 5
parent 3d3df1beb0
commit 5d0de7a682
7 changed files with 51 additions and 37 deletions
-18
View File
@@ -29,21 +29,3 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
# Display + Error impls for the error enum uniffi turns into a Kotlin exception.
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"]
-14
View File
@@ -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()
}