Skip to content

Commit a22a35c

Browse files
aquasolterraclaude
andauthored
Build libdartjni.so without a GNU build ID (#49)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 6d2c346 commit a22a35c

4 files changed

Lines changed: 46 additions & 2 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,10 @@ Three smaller traps, each found by a test that had to be written twice:
17191719
human to check the signing fingerprint before publishing. So never build and upload a
17201720
release artifact by hand — the point of the workflow is that the environment which
17211721
produced a published APK is knowable, which is also what a later move to F-Droid's
1722-
verified builds would need. `CONTRIBUTING.md` has the steps.
1722+
verified builds would need. `CONTRIBUTING.md` has the steps. The same goal is why
1723+
`android/build.gradle.kts` passes `-Wl,--build-id=none` to `jni`'s CMake: that build ID
1724+
was the only thing making two builds of one tag differ, and the comment there says how
1725+
it was measured.
17231726
- **The build CI hands out installs beside a real one, not over it.** Every
17241727
pull request's `Build Android APK` job uploads the arm64-v8a APK as an
17251728
artifact, so a change can be installed rather than only read. It is built with

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
Notable changes per release. Dates are release dates; the git tags carry the
44
exact commits.
55

6+
## 1.11.1 — 2026-09-05
7+
8+
- **Nothing changes in the app.** This release exists so that two builds of the same source
9+
come out byte for byte identical, which is what lets somebody else check that a published
10+
APK really was built from the code in this repository.
11+
612
## 1.11.0 — 2026-09-04
713

814
- **This version installs fresh rather than as an update, and you should export your data

android/build.gradle.kts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import com.android.build.gradle.LibraryExtension
2+
13
allprojects {
24
repositories {
35
google()
@@ -17,6 +19,39 @@ subprojects {
1719
}
1820
subprojects {
1921
project.evaluationDependsOn(":app")
22+
23+
// `package:jni` compiles libdartjni.so through CMake, and the linker stamps a
24+
// GNU build ID into it by default -- a hash that comes out different on every
25+
// machine even when the library itself does not. Measured on this project: the
26+
// APK published from CI and one built locally from the same tag differ in
27+
// exactly 20 bytes, and those 20 bytes are the build ID. Nothing reads it here,
28+
// and it is the one thing standing between two builds of the same source being
29+
// byte for byte the same.
30+
//
31+
// That matters because of what F-Droid can then do: with `binary:` in the build
32+
// recipe it rebuilds a release from source, compares it against the APK
33+
// published here, and on a match ships *this project's* signed APK rather than
34+
// one of its own -- so somebody moving from a GitHub download to F-Droid keeps
35+
// their install and their database. The comparison is a signature copy, which
36+
// v2 signatures make equivalent to byte equality, so 20 bytes is as fatal as a
37+
// megabyte.
38+
//
39+
// Scoped to `jni` rather than applied to every subproject: it is the only module
40+
// here that builds native code of its own, and a flag that reaches libraries
41+
// nobody has looked at is a change whose effects nobody has looked at either.
42+
plugins.withId("com.android.library") {
43+
if (name == "jni") {
44+
extensions.configure<LibraryExtension>("android") {
45+
defaultConfig {
46+
externalNativeBuild {
47+
cmake {
48+
arguments += "-DCMAKE_SHARED_LINKER_FLAGS=-Wl,--build-id=none"
49+
}
50+
}
51+
}
52+
}
53+
}
54+
}
2055
}
2156

2257
tasks.register<Delete>("clean") {

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ publish_to: 'none'
77

88
# In Android, build-name is used as versionName while build-number is used as
99
# versionCode; both can be overridden with `flutter build --build-name/--build-number`.
10-
version: 1.11.0+12
10+
version: 1.11.1+13
1111

1212
environment:
1313
sdk: ^3.12.0

0 commit comments

Comments
 (0)