build.gradle

8.8 KB · raw

1plugins {2    id "com.android.application"3    id "org.jetbrains.kotlin.android"4    id "org.jetbrains.kotlin.plugin.compose"5    id "org.jetbrains.kotlin.plugin.parcelize"6    id "org.jetbrains.kotlin.plugin.serialization"7    id "kotlin-kapt"8    id "com.google.dagger.hilt.android"9}1011android {12    namespace "com.peachpasswords"13    compileSdk 351415    // VERSION is the single semantic-version authority. versionCode remains16    // Android/Gradle metadata because Kepr's manifest does not carry it; the17    // updater enforces exact VERSION plus a strictly newer code.18    def versionAuthorityFile = rootProject.file("VERSION")19    if (!versionAuthorityFile.isFile()) {20        throw new GradleException("VERSION is missing; it is the semantic-version authority")21    }22    def semanticVersion = versionAuthorityFile.getText("UTF-8").trim()23    if (!(semanticVersion ==~ /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/)) {24        throw new GradleException("VERSION must contain exactly one strict major.minor.patch value")25    }26    if (semanticVersion.split("\\.").any { it.toBigInteger() > Integer.MAX_VALUE }) {27        throw new GradleException("VERSION contains a semantic-version component outside Gradle's supported range")28    }2930    defaultConfig {31        applicationId "com.peachpasswords"32        minSdk 2633        targetSdk 3534        // Keep the Android code in Gradle; the semantic name comes from root VERSION.35        versionCode 24014636        versionName semanticVersion3738        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"39        vectorDrawables {40            useSupportLibrary true41        }42    }4344    signingConfigs {45        release {46            // Read from local.properties (koh-ignored) so the keystore and its47            // password never enter version history. Absent on a machine without48            // the key -> release build stays unsigned rather than failing.49            def props = new Properties()50            def f = rootProject.file("local.properties")51            if (f.exists()) { f.withInputStream { props.load(it) } }52            if (props.getProperty("peachStoreFile")) {53                storeFile file(props.getProperty("peachStoreFile"))54                storePassword props.getProperty("peachStorePassword")55                keyAlias props.getProperty("peachKeyAlias")56                keyPassword props.getProperty("peachKeyPassword")57            }58            // v3 is the only escape hatch from "this key is forever": it carries a59            // rotation lineage, so a future key can be proven to descend from this60            // one instead of forcing every tester to uninstall and lose their61            // vault. AGP leaves it off unless asked.62            enableV2Signing true63            enableV3Signing true64        }65    }6667    // ABI splits were tried and removed: the native libraries are ~2.5 MB of a68    // 24 MB APK, so per-ABI builds saved 8% in exchange for four artifacts and69    // a "which one do I need?" question at every install. The weight is 62 MB of70    // DEX, because `minifyEnabled false` below leaves R8 off entirely — that is71    // the lever worth pulling, and it needs its own pass with real-device72    // verification (kotlinx.serialization, BouncyCastle, Hilt, Compose).7374    buildTypes {75        debug {76            applicationIdSuffix ".debug"77            versionNameSuffix "-debug"78            debuggable true79        }80        release {81            signingConfig signingConfigs.release82            minifyEnabled false83            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"84        }85    }8687    compileOptions {88        sourceCompatibility JavaVersion.VERSION_1789        targetCompatibility JavaVersion.VERSION_1790    }9192    kotlinOptions {93        jvmTarget = "17"94    }9596    buildFeatures {97        compose true98        buildConfig true99    }100101    composeOptions {102        kotlinCompilerExtensionVersion "1.5.15"103    }104105    packaging {106        resources {107            excludes += [108                "/META-INF/{AL2.0,LGPL2.1}",109                "META-INF/DEPENDENCIES",110                "META-INF/LICENSE*",111                "META-INF/NOTICE*",112            ]113        }114    }115116    testOptions {117        unitTests.all {118            def coreDir = rootProject.file("../peach-browser/crypto-core")119            def nativeLibrary = new File(120                coreDir,121                "target/release/libpeach_noise_core.dylib",122            )123            if (coreDir.exists()) {124                dependsOn rootProject.tasks.named("buildRustNoiseHost")125                systemProperty "peach.noise.library.path", nativeLibrary.absolutePath126            }127        }128    }129}130131dependencies {132    implementation platform("androidx.compose:compose-bom:2024.06.00")133    androidTestImplementation platform("androidx.compose:compose-bom:2024.06.00")134135    implementation "androidx.activity:activity-compose:1.9.2"136    implementation "androidx.autofill:autofill:1.1.0"137    implementation "androidx.biometric:biometric:1.1.0"138    implementation "androidx.core:core-splashscreen:1.0.1"139    implementation "androidx.appcompat:appcompat:1.7.0"140    implementation "androidx.credentials:credentials:1.5.0"141    implementation "androidx.credentials:credentials-play-services-auth:1.5.0"142    implementation "androidx.glance:glance-appwidget:1.1.0"143    implementation "androidx.glance:glance-material3:1.1.0"144    implementation "androidx.hilt:hilt-navigation-compose:1.2.0"145    // In-app updates: a periodic release check that survives Doze without a146    // service. hilt-work lets the worker take UpdateRepository by injection147    // rather than reaching for a global.148    implementation "androidx.hilt:hilt-work:1.2.0"149    kapt "androidx.hilt:hilt-compiler:1.2.0"150    implementation "androidx.work:work-runtime-ktx:2.9.1"151    implementation "androidx.lifecycle:lifecycle-runtime-compose:2.8.4"152    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4"153    implementation "androidx.lifecycle:lifecycle-process:2.8.4"154    implementation "androidx.navigation:navigation-compose:2.8.0"155    // Deliberately pinned to 1.1.0-alpha06 (audit M-12). 1.1.0 stable exists156    // now and GradleDependency lint flags this coordinate; a bump is a policy157    // choice (Tink runtime vs. baseline AES, master-key rotation semantics),158    // not an oversight, and is tracked separately. Exact alpha (never a floating159    // range) so the resolved artifact is reproducible. Used only for the160    // duress/license EncryptedSharedPreferences; the vault slots are sealed by161    // VaultCrypto, not this.162    implementation "androidx.security:security-crypto:1.1.0-alpha06"163    implementation "androidx.compose.material3:material3"164    implementation "androidx.compose.ui:ui"165    implementation "androidx.compose.ui:ui-tooling-preview"166    implementation "androidx.compose.foundation:foundation"167    implementation "androidx.compose.material:material-icons-extended"168    implementation "androidx.core:core-ktx:1.13.1"169    implementation "com.google.android.material:material:1.12.0"170171    implementation "com.google.dagger:hilt-android:2.51.1"172    kapt "com.google.dagger:hilt-compiler:2.51.1"173    implementation "com.google.zxing:core:3.5.3"174    implementation "androidx.camera:camera-core:1.3.4"175    implementation "androidx.camera:camera-camera2:1.3.4"176    implementation "androidx.camera:camera-lifecycle:1.3.4"177    implementation "androidx.camera:camera-view:1.3.4"178    implementation "com.squareup.okhttp3:okhttp:4.12.0"179    implementation "org.bouncycastle:bcprov-jdk18on:1.78.1"180    // zstd-jni (reference libzstd) — per-section compression for the PeachScript181    // PCHS binary format (MF-2). Required for cross-platform interop with the182    // browser's zstd sections. The @aar variant ships the Android jniLibs183    // (lib/<abi>/libzstd-jni.so); the plain jar bundles only desktop natives and184    // would fail with UnsatisfiedLinkError on-device.185    implementation "com.github.luben:zstd-jni:1.5.6-3@aar"186    // The @aar ships only Android .so; the plain jar carries the desktop natives187    // the host JVM unit tests need.188    testImplementation "com.github.luben:zstd-jni:1.5.6-3"189    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"190    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1"191192    debugImplementation "androidx.compose.ui:ui-tooling"193    debugImplementation "androidx.compose.ui:ui-test-manifest"194195    androidTestImplementation "androidx.test.ext:junit:1.2.1"196    androidTestImplementation "androidx.test.espresso:espresso-core:3.6.1"197    androidTestImplementation "androidx.compose.ui:ui-test-junit4"198199    testImplementation "junit:junit:4.13.2"200    // Real org.json on the unit-test classpath; android.jar's is a throwing stub,201    // so the release-manifest parser would otherwise be untestable off-device.202    testImplementation "org.json:json:20240303"203    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1"204}