Skip to content

Latest commit

 

History

History
148 lines (108 loc) · 4.24 KB

File metadata and controls

148 lines (108 loc) · 4.24 KB

F-Droid Reproducible Builds

This document explains how to build P.CASH Wallet for F-Droid with reproducible builds enabled.

Overview

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

F-Droid Metadata Configuration

The F-Droid build metadata is maintained in the fdroiddata repository.

File: metadata/cash.p.terminal.yml

Option 1: Using gradleProps (Recommended)

Builds:
  - versionName: 0.51.4
    versionCode: 207
    commit: 0.51.4
    subdir: app
    submodules: true
    gradle:
      - yes
    gradleProps:
      - fdroid=true

Option 2: Using Custom Build Command

Builds:
  - versionName: 0.51.4
    versionCode: 207
    commit: 0.51.4
    subdir: app
    submodules: true
    build: ../gradlew assembleRelease -Pfdroid=true

Building Locally

Method 1: F-Droid's Docker Image

Replicates 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/

Method 2: Manual Build

# 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/

Verification

Verify Baseline Profile is Disabled

# 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.prof

Compare APKs

Manual 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-build

Expected: No differences, or only signature-related differences.

Troubleshooting

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

How It Works

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.

References