This document explains how to build P.CASH Wallet for F-Droid with reproducible builds enabled.
F-Droid requires reproducible builds to verify that the published APK matches the source code. The main challenge is that baseline profiles (assets/dexopt/baseline.prof) are non-deterministic and differ between builds.
Solution: Pass -Pfdroid=true gradle property to disable baseline profile generation.
| Build Type | Baseline Profiles | Flag |
|---|---|---|
| Play Store | Enabled (better startup performance) | None |
| F-Droid | Disabled (reproducible) | -Pfdroid=true |
The F-Droid build metadata is maintained in the fdroiddata repository.
File: metadata/cash.p.terminal.yml
Builds:
- versionName: 0.51.4
versionCode: 207
commit: 0.51.4
subdir: app
submodules: true
gradle:
- yes
gradleProps:
- fdroid=trueBuilds:
- versionName: 0.51.4
versionCode: 207
commit: 0.51.4
subdir: app
submodules: true
build: ../gradlew assembleRelease -Pfdroid=trueReplicates F-Droid's exact build environment:
# Clone repository at specific version
git clone --branch 0.51.4 --depth 1 https://github.com/piratecash/pcash-wallet-android
cd pcash-wallet-android
# Build using F-Droid's buildserver image
docker run --rm \
-v "$PWD":/repo \
-w /repo \
registry.gitlab.com/fdroid/fdroidserver:buildserver \
bash -c './gradlew clean :app:assembleRelease -Pfdroid=true'
# APK output location
ls -la app/build/outputs/apk/release/# Clone and checkout version
git clone https://github.com/piratecash/pcash-wallet-android
cd pcash-wallet-android
git checkout 0.51.4
# Build with F-Droid flag
./gradlew clean :app:assembleRelease -Pfdroid=true
# APK output
ls -la app/build/outputs/apk/release/# Check APK contents
unzip -l app/build/outputs/apk/release/*.apk | grep baseline
# Expected results:
# With -Pfdroid=true → No output (disabled)
# Without flag → Shows assets/dexopt/baseline.profManual comparison with apktool:
# Extract both APKs
apktool d -o /tmp/local-build local-build.apk
apktool d -o /tmp/fdroid-build fdroid-build.apk
# Compare
diff -r /tmp/local-build /tmp/fdroid-build
# Visual comparison (requires meld)
meld /tmp/local-build /tmp/fdroid-buildExpected: No differences, or only signature-related differences.
| Issue | Cause | Solution |
|---|---|---|
baseline.prof in diff |
Flag not passed | Add -Pfdroid=true to gradle command |
classes*.dex differs |
Baseline profile included | Verify -Pfdroid=true is set |
| Resource ordering differs | Non-deterministic processing | Use F-Droid's docker image |
| JDK version mismatch | Different Java versions | Match F-Droid's JDK (currently 21) |
| Gradle version mismatch | Wrapper not used | Always use ./gradlew |
The app/build.gradle contains:
// F-Droid reproducible builds: when invoked with -Pfdroid=true, disable ART profile
// packaging so the APK omits assets/dexopt/baseline.prof and baseline.profm.
if (project.hasProperty('fdroid')) {
tasks.matching { it.name.contains('ArtProfile') }.configureEach {
enabled = false
}
}When -Pfdroid=true is passed, all tasks containing "ArtProfile" in their name are disabled, so the APK ships without the baseline profile — keeping F-Droid builds byte-reproducible. Non-F-Droid channels (Google Play, direct APK) build without the flag and keep the profile.
- F-Droid Reproducible Builds
- fdroiddata Repository
- F-Droid Build Metadata Reference
- WalletScrutiny - Wallet verification service