Skip to content

Add a host-only path for refreshing the Kotlin bindings - #475

Merged
kwsantiago merged 1 commit into
mainfrom
bindings-fast-path
Aug 7, 2026
Merged

Add a host-only path for refreshing the Kotlin bindings#475
kwsantiago merged 1 commit into
mainfrom
bindings-fast-path

Conversation

@kwsantiago

@kwsantiago kwsantiago commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Changing keep-mobile's FFI leaves the generated Kotlin stale, and the only way to refresh it was build-rust.sh, which cross-compiles for every Android ABI first. That is what a runnable APK needs, but it means the repository cannot be typechecked against a changed core without the NDK, cargo-ndk and the Android targets, even though the Kotlin uniffi emits is platform independent.

uniffi reads interface metadata from the library rather than machine code, so a host build carries the same metadata as a cross-compiled one. The new script builds for the host and generates from that.

It is deliberately not a replacement. No jniLibs are written, so the app compiles and then fails at runtime with an UnsatisfiedLinkError. The script says so on its last line and the README says so where it is introduced, because a faster path that quietly produces something unrunnable would cost more time than it saves.

Two details worth noting. The target directory is resolved through cargo metadata rather than assumed to be ../target, since a workspace may set CARGO_TARGET_DIR and guessing would report a missing library that had in fact just built. And the same suppression rewrite build-rust.sh performs is applied here, so the two paths produce the same file and switching between them does not surface as a diff.

Test plan

Verified end to end rather than by inspection. The script was run against this checkout, and the Kotlin it produced is byte-identical to the bindings the cross-compiled path had already written, confirmed with diff. The suppression line matches. ./gradlew compileDebugKotlin then succeeds against the regenerated file, which is the thing the script exists to enable.

Shell syntax checked with bash -n. Both failure paths were written to fail loudly: a missing KEEP_REPO, and a library that is absent after a successful build, which would mean keep-mobile had stopped being a cdylib.

Summary by CodeRabbit

  • New Features

    • Added a command-line workflow for refreshing generated Kotlin bindings after FFI changes.
    • Added validation and clear error reporting for missing build outputs or generated bindings.
    • Supports host-only builds without requiring Android NDK or Android targets.
  • Documentation

    • Documented the binding refresh commands, limitations, and type-checking-only workflow.
    • Clarified that runtime execution is unavailable because JNI libraries are not generated.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ed6917b-58de-4b24-9bce-0f7c8f4f94f1

📥 Commits

Reviewing files that changed from the base of the PR and between 6417829 and 4ed01c3.

📒 Files selected for processing (2)
  • README.md
  • scripts/refresh-bindings.sh

Walkthrough

The PR adds a strict host-based script for generating Kotlin UniFFI bindings. It validates the build, locates the host library, verifies generated output, and documents that the result supports typechecking but not runtime JNI execution.

Changes

Kotlin binding refresh

Layer / File(s) Summary
Host binding generation workflow
scripts/refresh-bindings.sh, README.md
The script builds the host cdylib, generates Kotlin bindings, applies suppressions, verifies output, and reports errors for invalid inputs or missing artifacts. The README documents the commands and the UnsatisfiedLinkError runtime limitation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant refresh_bindings_sh
  participant Cargo
  participant UniFFI_bindgen
  participant Kotlin_bindings
  refresh_bindings_sh->>Cargo: host-build keep-mobile
  Cargo-->>refresh_bindings_sh: platform-specific cdylib
  refresh_bindings_sh->>UniFFI_bindgen: generate Kotlin bindings from cdylib
  UniFFI_bindgen-->>Kotlin_bindings: generated Kotlin source
  refresh_bindings_sh->>Kotlin_bindings: apply suppressions and verify output
Loading

Poem

I hop through Cargo, quick and bright,
Bind Kotlin shapes by morning light.
No JNI run, the script explains,
But typed code grows across the plains.
A tidy check, then off I dash!
🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a host-only path to refresh Kotlin bindings.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bindings-fast-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kwsantiago
kwsantiago merged commit 045ad6d into main Aug 7, 2026
4 checks passed
@kwsantiago
kwsantiago deleted the bindings-fast-path branch August 7, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant