build.gradle.kts 133 lignes · 5783 octets
import java.net.URI

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("org.jetbrains.kotlin.plugin.compose")
    id("org.jetbrains.kotlin.plugin.serialization")
    id("com.google.devtools.ksp")
}

/** `fast` (défaut, ~18 Mo) ou `full` (~80 Mo+). Ex. : ./gradlew assembleDebug -Ptessdata=full */
val tessdataVariant: String =
    (findProperty("tessdata") as String?)?.lowercase()?.trim().orEmpty().ifEmpty { "fast" }
require(tessdataVariant == "fast" || tessdataVariant == "full") {
    "Propriété -Ptessdata= invalide (« $tessdataVariant ») — utiliser fast ou full"
}

val tessdataLanguages = listOf("fra", "deu", "eng", "spa", "por", "ita", "pol")
val tessdataCacheDir = rootProject.layout.projectDirectory.dir("tessdata-cache/$tessdataVariant")
val tessdataGeneratedAssets = layout.buildDirectory.dir("generated/tessdataAssets")

android {
    namespace = "fr.ebii.card2vcf"
    compileSdk = 35
    defaultConfig {
        applicationId = "fr.ebii.card2vcf"
        minSdk = 31
        targetSdk = 35
        versionCode = 1
        versionName = "0.1.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters += listOf("arm64-v8a")
        }
    }
    buildFeatures {
        compose = true
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_21
        targetCompatibility = JavaVersion.VERSION_21
    }
    kotlinOptions { jvmTarget = "21" }
    testOptions {
        unitTests.isReturnDefaultValues = true
        unitTests.isIncludeAndroidResources = true
    }
    sourceSets.getByName("main").assets.srcDir(tessdataGeneratedAssets)
}

val prepareTessdata by tasks.registering {
    group = "build"
    description = "Télécharge (cache) et prépare les traineddata Tessdata ($tessdataVariant)"
    inputs.property("variant", tessdataVariant)
    inputs.property("languages", tessdataLanguages.joinToString(","))
    outputs.dir(tessdataGeneratedAssets)
    doLast {
        val cache = tessdataCacheDir.asFile.apply { mkdirs() }
        val outDir = tessdataGeneratedAssets.get().asFile
            .resolve("tesseract/tessdata")
            .apply { mkdirs() }
        val repo = if (tessdataVariant == "fast") "tessdata_fast" else "tessdata"
        for (lang in tessdataLanguages) {
            val cached = cache.resolve("$lang.traineddata")
            if (!cached.isFile || cached.length() < 10_000L) {
                val url = "https://github.com/tesseract-ocr/$repo/raw/main/$lang.traineddata"
                logger.lifecycle("Téléchargement $repo/$lang.traineddata …")
                URI(url).toURL().openStream().use { input ->
                    cached.outputStream().use { output -> input.copyTo(output) }
                }
                check(cached.isFile && cached.length() >= 10_000L) {
                    "Échec téléchargement $url"
                }
            }
            cached.copyTo(outDir.resolve("$lang.traineddata"), overwrite = true)
        }
        outDir.resolve("variant.txt").writeText(tessdataVariant)
        outDir.resolve("README.md").writeText(
            "Généré au build (variante=$tessdataVariant). Ne pas éditer.\n" +
                "Cache : android/tessdata-cache/$tessdataVariant/\n"
        )
        logger.lifecycle("Tessdata $tessdataVariant prêt (${tessdataLanguages.size} langues).")
    }
}

tasks.matching {
    it.name.startsWith("merge") && it.name.endsWith("Assets")
}.configureEach {
    dependsOn(prepareTessdata)
}
tasks.named("preBuild").configure { dependsOn(prepareTessdata) }

dependencies {
    implementation(platform("androidx.compose:compose-bom:2024.09.02"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.compose.material:material-icons-core")
    implementation("androidx.compose.material:material-icons-extended")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.activity:activity-compose:1.9.2")
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.6")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.6")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
    implementation("androidx.camera:camera-camera2:1.4.1")
    implementation("androidx.camera:camera-lifecycle:1.4.1")
    implementation("androidx.camera:camera-view:1.4.1")
    implementation("org.opencv:opencv:4.10.0")
    implementation("com.github.adaptech-cz.Tesseract4Android:tesseract4android-openmp:4.9.0")
    implementation("androidx.exifinterface:exifinterface:1.3.7")

    val room = "2.6.1"
    implementation("androidx.room:room-runtime:$room")
    implementation("androidx.room:room-ktx:$room")
    ksp("androidx.room:room-compiler:$room")
    implementation("androidx.navigation:navigation-compose:2.8.2")
    testImplementation("androidx.room:room-testing:$room")

    testImplementation("junit:junit:4.13.2")
    testImplementation("org.jetbrains.kotlin:kotlin-test:2.0.20")
    testImplementation("org.robolectric:robolectric:4.13")
    testImplementation("androidx.test:core:1.6.1")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")

    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    testImplementation("com.squareup.okhttp3:mockwebserver:4.12.0")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
    implementation("androidx.security:security-crypto:1.1.0-alpha06")
    implementation("org.bouncycastle:bcprov-jdk18on:1.85")

    androidTestImplementation("androidx.test.ext:junit:1.2.1")
    androidTestImplementation("androidx.test:runner:1.6.2")
    androidTestImplementation("androidx.test:rules:1.6.1")
}