F-Droid unterstützt reproduzierbare Builds von Apps, so dass jeder den Build-Prozess erneut ausführen und das gleiche APK wie das Original-Release reproduzieren kann. Dies bedeutet, dass F-Droid überprüfen kann, ob eine Anwendung 100% freie Software ist, während die APK-Signaturen des ursprünglichen Entwicklers verwendet werden. F-Droid verifiziert reproduzierbare Builds anhand von APK-Signaturkopie.
Dieses Konzept wird gelegentlich als „deterministische Builds“ bezeichnet. Das ist ein viel strengerer Standard: es bedeutet, dass der gesamte Prozess jedes Mal in der gleichen Reihenfolge abläuft. Das Wichtigste ist, dass jeder den Prozess ausführen kann und am Ende genau das gleiche Ergebnis hat.
Wie es ab sofort umgesetzt wird
Die Veröffentlichung signierter Binärdateien (APKs) von anderswo (z. B. vom
Upstream-Entwickler) ist nun möglich, wenn die Überprüfung zeigt, dass sie
nach Herstellung mittels eines fdroiddata-Rezeptes exakt
übereinstimmen. Dieser Vorgang ist als Teil von fdroid publish
implementiert. Die Prüfung der Reproduzierbarkeit im
Veröffentlichungsschritt folgt dieser Logik:
Veröffentlichung von APKs, die sowohl von (Upstream-)Entwicklern als auch von F-Droid signiert sind
Diese Vorgehensweise ermöglicht eine Veröffentlichung sowohl von APKs, die vom (Upstream-)Entwickler signiert sind, als auch solchen, die von F-Droid signiert sind. Dies versetzt uns in die Lage, Aktualisierungen an Benutzer auszuliefern, die Apps aus anderen Quellen als F-Droid (z. B. aus dem Play Store) installiert haben, und gleichzeitig Aktualisierungen für Apps zu verschicken, die von F-Droid erstellt und signiert wurden.
Dazu müssen (Upstream-)Entwicklersignaturen extrahiert und in fdroiddata eingefügt werden. Diese Signaturen werden dann später aus dem fdroiddata-Rezept in die unsignierte APK kopiert. Wir bieten einen Befehl zum einfachen Extrahieren von Signaturen aus APKs:
$ cd /pfad/zum/fdroiddata
$ fdroid signatures F-Droid.apk
Anstelle von lokalen Dateien können Sie auch HTTPS-URLs an fdroid
signatures
übergeben.
Die Signaturdateien werden gebrauchsfertig für fdroid publish
in das
entsprechende Metadatenverzeichnis der App extrahiert. Eine Signatur
besteht aus 2-6 Dateien: einer v1-Signatur (Manifest, Signatur-Datei und
Signatur-Blockdatei) und/oder einer v2/v3-Signatur (APK-Signier-Block und
Offset); war die APK mit z. B. signflinger
statt apksigner
v1-signiert,
gibt es zusätzlich eine differences.json
. Das Ergebnis des Extrahierens
ähnelt diesen Dateilisten:
$ ls metadata/org.fdroid.fdroid/signatures/1000012/ # v1 signature only
CIARANG.RSA CIARANG.SF MANIFEST.MF
$ ls metadata/your.app/signatures/42/ # v1 + v2/v3 signature
APKSigningBlock APKSigningBlockOffset MANIFEST.MF YOURKEY.RSA YOURKEY.SF
Wenn Sie fdroidserver
nicht installieren wollen (oder eine ältere Version
haben, die das Extrahieren von v2/v3-Signaturen noch nicht unterstützt),
können Sie auch apksigcopier
(verfügbar z. B. in Debian, Ubuntu, Arch Linux, NixOS) anstelle von
fdroid signatures
verwenden:
$ cd /path/to/fdroiddata
$ APPID=your.app VERSIONCODE=42
$ mkdir metadata/$APPID/signatures/$VERSIONCODE
$ apksigcopier extract --v1-only=auto Your.apk metadata/$APPID/signatures/$VERSIONCODE
Veröffentlichung von APKs, die ausschließlich von (Upstream-)Entwicklern signiert sind
Um diesen älteren Ansatz zu verwenden, sollte alles in den Metadaten wie
üblich sein plus der Anweisung Binaries:
, um festzulegen, woher die
Binärdateien (APKs) kommen sollen. In diesem Fall wird F-Droid niemals
versuchen, von F-Droid signierte APKs zu veröffentlichen. Wenn fdroid
publish
verifizieren kann, dass das heruntergeladene APK mit dem nach dem
fdroiddata-Rezept hergestellten übereinstimmt, wird das heruntergeladene APK
veröffentlicht. Andernfalls überspringt F-Droid die Veröffentlichung dieser
Version der App.
Hier ein Beispiel für eine Binaries
-Anweisung:
Binaries: https://example.com/path/to/myapp-%v.apk
Siehe auch: Build-Metadaten-Referenz - Binaries
Reproduzierbare Signaturen
F-Droid verifiziert reproduzierbare Builds anhand der APK-Signatur (eine Form von eingebetteter Signatur, was das Kopieren der Signatur von einer signierten APK auf eine unsignierte APK erfordert, um dann zu prüfen, ob letztere verifiziert werden kann. Die alten v1 (JAR)-Signaturen decken nur den Inhalt der APK ab (z. B. ZIP-Metadaten und Reihenfolge sind irrelevant), aber v2/v3-Signaturen decken alle anderen Bytes in der APK ab. Die APKs müssen also vor und nach dem Signieren völlig identisch sein (abgesehen von der Signatur), um korrekt verifiziert werden zu können.
Das Kopieren der Signatur verwendet denselben Algorithmus, den apksigner
beim Signieren einer APK verwendet. Es ist daher wichtig, dass
(Upstream-)Entwickler beim Signieren von APKs dasselbe tun, idealerweise mit
apksigner
.
Verifikations-Builds
Viele Leute oder Organisationen werden daran interessiert sein, Builds zu reproduzieren, um sicherzustellen, dass die f-droid.org-Builds mit dem ursprünglichen Quellcode übereinstimmen und nichts verändert wurde. In diesem Fall werden die resultierenden APKs nicht zur Installation veröffentlicht. Der Verifikationsserver automatisiert diesen Vorgang.
Reproduzierbare Builds
Etliche Builds verifizieren bereits ohne zusätzlichen Aufwand, da Java-Code
oft von einer Vielzahl von Java-Versionen in den gleichen Bytecode
kompiliert wird. Die build-tools
des Android-SDKs erzeugen Unterschiede
in den resultierenden XML-, PNG-, usw. Dateien, aber das ist normalerweise
kein Problem, da die build.gradle
die genaue Version von build-tools
enthält.
Alles, was mit dem NDK gebaut wird, ist viel empfindlicher. Selbst für
Builds, die genau die gleiche Version des NDK verwenden (z. B. r13b
), aber
auf verschiedenen Plattformen (z. B. macOS gegenüber Ubuntu), werden die
resultierenden Binärdateien Unterschiede aufweisen.
Zusätzlich müssen wir nach allem Ausschau halten, was Zeitstempel oder Build-Pfade, Sortierreihenfolge usw. enthält.
Google arbeitet auch an reproduzierbaren Builds von Android-Apps, so dass die Verwendung aktueller Versionen des Android-SDKs hilft. Ein spezieller Fall beginnt mit dem Gradle Android Plugin v2.2.2, Zeitstempel in den ZIP-Metadaten der APK-Datei werden automatisch auf Null gesetzt.
Debugging reproduzierbarer Builds
Empfohlene Werkzeuge
Wir empfehlen die Verwendung von diffoscope
, um
die Unterschiede zwischen dem von den App-Entwicklern bereitgestellten
Referenz-APK und dem APK, das fdroidserver
herstellte, herauszufinden.
Sie finden das APK, das fdroidserver
herstellte entweder unter z. B.
fdroiddata/build/com.example.app/app/build/outputs/apk/prod/release/example-1.0.0-prod-release-unsigned.apk
(wenn er lokal läuft) oder in den Pipeline Artifacts (bei Verwendung von
GitLab CI). Passen Sie den Pfad entsprechend an (z. B. für von prod
abweichenden Varianten).
Priorisierung und Beheben von Unterschieden
Die Anleitung: APKs für Reproduzierbare Builds differenzieren und einrichten im Wiki von F-Droid enthält detaillierte Informationen über die verschiedenen Arten der im Allgemeinen anzutreffenden Abweichungen, welchen Abweichungen normalerweise beim Debugging der Vorzug gegeben werden sollte und wie verbreitete Probleme gelöst werden.
Sie zeigt auch, wie verschiedene spezialisierte Tools verwendet werden
können, die möglicherweise bessere Ergebnisse liefern, wenn diffoscope
nicht ausreicht.
Reproduzierbare APK-Tools
Die Skripte aus
reproducible-apk-tools
(als srclib
in fdroiddata enthalten) können dabei helfen, Builds
reproduzierbar zu gestalten, z. B. durch Korrektur von Zeilenvorschüben
(CRLF gegen LF) oder Schaffung einer deterministischen ZIP-Ordnung, wenn die
Entfernung der für die Unterschiede verantwortlichen Ursachen keine
realistische Option bietet. Abhängig von speziellen Details, müssen diese
Skripte von Upstream-Entwicklern vor dem Signieren ihrer APKs durch sie
selbst und/oder durch das fdroiddata-Rezept angewandt werden.
Ursprünglich geschaffen, um Non-Determinismus in den Build-Vorgang
einzuführen, kann
disorderfs auch
das Gegenteil ausführen: das Auslesen des Dateisystems deterministisch
vornehmen. In einigen Fällen kann dies z. B. resources.arsc
reproduzierbar machen. Hier ein Beispiel eines bestehenden Rezepts:
$ mv my.app my.app_underlying
$ disorderfs --sort-dirents=yes --reverse-dirents=no my.app_underlying my.app
Mögliche Ursachen für nicht reproduzierbare Builds
Es gibt verschiedene Möglichkeiten, wie Builds nicht reproduzierbar sein können. Einige sind relativ leicht zu vermeiden, andere sind schwer zu beheben. Im Folgenden haben wir versucht, einige häufige Ursachen aufzulisten.
Siehe auch dieses GitLab-Ticket.
Fehler: Android Studio-Builds haben eine nicht-deterministische ZIP-Reihenfolge
Nicht vorhersehbare Reihenfolge der ZIP-Einträge in APK macht Builds unreproduzierbar (erfordert möglicherweise ein Google-Konto zur Ansicht).
Hinweis: Dies sollte in Android Gradle Plugin
(com.android.tools.build:gradle
/ com.android.application
) 7.1.X
und
später behoben werden.
Bei der Erstellung von APKs mit Android Studio kann die Reihenfolge der
ZIP-Einträge in der APK anders sein als bei APKs, die durch den direkten
Aufruf von gradle
erstellt wurden, was die Reproduzierbarkeit
beeinträchtigt; die Reihenfolge kann völlig unbestimmt sein und sich sogar
zwischen verschiedenen Builds desselben Quellcodes unterscheiden.
Ein Workaround für ältere Versionen ist der direkte Aufruf von gradle
(wie
bei F-Droid oder CI-Builds) unter Umgehung von Android Studio:
$ ./gradlew assembleRelease
NB: Je nach Ihrer Signierkonfiguration kann es erforderlich sein, die APK
anschließend mit apksigner
zu signieren, da die Signierung in diesem Fall
nicht von Android Studio durchgeführt wird.
Fehler: baseline.profm nicht deterministisch
Non-stable
assets/dexopt/baseline.profm
(erfordert möglicherweise ein Google-Konto zur Ansicht).
Siehe auch diesen Bericht über Abhilfen.
Fehler: coreLibraryDesugaring nicht deterministisch
Hinweis: Dies sollte in R8 (com.android.tools:r8
) ab Version 3.0.69
behoben sein.
In einigen Fällen sind Builds nicht reproduzierbar aufgrund eines Fehlers
in
coreLibraryDesugaring
(erfordert möglicherweise ein Google-Konto zur Ansicht); dies betraf
NewPipe.
Bug: Unterschiede in den Zeilenendungen zwischen Windows- und Linux-Builds
Unterschiede am Zeilenende zwischen Builds unter Windows und Linux machen sie unreproduzierbar (erfordert möglicherweise ein Google-Konto, um angezeigt zu werden).
Eine Abhilfe besteht darin,
fix-newlines.py
auf der unsignierten APK mit den “falschen” Zeilenenden auszuführen, um
sie von LF in CRLF zu ändern (oder umgekehrt mit --from-crlf
) und es
danach wieder zu zipalign
en.
Parallelität: Die Reproduzierbarkeit kann von der Anzahl der CPUs/Kerne abhängen
Dies kann .dex
Dateien (obwohl dies selten zu sein scheint) oder nativen
Code (z. B. Rust) betreffen.
Verwendung von nur 1 CPU/Kern als Workaround:
export CPUS_MAX=1
export CPUS=$(getconf _NPROCESSORS_ONLN)
for (( c=$CPUS_MAX; c<$CPUS; c++ )) ; do echo 0 > /sys/devices/system/cpu/cpu$c/online; done
Hinweis: Diese Umgehung wirkt sich auf die gesamte Maschine aus, daher wird empfohlen, sie in einer nicht-persistenten virtuellen Maschine oder einem Container zu verwenden.
Für Rust-Code können Sie codegen-units =
1
einstellen.
Siehe auch dieses GitLab-Ticket.
Eingebettete Buildpfade
Eingebettete Build-Pfade
sind eine Quelle für Probleme mit der Reproduzierbarkeit, die Apps
betreffen, die z. B. mit Flutter, python-for-android oder mit nativem Code
(z. B. Rust, C/C++, jede Art von libfoo.so
) erstellt wurden. Apps, die
vollständig in Java und/oder Kotlin geschrieben wurden, sind in der Regel
nicht davon betroffen.
Oft ist die einfachste Lösung, immer dasselbe Arbeitsverzeichnis für die
Erstellung zu verwenden, z. B. /builds/fdroid/fdroiddata/build/your.app.id
(F-Droid CI), /home/vagrant/build/your.app.id
(F-Droid build server),
/tmp/build
, oder eines zu erstellen, um die vom Upstream verwendeten
Ordner zu spiegeln, z. B. für macOS /Users/runner
.
Hinweis: Die Verwendung eines Unterverzeichnisses im von allen
beschreibbaren /tmp
kann (auf Mehrbenutzersystemen) zu
Sicherheitsbeeinträchtigungen führen.
Wenn der SDK-Pfad in Flutter eingebettet endet, kann man das SDK in der Rezeptur
in den besagten Pfad verschieben und es mit: flutter config --android-sdk <path>
konfigurieren,
da die Festlegung von ANDROID_SDK_ROOT
unter Umständen nicht ausreichend sein kann.
Eingebettete Zeitstempel
Eingebettete Zeitstempel sind die häufigste Ursache für Probleme mit der Reproduzierbarkeit und sollten vermieden werden.
Native Bibliothek strippen
Es scheint, dass das Strippen von nativen Bibliotheken, z. B. libfoo.so
,
zeitweise Reproduzierbarkeitsprobleme verursachen kann. Es ist wichtig,
beim Neuaufbau die genaue NDK-Version zu verwenden, z. B. r21e
. Das
Deaktivieren von Stripping kann manchmal helfen. Gradle scheint
freigegebene Bibliotheken standardmäßig zu strippen, auch wenn die App die
freigegebenen Bibliotheken über eine AAR-Bibliothek erhält. Hier erfahren
Sie, wie Sie es in Gradle deaktivieren können:
android {
packagingOptions {
doNotStrip '**/*.so'
}
}
NDK build-id
Auf verschiedenen Build-Maschinen werden unterschiedliche NDK-Pfade und
unterschiedliche Pfade zum Projekt (und damit zu seinem jni
-Verzeichnis)
verwendet. Dies führt zu unterschiedlichen Pfaden zu den Quelldateien in
Debug-Symbolen, was den Linker veranlasst, eine andere Build-ID zu
erzeugen, die nach dem Strippen erhalten bleibt.
Eine mögliche Lösung ist die Übergabe von --build-id=none
an den Linker,
der die build-id-Erzeugung komplett deaktiviert.
NDK-Hash-Stil
LLVM übergibt verschiedene Standards an Linker auf verschiedenen
Plattformen. Nachdem dieser
Commit
ins NDK integriert wurde, wird in Debian --hash-style=gnu
als Standard
verwendet. Um den Hash-Typ zu ändern, kann --hash-style=gnu
an den Linker
übergeben werden.
platform Revisionen
Im Jahr 2014 wurden die Android SDK-Tools
geändert auf stick
two
data
elements
in AndroidManifest.xml
als Teil des Build-Prozesses:
platformBuildVersionName
und platformBuildVersionCode
.
platformBuildVersionName
enthält die „Revision“ des Pakets platform,
gegen das gebaut wurde (z. B. android-23
), jedoch können verschiedene
“Revisionen” desselben Pakets platform nicht parallel installiert werden.
Außerdem unterstützen die SDK-Tools nicht die Angabe der erforderlichen
Revision als Teil des Build-Prozesses. Dies führt oft zu einem ansonsten
reproduzierbaren Build, wobei der einzige Unterschied das Attribut
platformBuildVersionName
ist.
Die platform ist Teil des Android SDK, das die Standardbibliothek
darstellt, die auf dem Telefon installiert ist. Die Version besteht aus
zwei Teilen: „Versionscode“, eine ganze Zahl, die das SDK-Release
repräsentiert, und die „Revision“, die Bugfix-Versionen für jede Plattform
repräsentiert. Diese Versionen sind in der mitgelieferten Datei
build.prop
zu finden. Jede Revision hat eine andere Nummer in
ro.build.version.incremental
. Gradle hat keine Möglichkeit, die Revision
in compileSdkVersion
oder targetSdkVersion
anzugeben. Es kann jeweils
nur eine Plattform-23
installiert werden, im Gegensatz zu build-tools
,
wo jede Version parallel installiert werden kann.
Hier sind zwei Beispiele, bei denen alle Unterschiede vermutlich von verschiedenen Revisionen der Plattform herrühren:
- https://verification.f-droid.org/de.nico.asura_12.apk.diffoscope.html
- https://verification.f-droid.org/de.nico.ha_manager_25.apk.diffoscope.html
PNG Crush/Crunch
Ein Standardbestandteil des Android-Buildprozesses ist es, eine Art
PNG-Optimierungswerkzeug wie aapt singleCrunch
, pngcrush
, zopflipng
oder optipng
auszuführen. Diese liefern keine deterministische Ausgabe,
es ist immer noch eine offene Frage, warum. Da PNGs normalerweise in das
Quell-Repo committed sind, besteht eine Lösung für dieses Problem darin, das
Tool Ihrer Wahl auf den PNG-Dateien auszuführen und diese Änderungen dann in
das Quell-Repo zu übertragen (z. B. git
). Deaktivieren Sie dann den
standardmäßigen PNG-Optimierungsprozess, indem Sie diesen in build.gradle
einfügen:
android {
aaptOptions {
cruncherEnabled = false
}
}
Zu beachten ist, dass Werkzeuge wie svgo
ähnliche Optimierungen an
SVG-Dateien vornehmen können.
PNGs, die aus Vektorgrafiken erzeugt wurden
Android Gradle Plugin generiert PNG-Ressourcen aus Vektor-Drawables für alte Android-Versionen. Leider sind die generierten PNG-Dateien nicht reproduzierbar.
Sie können die Generierung der PNGs deaktivieren, indem Sie dies zu
build.gradle
hinzufügen:
android {
defaultConfig {
vectorDrawables.generatedDensities = []
}
}
R8-Optimierer
Es kommt vor, dass einige R8-Optimierungen nicht-deterministisch sind und bei verschiedenen Build-Durchläufen unterschiedlichen Bytecode erzeugen.
Beispielsweise versucht R8, die ServiceLoader
-Nutzung zu optimieren, indem
eine statische Liste aller Dienste im Code erzeugt wird. Die Anordnung
dieser Liste kann bei jedem Build-Durchlauf unterschiedlich (oder sogar
unvollständig) sein. Die einzige Möglichkeit, dieses Verhalten zu
verhindern, ist die Deaktivierung solcher Optimierungen durch Deklaration
optimierter Klassen in proguard-rules.pro
:
-keep class kotlinx.coroutines.CoroutineExceptionHandler
-keep class kotlinx.coroutines.internal.MainDispatcherFactory
Seien Sie vorsichtig im Umgang mit R8. Testen Sie Ihre Builds immer mehrere Male und deaktivieren Sie Optimierungen, die nicht-deterministische Ausgaben erzeugen.
Ressourcen schrumpfen
Es ist möglich die APK-Dateigröße zu reduzieren, indem nicht verwendete Ressourcen aus dem Paket entfernt werden. Das ist praktisch, wenn ein Projekt von bestimmten aufgeblähten Bibliotheken, wie AppCompat, abhängt, insbesondere wenn R8/ProGuard zum Schrumpfen des Codes verwendet wird.
Allerdings kann es geschehen, dass der Ressourcen-Schrumpfer die APK-Größe auf verschiedenen Plattformen erhöht, insbesondere wenn es nicht viele Ressourcen zu schrumpfen gibt, sodass dann das Original-APK anstatt des geschrumpften verwendet wird (nicht-deterministisches Verhalten des Gradle-Plugin). Vermeiden Sie die Verwendung des Ressourcen-Schrumpfers, solange die APK-Dateigröße nicht signifikant verkleinert wird.
ZIP-Metadaten
APKs verwenden das ZIP-Dateiformat, das ursprünglich für das MSDOS FAT-Dateisystem entwickelt wurde. UNIX-Dateiberechtigungen wurden als Erweiterung hinzugefügt. APKs benötigen nur das einfachste ZIP-Format, ohne irgendwelche Erweiterungen. Diese Erweiterungen werden oft bei der finalen Versionssignierung entfernt. Aber der APK-Build-Prozess kann sie hinzufügen. Zum Beispiel:
--- a2dp.Vol_137.apk
+++ sigcp_a2dp.Vol_137.apk
@@ -1,50 +1,50 @@
--rw---- 2.0 fat 8976 bX defN 79-Nov-30 00:00 AndroidManifest.xml
--rw---- 2.0 fat 1958312 bX defN 79-Nov-30 00:00 classes.dex
--rw---- 1.0 fat 78984 bx stor 79-Nov-30 00:00 resources.arsc
+-rw-rw-rw- 2.3 unx 8976 b- defN 80-000-00 00:00 AndroidManifest.xml
+-rw---- 2.4 fat 1958312 b- defN 80-000-00 00:00 classes.dex
+-rw-rw-rw- 2.3 unx 78984 b- stor 80-000-00 00:00 resources.arsc
Nicht zusammenpassende Toolchains
Verschiedene Werkzeug-Programme können unterschiedliche Binärdateien erzeugen. Für gewöhnlich ist das so, wenn mehr als eine JDK-Version/Distribution verwendet werden, um das APK herzustellen. Manchmal kann sogar Gradle verschiedene JDK-Versionen beim Build eines APK mischen. Um solche Probleme zu vermeiden, sollten ungenutzte JDKs entfernt werden.
Das APK diff wird in den classes.dex
-Dateien Einträge wie diese aufweisen,
z. B. Java 17 vs. Java 11:
- .annotation system Ldalvik/annotation/Signature;
- value = {
- "()V"
- }
- .end annotation
Sprachspezifische Anweisungen
Native Bibliotheken können mit verschiedenen Werkzeugen und in vielen Sprachen erzeugt werden. Auch wenn sie mit ähnlichen Schwierigkeiten bei der Reproduzierbarkeit kämpfen, sind die Methoden, diese zu lösen, verschieden. Einige bekannte Lösungen sind im Folgenden aufgelistet:
ndk-build
LOCAL_LDFLAGS += -Wl,<linker args>
können in Android.mk
-Dateien oder
build.gradle
/build.gradle.kts
ergänzt werden:
android {
defaultConfig {
externalNativeBuild {
ndkBuild {
arguments "LOCAL_LDFLAGS += -Wl,<linker args>"
}
}
}
}
CMake
For CMake versions since 3.13, add_link_options(LINKER:<linker args>)
can be added to CMakeLists.txt
globally. For CMake versions before 3.13,
target_link_libraries(<target> LINKER:<linker args>)
can be used instead for
every target. It can also be set in Gradle files:
android {
defaultConfig {
externalNativeBuild.cmake {
cFlags "-DCMAKE_SHARED_LINKER_FLAGS=-Wl,<linker args>"
}
}
}
-ffile-prefix-map
can be used to remove embedded build path.
Golang
Linker-Argumente können zu CGO_LDFLAGS
hinzugefügt werden. Einige weitere
hilfreiche Argumente, die an go build
übergeben werden können, sind
-ldflags="-buildid="
, -trimpath
(um eingebettete Build-Pfade zu
vermeiden) und -buildvcs=false
.
Rust
Compiler- und Linker-Argumente können in Cargo build.rustflags
und rustc Codegen Options ergänzt werden.
Linker-Argumente können mit -C link-args=-Wl,<linker args>
hinzugefügt werden; --remap-path-prefix=<old>=<new>
kann eingefügt werden, um Build-Pfade zu zerlegen.
Die Rust-Toolchain sollte an dieselbe Version wie die des Upstreams geheftet werden. Dies kann bei der Installation von „rustup“ mit rustup-init.sh -y --default-toolchain <version>
erledigt werden.
Library-specific instructions
Some libraries generate non-deterministic code due to timestamps, unsorted iterations etc. Some known fixes are documented below:
Gradle-Plugin AboutLibraries
Sie können verhindern, dass dieses Plugin
(com.mikepenz.aboutlibraries.plugin
) einen Zeitstempel zu der JSON-Datei
hinzufügt, die es erzeugt, indem Sie dies zu build.gradle
hinzufügen:
aboutLibraries {
// Entfernen Sie den Zeitstempel "generated", um reproduzierbare Builds zu ermöglichen
excludeFields = ["generated"]
}
Fügen Sie für build.gradle.kts
stattdessen Folgendes hinzu:
aboutLibraries {
// Entfernen Sie den "generated" Zeitstempel, um reproduzierbare Builds zu ermöglichen
excludeFields = arrayOf("generiert")
}
EventBus
It generates non-deterministic code which can be sorted after the classes are generated. The detailed instructions can be found in Eternity’s source code.
Migration zu reproduzierbaren Builds
TODO
- jar-Sortierreihenfolge für APKs
aapt
Versionen liefern unterschiedliche Ergebnisse (XML und res/ Unterordnernamen)
Quellen
- https://gitlab.com/fdroid/fdroidserver/commit/8568805866dadbdcc6c07449ca6b84b80d0ab03c
- Verifikationsserver
- https://verification.f-droid.org
- https://reproducible-builds.org
- https://wiki.debian.org/ReproducibleBuilds
- https://gitian.org/
- [Google Issue #70292819 platform-27_r01.zip wurde mit einem neuen Update überschrieben](https://issuetracker.google.com/issues/70292819 (Google-Login und JavaScript erforderlich)
- Google Issue #37132313 platformBuildVersionName erschwert die Reproduzierbarkeit von Builds und erzeugt nicht benötigte Diffs (Google-Login und JavaScript erforderlich)
- Google Issue #110237303 resources.arsc ohne Determinismus erstellt, verhindert reproduzierbare APK-Builds (Google-Login und JavaScript erforderlich)
- Unreproducible/non-deterministic code generation by navigation.safeargs.kotlin (Google-Login und JavaScript erforderlich)
- Unnötige DEX-Code-Unterschiede basierend auf der Anzahl der im Build-Prozess verwendeten CPUs (Google-Login und JavaScript erforderlich)