Skip to content

Build libsqlite3.so with the NDK Gradle uses; prepare 1.13.2 - #102

Merged
aquasolterra merged 2 commits into
mainfrom
pin-ndk
Oct 4, 2026
Merged

aquasolterra merged 2 commits into
mainfrom
pin-ndk

Conversation

@aquasolterra

Copy link
Copy Markdown
Member

F-Droid cannot reproduce 1.13.1. Its libsqlite3.so was compiled with NDK r27d, while libdartjni.so (and F-Droid's whole build) uses r28c — the two libsqlite3.so builds differ in 1.58 M of 1.75 M bytes.

Why: the SQLite build hook gets its compiler from Flutter, which reads ANDROID_NDK_HOME first. GitHub's runners set it to their own default NDK; fdroidserver sets it to the recipe's ndk:. Gradle meanwhile uses flutter.ndkVersion for libdartjni.so. My earlier "two local builds are byte-identical" check (#99) could not see this, because both builds shared the one thing that differed.

Fix:

  • tool/pin_ndk.sh reads flutter.ndkVersion from the Flutter SDK, installs that NDK if missing, and points ANDROID_NDK_HOME / ANDROID_NDK_ROOT / ANDROID_NDK at it (via $GITHUB_ENV in CI, eval "$(tool/pin_ndk.sh)" locally). Run before the APK build in release.yml and ci.yml.
  • tool/check_apk_ndk.py reads .note.android.ident from libsqlite3.so and libdartjni.so in the built APKs and fails unless both name the pinned NDK. Prebuilt libraries (libflutter.so, AndroidX's libdatastore_shared_counter.so) are deliberately not checked.
  • AGENTS.md and docs/fdroid.md corrected (the sentence claiming SQLite already used r28c was false).

Tested locally: the checker fails on the 1.13.1 release APKs (naming both NDKs), passes on a local r28c build, and fails on a wrong --expect or a missing library.

Release: the second commit prepares 1.13.2+406 (versionCodes 4061/4062/4063), with a CHANGELOG and fastlane entry saying nothing in the app changed. After merging, tag v1.13.2 as usual; I'll then verify the release APKs and update the F-Droid recipe.

🤖 Generated with Claude Code

aquasolterra and others added 2 commits October 4, 2026 22:50
The SQLite build hook takes its compiler from Flutter, which reads
ANDROID_NDK_HOME before anything else; Gradle compiles libdartjni.so with
flutter.ndkVersion. GitHub's runners point the variable at their own
default NDK, so the published 1.13.1 carries a libsqlite3.so built with
r27d beside a libdartjni.so built with r28c. fdroidserver sets the same
variable to the recipe's ndk:, r28c, so F-Droid's build cannot reproduce
the release: the two libraries differ in 1.58 million of 1.75 million
bytes. Two local builds agreed only because they share the one thing
that differed.

tool/pin_ndk.sh reads flutter.ndkVersion from the Flutter SDK, installs
that NDK if needed and points ANDROID_NDK_HOME at it; both workflows run
it before building. tool/check_apk_ndk.py reads the NDK each library
compiled here names in its .note.android.ident and fails unless
libsqlite3.so and libdartjni.so both carry that version. Prebuilt ones
(libflutter.so, AndroidX's libdatastore_shared_counter.so) are not
checked; they come with whatever NDK their publishers used.

Tested against the 1.13.1 release APKs (fails, naming both NDKs), a local
r28c build (passes), a wrong expectation and a missing library (both fail).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing changes in the app: this release exists so that F-Droid can
reproduce it, now that libsqlite3.so is built with the same NDK as the
rest. Build number 406, versionCodes 4061/4062/4063.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@aquasolterra
aquasolterra merged commit 6f97896 into main Oct 4, 2026
5 checks passed
@aquasolterra
aquasolterra deleted the pin-ndk branch October 4, 2026 21:08
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